pax_global_header00006660000000000000000000000064141452375260014523gustar00rootroot0000000000000052 comment=432ce475efb1fa846518abf98a182ff5fa3bce4c flint2-2.8.4/000077500000000000000000000000001414523752600127345ustar00rootroot00000000000000flint2-2.8.4/.build_dependencies000077500000000000000000000013341414523752600165460ustar00rootroot00000000000000#! /bin/sh mkdir -p local git clone https://github.com/yasm/yasm cd yasm git checkout v1.3.0 ./autogen.sh ./configure ABI=$ABI --prefix=${LOCAL} ${MAKE} > /dev/null 2>&1 ${MAKE} install > /dev/null 2>&1 cd .. wget http://mpir.org/mpir-3.0.0.tar.bz2 tar -xf mpir-3.0.0.tar.bz2 cd mpir-3.0.0 ./configure ABI=$ABI --enable-gmpcompat --prefix=${LOCAL} --with-yasm=${LOCAL}/bin/yasm ${MAKE} > /dev/null 2>&1 ${MAKE} install > /dev/null 2>&1 cd .. wget https://www.mpfr.org/mpfr-4.0.0/mpfr-4.0.0.tar.bz2 tar -xf mpfr-4.0.0.tar.bz2 cd mpfr-4.0.0 ./configure ABI=$ABI --with-gmp=${LOCAL} --prefix=${LOCAL} ${MAKE} > /dev/null 2>&1 ${MAKE} install > /dev/null 2>&1 cd .. echo "int flint_test_multiplier(){return 1;}" > test_helpers.c flint2-2.8.4/.check_post_install000077500000000000000000000007101414523752600166060ustar00rootroot00000000000000#!/bin/sh # script for testing the installation # this has been added to check the post instal hook on osx (Darwin) set -ev mkdir -p tmp cd tmp cat > test.c < ${{ env.SPKG }}-git.tar.gz ) \ && mkdir -p upstream && cp build/pkgs/${{ env.SPKG }}/src/*.tar.gz upstream/${{ env.SPKG }}-git.tar.gz \ && echo "sage-package create ${{ env.SPKG }} --version git --tarball ${{ env.SPKG }}-git.tar.gz --type=standard" > upstream/update-pkgs.sh \ && if [ -n "${{ env.REMOVE_PATCHES }}" ]; then echo "(cd ../build/pkgs/${{ env.SPKG }}/patches && rm -f ${{ env.REMOVE_PATCHES }}; :)" >> upstream/update-pkgs.sh; fi \ && ls -l upstream/ - uses: actions/upload-artifact@v2 with: path: upstream name: upstream cygwin: env: STAGE: i-a LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} MAKE: make -j8 SAGE_NUM_THREADS: 3 SAGE_CHECK: yes SAGE_CHECK_PACKAGES: "!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl" CYGWIN: winsymlinks:native CONFIGURE_ARGS: --enable-experimental-packages --enable-download-from-upstream-url SAGE_FAT_BINARY: yes SAGE_LOCAL: /opt/sage-flint-${{ github.sha }} runs-on: windows-latest needs: [dist] strategy: fail-fast: false matrix: pkgs: [minimal, standard] steps: - run: | git config --global core.autocrlf false git config --global core.symlinks true - name: install cygwin with choco shell: bash {0} run: | choco --version choco install git python3 --source cygwin - name: Check out SageMath uses: actions/checkout@v2 with: repository: ${{ env.SAGE_REPO }} ref: ${{ env.SAGE_REF }} fetch-depth: 2000 if: env.SAGE_REPO != '' - name: Check out git-trac-command uses: actions/checkout@v2 with: repository: sagemath/git-trac-command path: git-trac-command if: env.SAGE_TRAC_GIT != '' - name: Check out SageMath from trac.sagemath.org shell: bash {0} # Random sleep and retry to limit the load on trac.sagemath.org run: | git config --global user.email "ci-sage@example.com" git config --global user.name "ci-sage workflow" if [ ! -d .git ]; then git init; fi; git remote add trac ${{ env.SAGE_TRAC_GIT }} && x=1 && while [ $x -le 5 ]; do x=$(( $x + 1 )); sleep $(( $RANDOM % 60 + 1 )); if git-trac-command/git-trac fetch $SAGE_TICKET; then git merge FETCH_HEAD || echo "(ignored)"; exit 0; fi; sleep 40; done; exit 1 if: env.SAGE_TRAC_GIT != '' - uses: actions/download-artifact@v2 with: path: upstream name: upstream - name: install minimal prerequisites with choco shell: bash {0} run: | choco --version PACKAGES="python38 python38-pip" choco install $PACKAGES --source cygwin - name: Update Sage packages from upstream artifact run: | C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && ls -l upstream/ && export PATH="$(pwd)/build/bin:$PATH:/usr/local/bin:/usr/bin" && (cd upstream && bash -x update-pkgs.sh) && git diff' - name: tox run: | C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' - name: Prepare logs artifact shell: bash run: | mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in local/var/tmp/sage/build/*; do if [ -d $a ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename $a).tar" $a || tar -c --ignore-failed-read -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename $a)-save.tar" $a ; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" if: always() - uses: actions/upload-artifact@v2 with: path: artifacts name: ${{ env.LOGS_ARTIFACT_NAME }} if: always() - name: Print out logs for immediate inspection # The markup in the output is a GitHub Actions logging command # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions shell: bash run: | find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; if: always() - name: Prepare sage-local artifact # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. run: | C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --remove-files "${{ env.SAGE_LOCAL }}"' if: always() - uses: actions/upload-artifact@v2 # upload-artifact@v2 does not support whitespace in file names. # so we tar up the directory ourselves with: path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar name: ${{ env.LOCAL_ARTIFACT_NAME }} if: always() docker: runs-on: ubuntu-latest needs: [dist] strategy: fail-fast: false max-parallel: 32 matrix: tox_system_factor: [ubuntu-trusty, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, ubuntu-impish, debian-jessie, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-17, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, centos-7, centos-8, gentoo, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386, raspbian-buster-armhf] tox_packages_factor: [minimal, standard] env: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} DOCKER_TARGETS: configured with-targets with-targets-optional steps: - name: Check out SageMath uses: actions/checkout@v2 with: repository: ${{ env.SAGE_REPO }} ref: ${{ env.SAGE_REF }} fetch-depth: 2000 if: env.SAGE_REPO != '' - name: Check out git-trac-command uses: actions/checkout@v2 with: repository: sagemath/git-trac-command path: git-trac-command if: env.SAGE_TRAC_GIT != '' - name: Check out SageMath from trac.sagemath.org shell: bash {0} run: | git config --global user.email "ci-sage@example.com" git config --global user.name "ci-sage workflow" if [ ! -d .git ]; then git init; fi; git remote add trac ${{ env.SAGE_TRAC_GIT }} && x=1 && while [ $x -le 5 ]; do x=$(( $x + 1 )); sleep $(( $RANDOM % 60 + 1 )); if git-trac-command/git-trac fetch $SAGE_TICKET; then git merge FETCH_HEAD || echo "(ignored)"; exit 0; fi; sleep 40; done; exit 1 if: env.SAGE_TRAC_GIT != '' - uses: actions/download-artifact@v2 with: path: upstream name: upstream - name: Install test prerequisites run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update sudo DEBIAN_FRONTEND=noninteractive apt-get install tox python3-setuptools - name: Update Sage packages from upstream artifact run: | (export PATH=$(pwd)/build/bin:$PATH; (cd upstream && bash -x update-pkgs.sh) && sed -i.bak '/upstream/d' .dockerignore && echo "/:toolchain:/i ADD upstream upstream" | sed -i.bak -f - build/bin/write-dockerfile.sh && git diff) - name: Configure and build Sage distribution within a Docker container run: | set -o pipefail; EXTRA_DOCKER_BUILD_ARGS="--build-arg USE_MAKEFLAGS=\"-k V=0 SAGE_NUM_THREADS=3\"" tox -e $TOX_ENV -- $TARGETS 2>&1 | sed "/^configure: notice:/s|^|::warning file=artifacts/$LOGS_ARTIFACT_NAME/config.log::|;/^configure: warning:/s|^|::warning file=artifacts/$LOGS_ARTIFACT_NAME/config.log::|;/^configure: error:/s|^|::error file=artifacts/$LOGS_ARTIFACT_NAME/config.log::|;" - name: Copy logs from the Docker image or build container run: | mkdir -p "artifacts/$LOGS_ARTIFACT_NAME" cp -r .tox/$TOX_ENV/Dockerfile .tox/$TOX_ENV/log "artifacts/$LOGS_ARTIFACT_NAME" if [ -f .tox/$TOX_ENV/Dockertags ]; then CONTAINERS=$(docker create $(tail -1 .tox/$TOX_ENV/Dockertags) /bin/bash || true); fi if [ -n "$CONTAINERS" ]; then for CONTAINER in $CONTAINERS; do for ARTIFACT in /sage/logs; do docker cp $CONTAINER:$ARTIFACT artifacts/$LOGS_ARTIFACT_NAME && HAVE_LOG=1; done; if [ -n "$HAVE_LOG" ]; then break; fi; done; fi if: always() - uses: actions/upload-artifact@v2 with: path: artifacts name: ${{ env.LOGS_ARTIFACT_NAME }} if: always() - name: Print out logs for immediate inspection # and markup the output with GitHub Actions logging commands run: | .github/workflows/scan-logs.sh "artifacts/$LOGS_ARTIFACT_NAME" if: always() - name: Push Docker images run: | if [ -f .tox/$TOX_ENV/Dockertags ]; then TOKEN="${{ secrets.DOCKER_PKG_GITHUB_TOKEN }}" if [ -z "$TOKEN" ]; then TOKEN="${{ secrets.GITHUB_TOKEN }}" fi echo "$TOKEN" | docker login docker.pkg.github.com -u ${{ github.actor }} --password-stdin for a in $(cat .tox/$TOX_ENV/Dockertags); do FULL_TAG=docker.pkg.github.com/$(echo ${{ github.repository }}|tr 'A-Z' 'a-z')/$a docker tag $a $FULL_TAG echo Pushing $FULL_TAG docker push $FULL_TAG done || echo "(Ignoring errors)" fi if: always() macos: runs-on: macos-latest strategy: fail-fast: false max-parallel: 4 matrix: os: [ macos-10.15, macos-11.0 ] tox_system_factor: [homebrew-macos, conda-forge-macos] tox_packages_factor: [minimal, standard] xcode_version_factor: [11.7, default] needs: [dist] env: TOX_ENV: local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }}-${{ matrix.os }}-xcode_${{ matrix.xcode_version_factor }} DOCKER_TARGETS: configured with-targets with-targets-optional steps: - name: Select Xcode version run: | if [ ${{ matrix.xcode_version_factor }} != default ]; then sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode_version_factor }}.app; fi - name: Check out SageMath uses: actions/checkout@v2 with: repository: ${{ env.SAGE_REPO }} ref: ${{ env.SAGE_REF }} fetch-depth: 2000 if: env.SAGE_REPO != '' - name: Check out git-trac-command uses: actions/checkout@v2 with: repository: sagemath/git-trac-command path: git-trac-command if: env.SAGE_TRAC_GIT != '' - name: Check out SageMath from trac.sagemath.org shell: bash {0} run: | git config --global user.email "ci-sage@example.com" git config --global user.name "ci-sage workflow" if [ ! -d .git ]; then git init; fi; git remote add trac ${{ env.SAGE_TRAC_GIT }} && x=1 && while [ $x -le 5 ]; do x=$(( $x + 1 )); sleep $(( $RANDOM % 60 + 1 )); if git-trac-command/git-trac fetch $SAGE_TICKET; then git merge FETCH_HEAD || echo "(ignored)"; exit 0; fi; sleep 40; done; exit 1 if: env.SAGE_TRAC_GIT != '' - uses: actions/download-artifact@v2 with: path: upstream name: upstream - name: Update Sage packages from upstream artifact run: | (export PATH=$(pwd)/build/bin:$PATH; (cd upstream && bash -x update-pkgs.sh) && git diff) - name: Install test prerequisites run: | brew install tox - name: Build and test with tox # We use a high parallelization on purpose in order to catch possible parallelization bugs in the build scripts. # For doctesting, we use a lower parallelization to avoid timeouts. run: | MAKE="make -j12" tox -e $TOX_ENV -- SAGE_NUM_THREADS=4 $TARGETS - name: Prepare logs artifact run: | mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; cp -r .tox/*/log "artifacts/$LOGS_ARTIFACT_NAME" if: always() - uses: actions/upload-artifact@v1 with: path: artifacts name: ${{ env.LOGS_ARTIFACT_NAME }} if: always() - name: Print out logs for immediate inspection # and markup the output with GitHub Actions logging commands run: | .github/workflows/scan-logs.sh "artifacts/$LOGS_ARTIFACT_NAME" if: always() flint2-2.8.4/.github/workflows/test_flint.yml000066400000000000000000000022461414523752600212330ustar00rootroot00000000000000name: flint-tests on: [push, pull_request] jobs: ubuntu-gcc: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - run: | sudo apt-get install texinfo ./.build_dependencies ./configure CFLAGS="-Wredundant-decls" --with-mpir=${LOCAL} --with-mpfr=${LOCAL} --prefix=${LOCAL} $MAKE ldd libflint.so $MAKE check env: LOCAL: ${{ github.workspace }}/local LDFLAGS: "-Wl,-rpath,$LOCAL/lib" MAKE: "make -j" ubuntu-cmake-gcc: runs-on: ubuntu-latest env: LOCAL: ${GITHUB_WORKSPACE}/local LDFLAGS: "-Wl,-rpath,$LOCAL/lib" MAKE: "make -j" steps: - uses: actions/checkout@v2 - run: | sudo apt-get install texinfo sudo apt-get install cmake ./.build_dependencies mkdir build cd build cmake -G"Unix Makefiles" -DWITH_NTL=no -DBUILD_TESTING=yes -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$LOCAL .. $MAKE ldd lib/libflint.so env: LOCAL: ${{ github.workspace }}/local LDFLAGS: "-Wl,-rpath,$LOCAL/lib" MAKE: "make -j" flint2-2.8.4/.gitignore000066400000000000000000000011251414523752600147230ustar00rootroot00000000000000*~ *.swp *.orig *.d *.o *.a *.so *.P *.ppm */.deps/* fmpz/fmpz.c build/ flint-config.h config.log fft_tuning.h fmpz-conversions.h /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 flint2-2.8.4/.travis.yml000066400000000000000000000022011414523752600150400ustar00rootroot00000000000000language: c sudo: false cache: ccache addons: apt: packages: - texinfo - cmake env: MAKE="make -j" os: - osx - linux osx_image: xcode10.2 compiler: - gcc - clang install: - export LOCAL=$(pwd)/local - export LDFLAGS="-Wl,-rpath,$LOCAL/lib" - ./.build_dependencies - ./configure CFLAGS="-Wredundant-decls" --with-mpir=${LOCAL} --with-mpfr=${LOCAL} --prefix=${LOCAL} - ${MAKE} - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then otool -L libflint.dylib; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ldd libflint.so; echo "Running cmake build"; mkdir build; cd build; cmake -G"Unix Makefiles" -DWITH_NTL=yes -DBUILD_TESTING=yes -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$LOCAL ..; ${MAKE}; ldd lib/libflint.so; cd ..; fi script: - ${MAKE} check - ${MAKE} install - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then otool -L local/lib/libflint.dylib; fi - PREFIX=$(pwd)/local ./.check_post_install - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then cd build; echo "Running cmake build testing"; ${MAKE} test; cd ..; fi flint2-2.8.4/AUTHORS000066400000000000000000000032221414523752600140030ustar00rootroot00000000000000FLINT 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. We list here just the *main* authors of Flint whose contributions have been in the tens of thousands of lines of code: William Hart -- integer and polynomial arithmetic, factorisation and primality testing, general infrastructure (supported by EPSRC Grant EP/G004870/1, DFG Priority programme SPP1489 and the DFG TRR 195 SFB Grant) Sebastian Pancratz -- polynomial arithmetic over Z, Z/n\Z and Q, p-adic and q-adic arithmetic, including polynomials and matrices (supported by ERC Grant 204083) Andy Novocin -- LLL, polynomial factorisation over Z, polynomial composition Fredrik Johansson -- matrices, polynomial and power series arithmetic, special functions (supported by Austrian Science Fund FWF Grant Y464-N18) Tom Bachmann -- C++ expressions template wrapper, documentation parser (Google Summer of Code 2013) 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 (supported by Macaulay2 developers NSF Grant 1002171) Daniel Schultz -- Multivariate polynomials over Z, Z/nZ, Q and F_q, including parallel implementations. -------- There are a vast number of other contributors who have made major and minor contributions. We attempt to list all of them and their contributions at: http://flintlib.org/authors.html If you believe there are names missing here or there, please contact us immediately on the Flint Google group flint-devel. flint2-2.8.4/CMake/000077500000000000000000000000001414523752600137145ustar00rootroot00000000000000flint2-2.8.4/CMake/FindCBLAS.cmake000066400000000000000000000017551414523752600163530ustar00rootroot00000000000000# 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 ) find_library(CBLAS_LIBRARIES NAMES accelerate openblas cblas blas blis HINTS CBLAS_ROOT ENV CBLAS_ROOT PATHS ${LIB_INSTALL_DIR} ${CMAKE_INSTALL_PREFIX}/lib PATH_SUFFIXES openblas cblas blis ) 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) flint2-2.8.4/CMake/FindGMP.cmake000066400000000000000000000051001414523752600161360ustar00rootroot00000000000000# Try to find the GMP library # https://gmplib.org/ # # This module supports requiring a minimum version, e.g. you can do # find_package(GMP 6.2.1) # to require version 6.2.1 to newer of GMP. # # Once done this will define # # GMP_FOUND - system has GMP lib with correct version # GMP_INCLUDE_DIRS - the GMP include directory # GMP_LIBRARIES - the GMP library # # Set GMP_FIND_VERSION to 6.0.0 if no minimum version is specified if(NOT GMP_FIND_VERSION) if(NOT GMP_FIND_VERSION_MAJOR) set(GMP_FIND_VERSION_MAJOR 6) endif() if(NOT GMP_FIND_VERSION_MINOR) set(GMP_FIND_VERSION_MINOR 0) endif() if(NOT GMP_FIND_VERSION_PATCH) set(GMP_FIND_VERSION_PATCH 0) endif() set(GMP_FIND_VERSION "${GMP_FIND_VERSION_MAJOR}.${GMP_FIND_VERSION_MINOR}.${GMP_FIND_VERSION_PATCH}") endif() find_path(GMP_INCLUDE_DIRS NAMES gmp.h PATHS $ENV{GMPDIR} ${INCLUDE_INSTALL_DIR}) find_library(GMP_LIBRARIES gmp PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR}) if(GMP_INCLUDE_DIRS AND GMP_LIBRARIES) # This program will fail to compile if GMP is too old. # We prefer to perform this "test" at compile-time to # avoid problems with e.g. try_run() during cross-compilation. file(WRITE ${PROJECT_BINARY_DIR}/gmp-version-check.c "" "#include \n" "\n" "#define GMP_FIND_VERSION_MAJOR ${GMP_FIND_VERSION_MAJOR}\n" "#define GMP_FIND_VERSION_MINOR ${GMP_FIND_VERSION_MINOR}\n" "#define GMP_FIND_VERSION_PATCH ${GMP_FIND_VERSION_PATCH}\n" "\n" "#if __GNU_MP_VERSION < GMP_FIND_VERSION_MAJOR\n" "#error insufficient GMP major version\n" "#elif __GNU_MP_VERSION == GMP_FIND_VERSION_MAJOR\n" "#if __GNU_MP_VERSION_MINOR < GMP_FIND_VERSION_MINOR\n" "#error insufficient GMP minor version\n" "#elif __GNU_MP_VERSION_MINOR == GMP_FIND_VERSION_MINOR\n" "#if __GNU_MP_VERSION_PATCH < GMP_FIND_VERSION_PATCH\n" "#error insufficient GMP patch version\n" "#endif\n" "#endif\n" "#endif\n" "\n" "int main(int argc, char** argv) { return 0; }\n") # Try to compile the test program above with the appropriate version # strings substituted in. try_compile(GMP_VERSION_OK "${PROJECT_BINARY_DIR}" "${PROJECT_BINARY_DIR}/gmp-version-check.c" CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${GMP_INCLUDE_DIRS}") endif() if(NOT GMP_VERSION_OK) message(STATUS "No sufficient GMP version detected") endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GMP DEFAULT_MSG GMP_INCLUDE_DIRS GMP_LIBRARIES GMP_VERSION_OK) mark_as_advanced(GMP_INCLUDE_DIRS GMP_LIBRARIES) flint2-2.8.4/CMake/FindMPFR.cmake000066400000000000000000000052041414523752600162640ustar00rootroot00000000000000# Try to find the MPFR library # See https://www.mpfr.org/ # # This module supports requiring a minimum version, e.g. you can do # find_package(MPFR 2.3.0) # to require version 2.3.0 to newer of MPFR. # # Once done this will define # # MPFR_FOUND - system has MPFR lib with correct version # MPFR_INCLUDE_DIRS - the MPFR include directory # MPFR_LIBRARIES - the MPFR library # MPFR_VERSION - MPFR version # Copyright (c) 2006, 2007 Montel Laurent, # Copyright (c) 2008, 2009 Gael Guennebaud, # Copyright (c) 2010 Jitse Niesen, # Copyright (c) 2015 Jack Poulson, # Redistribution and use is allowed according to the terms of the BSD license. find_path(MPFR_INCLUDE_DIRS NAMES mpfr.h PATHS $ENV{GMPDIR} $ENV{MPFRDIR} ${INCLUDE_INSTALL_DIR}) # Set MPFR_FIND_VERSION to 1.0.0 if no minimum version is specified if(NOT MPFR_FIND_VERSION) if(NOT MPFR_FIND_VERSION_MAJOR) set(MPFR_FIND_VERSION_MAJOR 1) endif() if(NOT MPFR_FIND_VERSION_MINOR) set(MPFR_FIND_VERSION_MINOR 0) endif() if(NOT MPFR_FIND_VERSION_PATCH) set(MPFR_FIND_VERSION_PATCH 0) endif() set(MPFR_FIND_VERSION "${MPFR_FIND_VERSION_MAJOR}.${MPFR_FIND_VERSION_MINOR}.${MPFR_FIND_VERSION_PATCH}") endif() if(MPFR_INCLUDE_DIRS) # Query MPFR_VERSION file(READ "${MPFR_INCLUDE_DIRS}/mpfr.h" _mpfr_version_header) string(REGEX MATCH "define[ \t]+MPFR_VERSION_MAJOR[ \t]+([0-9]+)" _mpfr_major_version_match "${_mpfr_version_header}") set(MPFR_MAJOR_VERSION "${CMAKE_MATCH_1}") string(REGEX MATCH "define[ \t]+MPFR_VERSION_MINOR[ \t]+([0-9]+)" _mpfr_minor_version_match "${_mpfr_version_header}") set(MPFR_MINOR_VERSION "${CMAKE_MATCH_1}") string(REGEX MATCH "define[ \t]+MPFR_VERSION_PATCHLEVEL[ \t]+([0-9]+)" _mpfr_patchlevel_version_match "${_mpfr_version_header}") set(MPFR_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") set(MPFR_VERSION ${MPFR_MAJOR_VERSION}.${MPFR_MINOR_VERSION}.${MPFR_PATCHLEVEL_VERSION}) # Check whether found version exceeds minimum required if(${MPFR_VERSION} VERSION_LESS ${MPFR_FIND_VERSION}) set(MPFR_VERSION_OK FALSE) message(STATUS "MPFR version ${MPFR_VERSION} found in ${MPFR_INCLUDE_DIRS}, " "but at least version ${MPFR_FIND_VERSION} is required") else() set(MPFR_VERSION_OK TRUE) endif() endif() find_library(MPFR_LIBRARIES mpfr PATHS $ENV{GMPDIR} $ENV{MPFRDIR} ${LIB_INSTALL_DIR}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(MPFR DEFAULT_MSG MPFR_INCLUDE_DIRS MPFR_LIBRARIES MPFR_VERSION_OK) mark_as_advanced(MPFR_INCLUDE_DIRS MPFR_LIBRARIES)flint2-2.8.4/CMake/FindNTL.cmake000066400000000000000000000011431414523752600161530ustar00rootroot00000000000000# 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) flint2-2.8.4/CMake/FindPThreads.cmake000066400000000000000000000012401414523752600172260ustar00rootroot00000000000000# Try to find the PThreads librairies # 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)flint2-2.8.4/CMake/FindSphinx.cmake000066400000000000000000000022771414523752600170000ustar00rootroot00000000000000# - 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()flint2-2.8.4/CMake/README000066400000000000000000000021371414523752600145770ustar00rootroot00000000000000Quick cmake configuring/building/testing instuctions 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 realease 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/ flint2-2.8.4/CMakeLists.txt000066400000000000000000000252761414523752600155100ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.9) include(CheckIPOSupported) include(CheckIncludeFiles) include(CheckFunctionExists) include(CheckPrototypeDefinition) include(CheckCCompilerFlag) include(CheckCSourceRuns) include(CheckLibraryExists) include(TestBigEndian) project(flint LANGUAGES C CXX) 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() option(BUILD_SHARED_LIBS "Build shared libs" on) option(WITH_NTL "Build with NTL or not" off) file(READ "${CMAKE_CURRENT_SOURCE_DIR}/configure" CONFIGURE_CONTENTS) string(REGEX MATCH "FLINT_MAJOR=([0-9]*)" _ ${CONFIGURE_CONTENTS}) set(FLINT_MAJOR ${CMAKE_MATCH_1}) string(REGEX MATCH "FLINT_MINOR=([0-9]*)" _ ${CONFIGURE_CONTENTS}) set(FLINT_MINOR ${CMAKE_MATCH_1}) string(REGEX MATCH "FLINT_PATCH=([0-9]*)" _ ${CONFIGURE_CONTENTS}) set(FLINT_PATCH ${CMAKE_MATCH_1}) find_package(GMP REQUIRED) find_package(MPFR REQUIRED) if (WITH_NTL) find_package(NTL REQUIRED) endif() find_package(PythonInterp 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) find_package(PThreads REQUIRED) 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() # Find sources set(BUILD_DIRS aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_poly fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_poly nmod_poly_factor arith mpn_extras nmod_mat fmpq fmpq_vec fmpq_mat padic fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly fmpz_mod_mat fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve double_extras d_vec d_mat padic_poly padic_mat qadic fq fq_vec fq_mat fq_poly fq_poly_factor fq_nmod fq_nmod_vec fq_nmod_mat fq_nmod_poly fq_nmod_poly_factor fq_zech fq_zech_vec fq_zech_mat fq_zech_poly fq_zech_poly_factor fq_default fq_default_mat fq_default_poly fq_default_poly_factor thread_pool fmpz_mod fmpz_mod_vec n_poly mpoly fmpz_mpoly fmpq_mpoly nmod_mpoly fq_nmod_mpoly fmpz_mod_mpoly fmpz_mpoly_factor fmpq_mpoly_factor nmod_mpoly_factor fmpz_mod_mpoly_factor fq_nmod_mpoly_factor fq_zech_mpoly fq_zech_mpoly_factor flintxx ) set(TEMPLATE_DIRS fq_vec_templates fq_mat_templates fq_poly_templates fq_poly_factor_templates fq_templates ) set(SOURCES printf.c fprintf.c sprintf.c scanf.c fscanf.c sscanf.c clz_tab.c memory_manager.c version.c profiler.c thread_support.c exception.c hashmap.c inlines.c fmpz/fmpz.c ) if (MSVC) list(APPEND SOURCES gettimeofday.c) endif() if (WITH_NTL) list(APPEND SOURCES interfaces/NTL-interface.cpp) endif() set(HEADERS NTL-interface.h flint.h longlong.h flint-config.h gmpcompat.h fft_tuning.h fmpz-conversions.h profiler.h templates.h exception.h hashmap.h ) foreach (build_dir IN LISTS BUILD_DIRS TEMPLATE_DIRS) file(GLOB TEMP RELATIVE "${CMAKE_SOURCE_DIR}" "${build_dir}/*.c") list(APPEND SOURCES ${TEMP}) file(GLOB TEMP RELATIVE "${CMAKE_SOURCE_DIR}" "${build_dir}/*.h") list(APPEND HEADERS ${TEMP}) endforeach () execute_process( COMMAND ${PYTHON_EXECUTABLE} -c " from os.path import join with open(join('${CMAKE_SOURCE_DIR}','qadic', 'CPimport.txt')) as fin: with open('CPimport.h.in', 'w+') as fout: while True: l = fin.readline() if not l: break l = l.replace(' ', ',') l = l.replace('\\n', ',\\n') fout.writelines([l]) " WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) configure_file(${CMAKE_BINARY_DIR}/CPimport.h.in ${CMAKE_BINARY_DIR}/CPimport.h COPYONLY) # Setup for flint-config.h check_c_compiler_flag("-mpopcnt" HAS_FLAG_MPOPCNT) check_c_compiler_flag("-funroll-loops" HAS_FLAG_UNROLL_LOOPS) if(HAS_FLAG_MPOPCNT) set(CMAKE_REQUIRED_FLAGS "-mpopcnt") endif() # Testing __builtin_popcountl... check_c_source_runs([[int main(int argc, char ** argv) { #if defined(_WIN64) return __builtin_popcountll(argc) == 100; #else return __builtin_popcountl(argc) == 100; #endif }]] FLINT_USES_POPCNT) unset(CMAKE_REQUIRED_FLAGS) # 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 if(cxx_thread_local IN_LIST CMAKE_CXX_COMPILE_FEATURES) set(FLINT_USES_TLS ON CACHE BOOL "Use thread local storage.") endif() # Memory manager configuration set(MEMORY_MANAGER "reentrant" 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() # Populate headers configure_file( config.h.in flint-config.h ) configure_file( fmpz-conversions-${MEMORY_MANAGER}.in fmpz-conversions.h COPYONLY ) configure_file( fmpz/link/fmpz_${MEMORY_MANAGER}.c fmpz/fmpz.c COPYONLY ) if(CMAKE_SIZEOF_VOID_P EQUAL 8) configure_file( fft_tuning64.in fft_tuning.h COPYONLY ) elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) configure_file( fft_tuning32.in fft_tuning.h COPYONLY ) endif() set(TEMP ${HEADERS}) set(HEADERS ) foreach(header IN LISTS TEMP) if(EXISTS ${CMAKE_SOURCE_DIR}/${header}) list(APPEND HEADERS ${header}) else() list(APPEND HEADERS ${CMAKE_BINARY_DIR}/${header}) endif() endforeach() file(GLOB TEMP "${CMAKE_SOURCE_DIR}/*.h") list(APPEND HEADERS ${TEMP}) add_library(flint ${SOURCES}) target_link_libraries(flint PUBLIC ${NTL_LIBRARY} ${MPFR_LIBRARIES} ${GMP_LIBRARIES} ${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} ${GMP_INCLUDE_DIRS} ${MPFR_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} ${PThreads_INCLUDE_DIRS} ${NTL_INCLUDE_DIR} ) if(FLINT_USES_BLAS) target_include_directories(flint PUBLIC ${CBLAS_INCLUDE_DIRS}) endif() if(BUILD_SHARED_LIBS AND WIN32) # Export flint's functions target_compile_definitions(flint PRIVATE "FLINT_BUILD_DLL") # Use MPIR's dll import functions target_compile_definitions(flint PUBLIC "MSC_USE_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() # Versioning set_target_properties(flint PROPERTIES VERSION ${FLINT_MAJOR}.${FLINT_MINOR}.${FLINT_PATCH} SOVERSION ${FLINT_MAJOR} ) # 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}.${FLINT_MINOR} MACHO_CURRENT_VERSION ${FLINT_MAJOR}.${FLINT_MINOR}.${FLINT_PATCH} ) endif() elseif (WIN32) set_target_properties(flint PROPERTIES RUNTIME_OUTPUT_NAME "flint-${FLINT_MAJOR}") endif() if(NOT DEFINED IPO_SUPPORTED) message(STATUS "Checking for IPO") check_ipo_supported(RESULT ipo_supported LANGUAGES C) if(ipo_supported) message(STATUS "Checking for IPO - found") else() message(STATUS "Checking for IPO - not found") endif() set(IPO_SUPPORTED ${ipo_supported} CACHE INTERNAL "Introprocedural Optimization" FORCE) endif() if(IPO_SUPPORTED) 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_BINARY_DIR}/lib" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" ) if(BUILD_TESTING) enable_testing() add_library(test_helpers STATIC test_helpers.c) target_link_libraries(test_helpers flint) foreach (build_dir IN LISTS BUILD_DIRS CMAKE_SOURCE_DIR) file(GLOB TEST_FILES "${build_dir}/test/*.c") foreach(test_file IN LISTS TEST_FILES) file(RELATIVE_PATH test_name ${CMAKE_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 test_helpers ) add_test( NAME ${test_name} COMMAND $ ) set_target_properties(${test_name} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" ) endforeach() endforeach () 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_SOURCE_DIR}/doc/source" "${CMAKE_BINARY_DIR}/html" SOURCES ${DOC_SOURCES}) add_custom_target(latex COMMAND ${SPHINX_EXECUTABLE} -b latex "${CMAKE_SOURCE_DIR}/doc/source" "${CMAKE_BINARY_DIR}/latex" SOURCES ${DOC_SOURCES}) add_custom_target(pdf DEPENDS latex COMMAND make WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/latex") endif() flint2-2.8.4/INSTALL000066400000000000000000000023271414523752600137710ustar00rootroot00000000000000Instructions on installing flint 2 ---------------------------------- FLINT 2 follows a standard format for installation: ./configure make make check make install However, this assumes that MPIR and MPFR are already installed in the default search path of your compiler (e.g. /usr/include/ and /usr/lib/). If these libraries are not in such location you must specify where they are by passing their location to configure `--with-mpir=ABSOLUTE_PATH` for MPIR and `--with-mpfr=ABSOLUTE_PATH` for MPFR. The configure script also assumes you wish to install FLINT 2 at the prefix /usr/local. If not you must pass the prefix (the directory containing lib and include subdirectories into which FLINT will be installed) to configure with the option `--prefix=PATH`. A complete example of a custom configuration command would be ./configure --with-mpir=/home/user1/mpir-2.1.1/ --with-mpfr=/usr --prefix=/usr Note that the FLINT configure system can handle MPIR/MPFR as installed (in lib and include dirs) at some location, or as source builds (built from source and not installed). Though, to run the FLINT tests, MPIR/MPFR needs to be properly installed. For further configure and make options, please refer to the FLINT 2 documentation. flint2-2.8.4/LICENSE000066400000000000000000000636421414523752600137540ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. 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 not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the 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 specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey 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 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. This 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 this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! flint2-2.8.4/Makefile.in000066400000000000000000000364661414523752600150200ustar00rootroot00000000000000LIBDIR=lib QUIET_CC = @echo ' ' CC ' ' $@; QUIET_CXX = @echo ' ' CXX ' ' $@; QUIET_AR = @echo ' ' AR ' ' $@; AT=@ BUILD_DIRS = aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_poly \ fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_poly \ nmod_poly_factor arith mpn_extras nmod_mat fmpq fmpq_vec fmpq_mat padic \ fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly \ fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve \ double_extras d_vec d_mat padic_poly padic_mat qadic \ fq fq_vec fq_mat fq_poly fq_poly_factor fq_embed \ fq_nmod fq_nmod_vec fq_nmod_mat fq_nmod_poly fq_nmod_poly_factor fq_nmod_embed \ fq_zech fq_zech_vec fq_zech_mat fq_zech_poly fq_zech_poly_factor fq_zech_embed \ fmpz_mod_mat mpoly fmpz_mpoly fmpq_mpoly nmod_mpoly fq_nmod_mpoly \ thread_pool fmpz_mod fmpz_mod_vec fmpz_mod_mpoly fmpz_mod_mpoly_factor \ n_poly fmpz_mpoly_factor fmpq_mpoly_factor nmod_mpoly_factor \ fq_nmod_mpoly_factor fq_zech_mpoly fq_zech_mpoly_factor fq_default \ fq_default_poly fq_default_poly_factor fq_default_mat \ $(EXTRA_BUILD_DIRS) TEMPLATE_DIRS = fq_vec_templates fq_mat_templates fq_poly_templates \ fq_poly_factor_templates fq_embed_templates fq_templates export SOURCES = printf.c fprintf.c sprintf.c scanf.c fscanf.c sscanf.c clz_tab.c memory_manager.c version.c profiler.c thread_support.c exception.c hashmap.c inlines.c LIB_SOURCES = $(wildcard $(patsubst %, %/*.c, $(BUILD_DIRS))) $(patsubst %, %/*.c, $(TEMPLATE_DIRS)) HEADERS = $(patsubst %, %.h, $(BUILD_DIRS)) NTL-interface.h flint.h longlong.h flint-config.h gmpcompat.h fft_tuning.h fmpz-conversions.h profiler.h templates.h exception.h hashmap.h thread_support.h $(patsubst %, %.h, $(TEMPLATE_DIRS)) OBJS = $(patsubst %.c, build/%.o, $(SOURCES)) LIB_OBJS = $(patsubst %, build/%/*.o, $(BUILD_DIRS)) LOBJS = $(patsubst %.c, build/%.lo, $(SOURCES)) LIB_LOBJS = $(patsubst %, build/%/*.lo, $(BUILD_DIRS)) MOD_LOBJS = $(patsubst %, build/%.lo, $(BUILD_DIRS)) EXMP_SOURCES = $(wildcard examples/*.c) EXMPS = $(patsubst %.c, %, $(EXMP_SOURCES)) TEST_SOURCES = $(wildcard test/*.c) TESTS = $(patsubst %.c, build/%$(EXEEXT), $(TEST_SOURCES)) PROF_SOURCES = $(wildcard profile/*.c) PROFS = $(patsubst %.c, %$(EXEEXT), $(PROF_SOURCES)) TUNE_SOURCES = $(wildcard tune/*.c) TUNE = $(patsubst %.c, %$(EXEEXT), $(TUNE_SOURCES)) EXT_SOURCES = $(foreach ext, $(EXTENSIONS), $(foreach dir, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h)), $(wildcard $(ext)/$(dir)/*.c))) EXT_TEST_SOURCES = $(foreach ext, $(EXTENSIONS), $(foreach dir, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h)), $(wildcard $(ext)/$(dir)/test/t-*.c))) EXT_TUNE_SOURCES = $(foreach ext, $(EXTENSIONS), $(foreach dir, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h)), $(wildcard $(ext)/$(dir)/tune/*.c))) EXT_PROF_SOURCES = $(foreach ext, $(EXTENSIONS), $(foreach dir, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h)), $(wildcard $(ext)/$(dir)/profile/p-*.c))) EXT_OBJS = $(foreach ext, $(EXTENSIONS), $(foreach dir, $(filter-out %templates, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h))), build/$(dir).lo)) EXT_HEADERS = $(foreach ext, $(EXTENSIONS), $(wildcard $(ext)/*.h)) EXT_EXMP_SOURCES = $(foreach ext, $(EXTENSIONS), $(wildcard $(ext)/examples/*.c)) all: library quiet: library verbose: $(eval VERBOSE := 1) $(MAKE) AT= QUIET_CC= QUIET_CXX= QUIET_AR= clean: $(AT)$(foreach dir, $(BUILD_DIRS), WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=../build/$(dir); export BUILD_DIR; MOD_DIR=$(dir); export MOD_DIR; $(MAKE) -f ../Makefile.subdirs -C $(dir) clean || exit $$?;) $(AT)$(foreach ext, $(EXTENSIONS), $(foreach dir, $(filter-out %templates, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h))), BUILD_DIR=$(CURDIR)/build/$(dir); WANTDEPS=$(WANT_DEPS); export WANTDEPS; export BUILD_DIR; MOD_DIR=$(dir); export MOD_DIR; $(MAKE) -f $(CURDIR)/Makefile.subdirs -C $(ext)/$(dir) clean || exit $$?;)) rm -rf test_helpers.o profiler.o rm -f $(OBJS) $(LOBJS) $(TESTS) $(PROFS) $(EXMPS) rm -f libflint.a rm -f $(wildcard $(FLINT_LIBNAME)*) rm -f $(wildcard $(FLINT_LIB)*) rm -rf build distclean: clean rm -f flint-config.h config.log fft_tuning.h fmpz-conversions.h Makefile fmpz/fmpz.c dist: git archive --format tar --prefix flint-2.8.4/ origin/flint-2.8 > ../flint-2.8.4.tar; gzip ../flint-2.8.4.tar git archive --format zip --prefix flint-2.8.4/ origin/flint-2.8 > ../flint-2.8.4.zip profile: library $(PROF_SOURCES) $(EXT_PROF_SOURCES) build/profiler.o mkdir -p build/profile ifndef MOD $(AT)$(foreach prog, $(PROFS), $(CC) $(CFLAGS) -std=gnu99 $(INCS) $(prog).c build/profiler.o -o build/$(prog) $(LIBS) || exit $$?;) $(AT)$(foreach dir, $(BUILD_DIRS), mkdir -p build/$(dir)/profile; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=../build/$(dir); export BUILD_DIR; $(MAKE) -f ../Makefile.subdirs -C $(dir) profile || exit $$?;) $(AT)$(foreach ext, $(EXTENSIONS), $(foreach dir, $(filter-out %templates, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h))), mkdir -p build/$(dir)/profile; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=$(CURDIR)/build/$(dir); export BUILD_DIR; MOD_DIR=$(dir); export MOD_DIR; $(MAKE) -f $(CURDIR)/Makefile.subdirs -C $(ext)/$(dir) profile || exit $$?;)) else $(AT)$(foreach dir, $(MOD), mkdir -p build/$(dir)/profile; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=../build/$(dir); export BUILD_DIR; $(MAKE) -f ../Makefile.subdirs -C $(dir) profile || exit $$?;) endif tune: library $(TUNE_SOURCES) $(EXT_TUNE_SOURCES) mkdir -p build/tune $(AT)$(foreach prog, $(TUNE), $(CC) $(CFLAGS) $(INCS) $(prog).c -o build/$(prog) $(LIBS) || exit $$?;) $(AT)$(foreach dir, $(BUILD_DIRS), mkdir -p build/$(dir)/tune; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=../build/$(dir); export BUILD_DIR; $(MAKE) -f ../Makefile.subdirs -C $(dir) tune || exit $$?;) $(AT)$(foreach ext, $(EXTENSIONS), $(foreach dir, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h)), mkdir -p build/$(dir)/tune; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=$(CURDIR)/build/$(dir); export BUILD_DIR; MOD_DIR=$(dir); export MOD_DIR; $(MAKE) -f $(CURDIR)/Makefile.subdirs -C $(ext)/$(dir) tune || exit $$?;)) examples: library $(EXMP_SOURCES) $(EXT_EXMP_SOURCES) $(EXT_HEADERS) mkdir -p build/examples $(AT)$(foreach prog, $(EXMPS), $(CC) $(CFLAGS) $(INCS) $(prog).c -o build/$(prog) $(LIBS) || exit $$?;) $(AT)$(foreach ext, $(EXTENSIONS), $(foreach prog, $(patsubst $(ext)/examples/%.c, %, $(wildcard $(ext)/examples/*.c)), $(CC) $(CFLAGS) $(INCS) $(ext)/examples/$(prog).c -o build/examples/$(prog) $(LIBS) || exit $$?;)) $(FLINT_LIB): $(LOBJS) $(LIB_SOURCES) $(EXT_SOURCES) $(HEADERS) $(EXT_HEADERS) | build build/interfaces $(AT)$(foreach ext, $(EXTENSIONS), $(foreach dir, $(filter-out %templates, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h))), mkdir -p build/$(dir); WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=$(CURDIR)/build/$(dir); export BUILD_DIR; MOD_DIR=$(dir); export MOD_DIR; $(MAKE) -f $(CURDIR)/Makefile.subdirs -C $(ext)/$(dir) shared || exit $$?;)) $(AT)$(foreach dir, $(BUILD_DIRS), mkdir -p build/$(dir); WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=../build/$(dir); export BUILD_DIR; MOD_DIR=$(dir); export MOD_DIR; $(MAKE) -f ../Makefile.subdirs -C $(dir) shared || exit $$?;) $(AT)if [ "$(WANT_NTL)" -eq "1" ]; then \ $(MAKE) build/interfaces/NTL-interface.lo; \ $(CXX) $(CXXFLAGS) $(ABI_FLAG) -shared $(EXTRA_SHARED_FLAGS) build/interfaces/NTL-interface.lo $(LOBJS) $(MOD_LOBJS) $(EXT_OBJS) -o $(FLINT_LIB) $(LDFLAGS) $(LIBS2); \ fi $(AT)if [ "$(WANT_NTL)" -ne "1" ]; then \ $(CC) $(CFLAGS) $(ABI_FLAG) -shared $(EXTRA_SHARED_FLAGS) $(LOBJS) $(MOD_LOBJS) $(EXT_OBJS) -o $(FLINT_LIB) $(LDFLAGS) $(LIBS2); \ fi -$(AT)if [ "$(FLINT_SOLIB)" -eq "1" ]; then \ $(LDCONFIG) -n "$(CURDIR)"; \ fi ln -sf "$(FLINT_LIB)" "$(FLINT_LIBNAME)"; \ ln -sf "$(FLINT_LIB)" "$(FLINT_LIBNAME).$(FLINT_MAJOR)"; \ libflint.a: $(OBJS) $(LIB_SOURCES) $(EXT_SOURCES) $(HEADERS) $(EXT_HEADERS) | build build/interfaces $(AT)$(foreach ext, $(EXTENSIONS), $(foreach dir, $(filter-out %templates, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h))), mkdir -p build/$(dir); WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=$(CURDIR)/build/$(dir); export BUILD_DIR; MOD_DIR=$(dir); export MOD_DIR; $(MAKE) -f $(CURDIR)/Makefile.subdirs -C $(ext)/$(dir) static || exit $$?;)) $(AT)$(foreach dir, $(BUILD_DIRS), mkdir -p build/$(dir); WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=../build/$(dir); export BUILD_DIR; MOD_DIR=$(dir); export MOD_DIR; $(MAKE) -f ../Makefile.subdirs -C $(dir) static || exit $$?;) $(AT)if [ "$(FLINT_SHARED)" -eq "0" ]; then \ touch test/t-*.c; \ $(foreach dir, $(BUILD_DIRS), touch $(dir)/test/t-*.c;) \ $(foreach ext, $(EXTENSIONS), $(foreach mod, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h)), touch $(ext)/$(mod)/test/t-*.c;)) \ fi $(AT)if [ "$(WANT_NTL)" -eq "1" ]; then \ $(MAKE) build/interfaces/NTL-interface.o; \ $(AR) rcs libflint.a build/interfaces/NTL-interface.o; \ fi $(QUIET_AR) $(AR) rcs libflint.a $(OBJS); $(AT)$(foreach mod, $(BUILD_DIRS), $(AR) rcs libflint.a build/$(mod)/*.o || exit $$?;) $(AT)$(foreach ext, $(EXTENSIONS), $(foreach mod, $(filter-out %templates, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h))), $(AR) rcs libflint.a build/$(mod)/*.o || exit $$?;)) library: build/CPimport.h $(AT)if [ "$(FLINT_SHARED)" -eq "1" ]; then \ $(MAKE) shared; \ fi $(AT)if [ "$(FLINT_STATIC)" -eq "1" ]; then \ $(MAKE) static; \ fi shared: $(FLINT_LIB) static: libflint.a tests: library test_helpers.o $(TESTS) $(AT)$(foreach dir, $(BUILD_DIRS), mkdir -p build/$(dir)/test; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=../build/$(dir); export BUILD_DIR; $(MAKE) -f ../Makefile.subdirs -C $(dir) tests || exit $$?;) $(AT)$(foreach ext, $(EXTENSIONS), $(foreach dir, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h)), mkdir -p build/$(dir)/test; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=$(CURDIR)/build/$(dir); export BUILD_DIR; MOD_DIR=$(dir); export MOD_DIR; $(MAKE) -f $(CURDIR)/Makefile.subdirs -C $(ext)/$(dir) tests || exit $$?;)) mkdir -p build/interfaces/test $(AT)if [ "$(WANT_NTL)" -eq "1" ]; then \ $(MAKE) build/interfaces/test/t-NTL-interface$(EXEEXT); \ fi define test_mod $(eval vl := $(subst :, ,$(1))) $(eval dir := $(firstword $(vl))) $(eval uset_tests :=$(wordlist 2,$(words $(vl)),$(vl))) $(eval USER_SET_TESTS_VAR := USER_SET_TESTS=$(uset_tests)) $(AT)test ! -d $(dir) || mkdir -p build/$(dir)/test; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=../build/$(dir); export BUILD_DIR; test ! -d $(dir) || $(MAKE) $(USER_SET_TESTS_VAR) -f ../Makefile.subdirs -C $(dir) check endef define test_mod_ext $(eval vl := $(subst :, ,$(1))) $(eval ext := $(2)) $(eval dir := $(firstword $(vl))) $(eval uset_tests :=$(wordlist 2,$(words $(vl)),$(vl))) $(eval USER_SET_TESTS_VAR := USER_SET_TESTS=$(uset_tests)) $(AT)MOD_DIR=$(dir); export MOD_DIR; test ! -d $(ext)/$(dir) || mkdir -p build/$(dir)/test; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=$(CURDIR)/build/$(dir); export BUILD_DIR; test ! -d $(ext)/$(dir) || $(MAKE) $(USER_SET_TESTS_VAR) -f $(CURDIR)/Makefile.subdirs -C $(ext)/$(dir) check endef check: LDFLAGS:=$(LDFLAGS) -Wl,-rpath,$(GMP_LIB_DIR) -Wl,-rpath,$(MPFR_LIB_DIR) -Wl,-rpath,$(CURDIR) check: library test_helpers.o ifndef MOD $(AT)$(MAKE) $(TESTS) $(AT)(WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=build; export BUILD_DIR; $(MAKE) -f Makefile.subdirs -C . check || exit $$?;) $(AT)$(foreach ext, $(EXTENSIONS), $(foreach dir, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h)), mkdir -p build/$(dir)/test; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=$(CURDIR)/build/$(dir); export BUILD_DIR; MOD_DIR=$(dir); export MOD_DIR; $(MAKE) -f $(CURDIR)/Makefile.subdirs -C $(ext)/$(dir) check || exit $$?;)) $(AT)$(foreach dir, $(BUILD_DIRS), mkdir -p build/$(dir)/test; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=../build/$(dir); export BUILD_DIR; $(MAKE) -f ../Makefile.subdirs -C $(dir) check || exit $$?;) mkdir -p build/interfaces/test $(AT)if [ "$(WANT_NTL)" -eq "1" ]; then \ $(MAKE) build/interfaces/test/t-NTL-interface$(EXEEXT); \ build/interfaces/test/t-NTL-interface$(EXEEXT); \ fi else $(AT)$(foreach mod, $(MOD), $(call test_mod,$(mod)) || exit $$?;) $(AT)$(foreach ext, $(EXTENSIONS), $(foreach mod, $(MOD), $(call test_mod_ext,$(mod),$(ext)) || exit $$?;)) endif valgrind: library ifndef MOD $(AT)$(foreach dir, $(BUILD_DIRS), mkdir -p build/$(dir)/test; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=../build/$(dir); export BUILD_DIR; $(MAKE) -f ../Makefile.subdirs -C $(dir) valgrind || exit $$?;) $(AT)$(foreach ext, $(EXTENSIONS), $(foreach dir, $(patsubst $(ext)/%.h, %, $(wildcard $(ext)/*.h)), mkdir -p build/$(dir)/test; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=$(CURDIR)/build/$(dir); export BUILD_DIR; MOD_DIR=$(dir); export MOD_DIR; $(MAKE) -f $(CURDIR)/Makefile.subdirs -C $(ext)/$(dir) valgrind || exit $$?;)) else $(AT)$(foreach dir, $(MOD), mkdir -p build/$(dir)/test; WANTDEPS=$(WANT_DEPS); export WANTDEPS; BUILD_DIR=../build/$(dir); export BUILD_DIR; $(MAKE) -f ../Makefile.subdirs -C $(dir) valgrind || exit $$?;) endif install: library mkdir -p "$(DESTDIR)$(PREFIX)/$(LIBDIR)" mkdir -p "$(DESTDIR)$(PREFIX)/include/flint" $(AT)if [ "$(FLINT_SHARED)" -eq "1" ]; then \ cp $(FLINT_LIB) "$(DESTDIR)$(PREFIX)/$(LIBDIR)"; \ cp -a $(shell ls $(FLINT_LIBNAME)*) "$(DESTDIR)$(PREFIX)/$(LIBDIR)"; \ fi $(AT)if [ "$(FLINT_STATIC)" -eq "1" ]; then \ cp libflint.a "$(DESTDIR)$(PREFIX)/$(LIBDIR)"; \ fi cp $(HEADERS) "$(DESTDIR)$(PREFIX)/include/flint" $(AT)if [ ! -z "$(EXT_HEADERS)" ]; then \ cp $(EXT_HEADERS) "$(DESTDIR)$(PREFIX)/include/flint"; \ fi mkdir -p "$(DESTDIR)$(PREFIX)/include/flint/flintxx" cp flintxx/*.h "$(DESTDIR)$(PREFIX)/include/flint/flintxx" cp *xx.h "$(DESTDIR)$(PREFIX)/include/flint" $(AT)if [ "$(OS)" = "Darwin" ] && [ "$(FLINT_SHARED)" -eq "1" ]; then \ install_name_tool -id "$(PREFIX)/$(LIBDIR)/$(FLINT_LIB)" "$(DESTDIR)$(PREFIX)/$(LIBDIR)/$(FLINT_LIBNAME)"; \ fi uninstall: rm -rf "$(DESTDIR)$(PREFIX)/include/flint" rm -rf "$(DESTDIR)$(PREFIX)/$(LIBDIR)/$(FLINT_LIB)" rm -rf $(shell ls $(DESTDIR)$(PREFIX)/$(LIBDIR)/$(FLINT_LIBNAME)*) rm -rf "$(DESTDIR)$(PREFIX)/$(LIBDIR)/libflint.a" build: mkdir -p build build/CPimport.h: qadic/CPimport.txt build $(AT)sed "s/ /,/g;s/.*/&,/g" $< > $@ build/%.lo: %.c $(HEADERS) | build $(QUIET_CC) $(CC) $(PIC_FLAG) $(CFLAGS) $(INCS) -c $< -o $@; build/%.o: %.c $(HEADERS) | build $(QUIET_CC) $(CC) $(CFLAGS) $(INCS) -c $< -o $@; build/test/%$(EXEEXT): test/%.c $(HEADERS) test_helpers.o | build/test $(QUIET_CC) $(CC) $(CFLAGS) $(INCS) test_helpers.o $< -o $@ $(LIBS) $(LDFLAGS) build/test: mkdir -p build/test build/interfaces: mkdir -p build/interfaces build/interfaces/NTL-interface.lo: interfaces/NTL-interface.cpp NTL-interface.h $(QUIET_CXX) $(CXX) $(PIC_FLAG) $(CXXFLAGS) $(INCS) -c $< -o $@ build/interfaces/NTL-interface.o: interfaces/NTL-interface.cpp NTL-interface.h $(QUIET_CXX) $(CXX) $(CXXFLAGS) $(INCS) -c $< -o $@ build/interfaces/test/t-NTL-interface$(EXEEXT): interfaces/test/t-NTL-interface.cpp build/interfaces/NTL-interface.o $(QUIET_CXX) $(CXX) $(CXXFLAGS) $(INCS) $< build/interfaces/NTL-interface.o -o $@ $(LIBS) $(LDFLAGS) print-%: @echo '$*=$($*)' test_helpers.o: test_helpers.c $(QUIET_CC) $(CC) $(CFLAGS) $(INCS) -c test_helpers.c -o test_helpers.o .PHONY: profile library shared static clean examples tune check tests distclean dist install all valgrind flint2-2.8.4/Makefile.subdirs000066400000000000000000000057601414523752600160560ustar00rootroot00000000000000ifeq ($(strip $(VERBOSE)),) QUIET_CC = @echo ' ' CC ' ' $@; QUIET_CXX = @echo ' ' CXX ' ' $@; else QUIET_CC = QUIET_CXX = endif ifeq ($(WANTDEPS), 1) DEPFLAGS1 = -MMD -MP -MF $@.d -MT "$@" -MT "$@.d"; DEPFLAGS2 = -MMD -MP -MF "$(BUILD_DIR)/$(MOD_DIR)_$*.d" -MT "$(BUILD_DIR)/$(MOD_DIR)_$*.d" -MT "$@"; DEPFLAGS3 = -MMD -MP -MF "$(BUILD_DIR)/$*.d" -MT "$(BUILD_DIR)/$*.d" -MT "$@"; else DEPFLAGS1 = DEPFLAGS2 = DEPFLAGS3 = endif AT=@ comma=, SOURCES = $(wildcard *.c) HEADERS = $(wildcard ../*.h) TEST_HEADERS = $(wildcard *.h) OBJS = $(patsubst %.c, $(BUILD_DIR)/$(MOD_DIR)_%.o, $(SOURCES)) LOBJS = $(patsubst %.c, $(BUILD_DIR)/%.lo, $(SOURCES)) MOD_LOBJ = $(BUILD_DIR)/../$(MOD_DIR).lo ifndef USER_SET_TESTS TEST_SOURCES = $(wildcard test/*.c) TESTXX_SOURCES = $(wildcard test/*.cpp) else TL = $(subst $(comma), ,$(USER_SET_TESTS)) TEST_SOURCES = $(foreach test, $(TL), $(wildcard test/t-$(test).c)) TESTXX_SOURCES = $(foreach test, $(TL), $(wildcard test/t-$(test).cpp)) endif PROF_SOURCES = $(wildcard profile/*.c) TUNE_SOURCES = $(wildcard tune/*.c) TESTS = $(patsubst %.c, $(BUILD_DIR)/%$(EXEEXT), $(TEST_SOURCES)) \ $(patsubst %.cpp, $(BUILD_DIR)/%$(EXEEXT), $(TESTXX_SOURCES)) TESTS_RUN = $(patsubst %, %_RUN, $(TESTS)) VALGRIND_RUN = $(patsubst %, %_VALGRIND_RUN, $(TESTS)) PROFS = $(patsubst %.c, $(BUILD_DIR)/%$(EXEEXT), $(PROF_SOURCES)) TUNE = $(patsubst %.c, %$(EXEEXT), $(TUNE_SOURCES)) all: shared static shared: $(MOD_LOBJ) static: $(OBJS) profile: $(PROFS) -include $(patsubst %, %.d, $(PROFS)) $(BUILD_DIR)/profile/%$(EXEEXT): profile/%.c $(BUILD_DIR)/../profiler.o $(QUIET_CC) $(CC) $(CFLAGS) -std=gnu99 $(INCS) $< $(BUILD_DIR)/../profiler.o -o $@ $(LIBS) $(DEPFLAGS1) tune: $(TUNE_SOURCES) $(HEADERS) $(AT)$(foreach prog, $(TUNE), $(CC) $(CFLAGS) $(INCS) $(prog).c -o $(BUILD_DIR)/$(prog) $(LIBS) || exit $$?;) -include $(OBJS:.o=.d) $(BUILD_DIR)/$(MOD_DIR)_%.o: %.c $(QUIET_CC) $(CC) $(CFLAGS) $(INCS) -c $< -o $@ $(DEPFLAGS2) $(MOD_LOBJ): $(LOBJS) $(QUIET_CC) $(CC) $(ABI_FLAG) -r $^ -o $@ -nostdlib -include $(LOBJS:.lo=.d) $(BUILD_DIR)/%.lo: %.c $(QUIET_CC) $(CC) $(PIC_FLAG) $(CFLAGS) $(INCS) -c $< -o $@ $(DEPFLAGS3) clean: rm -rf $(BUILD_DIR) $(MOD_LOBJ) tests: $(TESTS) check: tests $(TESTS_RUN) valgrind: tests $(VALGRIND_RUN) -include $(patsubst %, %.d, $(TESTS)) ifeq ($(FLINT_SHARED), 0) $(BUILD_DIR)/test/%$(EXEEXT): $(BUILD_DIR)/../../libflint.a endif $(BUILD_DIR)/test/%$(EXEEXT): test/%.c $(BUILD_DIR)/../../test_helpers.o $(QUIET_CC) $(CC) $(CFLAGS) $(INCS) $(LDFLAGS) $< $(BUILD_DIR)/../../test_helpers.o -o $@ $(LIBS) $(DEPFLAGS1) $(BUILD_DIR)/test/%$(EXEEXT): test/%.cpp $(BUILD_DIR)/../../test_helpers.o $(QUIET_CXX) $(CXX) $(CXXFLAGS) $(INCS) $(LDFLAGS) $< $(BUILD_DIR)/../../test_helpers.o -o $@ $(LIBS) $(DEPFLAGS1) %_RUN: % @$< %_VALGRIND_RUN: % valgrind --track-origins=yes --leak-check=full --show-reachable=yes --log-file="$*.valgrind" $< .PHONY: profile tune clean check tests all shared static valgrind %_RUN %_VALGRIND_RUN flint2-2.8.4/NEWS000066400000000000000000001355441414523752600134470ustar00rootroot00000000000000v 1.0 -- 2-Dec-07 : * First version of FLINT, includes fmpz_poly, fmpz and mpQS v 1.0.1 -- 7-Dec-07 : * 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 v 1.0.2 -- 10-Dec-07 * 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. v 1.0.3 -- 16-Dec-07 * 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 v 1.0.4 -- 04-Jan-08 * 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. v 1.0.5 -- 05-Jan-08 * 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. v 1.0.6 -- 17-Jan-08 * Fixed an issue with FLINT_BIT_COUNT on certain machines (probably due to arithmetic shift issues) v 1.0.7 -- 22-Jan-08 * Made F_mpn_mul binary compatible with the way mpn_mul *operates* in practice. v 1.0.8 -- 15-Feb-08 * Fixed a bug in fmpz_poly_right_shift (reported by Kiran Kedlaya) v 1.0.9 -- 11-Mar-08 * Fixed a memory allocation bug in fmpz_poly_power v 1.0.10 -- 16-Jun-08: * 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 v 1.0.11 -- 9-Jul-08 * Fixed a bug in z_ll_mod_precomp on ia64 (reported by Michael Abshoff and William Stein) v 1.0.12 -- 11-Jul-08 * 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 v 1.0.13 -- 13-Jul-08 * Fixed memory leaks and dirty memory issues in test code for numerous modules. * Removed further issues with cache prefetching in mpn_extras.c v 1.0.14 -- 23-Sep-08 * 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 v 1.0.15 -- 15-Oct-08 * 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 v 1.0.16 -- 22-Oct-08 * 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) v 1.0.17 -- 30-Nov-08 * 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 v 1.0.18 -- 05-Dec-08 * Fixed another bug in the fmpz_poly_set_coeff_* functions which resulted in dirty coefficients v 1.0.19 -- 12-Dec-08 * Fixed a bug in z_remove_precomp v 1.0.20 -- 13-Dec-08 * Fixed some bugs in conversion of zmod_poly's to and from strings v 1.0.21 -- 25-Dec-08 * 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 v 1.1.0 -- 21-Dec-08 (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) v 1.1.1 -- 11-Feb-09 * 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. v 1.1.2 -- 1-Mar-09 * Fixed some memory allocation slowdowns and bugs in fmpz_poly division and pseudo division functions (reported by William Stein). v 1.1.3 -- 1-Mar-09 * Inserted some missing return values in zmod_poly test code. v 1.2.0 -- 10-Mar-09 * 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 v 1.2.1 -- 14-Mar-09 * Removed some FLINT 2.0 code which was interfering with the build of the NTL-interface * Removed an omp.h from fmpz_poly.c. v 1.2.2 -- 20-Mar-09 * Fixed a memory leak in zmod_poly_factor * Fixed zmod_poly-profile build v 1.2.3 -- 31-Mar-09 * Fixed bugs in all fmpz_poly evaluation functions, identified by Burcin Erocal. v 1.2.4 -- 4-Apr-09 * 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) v 1.2.5 -- 18-Apr-09 * Upgraded to zn_poly-0.9 to avoid a serious error in squaring of large polynomials over Z/nZ v 1.3.0 -- 09-Jun-09 * 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 v 1.4.0 -- 06-Jul-09 * 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 v 1.5.0 -- 22-Sep-09 * 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 v 1.6.0 -- 24-Dec-10 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 v 2.0 -- 16 Jan 2011 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) v 2.1 -- 9 Mar 2011 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 v 2.2 -- 4 Jun 2011 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 v 2.3 -- 1 Jul 2012 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 v 2.4 -- 20 Nov 2013 * 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 v 2.4.2 -- 11 Mar 2014 * Fix bug in ARM assembly v 2.4.3 -- 01 Apr 2014 * Fix a linker issue on Mac OSX. v 2.4.4 -- fixed a severe bug in flint's primality code (n_is_prime() affecting n_factor()) v 2.4.5 -- fixed a severe bug in flint's fmpz_poly_gcd_heuristic, reported by Anton Mellit. v 2.5.0 -- 07 Aug 2015 * 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 v 2.5.1 -- 12 Aug 2015 * Fix some build bugs related to soname versioning and ldconfig * Fix issue with Windows MSVC build v 2.5.2 -- 13 Aug 2015 * Fix further issues with soname versioning and ldconfig * Fix a bug when using GMP instead of MPIR. v 2.6.0 -- 5 Jun 2020 * 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 v 2.6.1 -- 23 Jul 2020 * Fix issues on Debian major architectures * Fix numerous reported bugs (mpoly, fq_poly, mpn_mul_1, mod 2 code, etc.) v 2.6.2 -- 31 Jul 2020 * Fix for choice of generator in an fq finite field of degree one * Fix an incorrectly written test v 2.6.3 -- 12 Aug 2020 * 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 2.7.0 -- 18 Dec 2020 * 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) 2.7.1 -- 18 Jan 2021 * 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 2.8.0 -- 23 Jul 2021 * 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 2.8.1 -- 01 Oct 2021 * Numerous bug fixes * Adjust soname on android * Allow disabling of dependency tracking 2.8.2 -- 15 Oct 2021 * Fix an issue with --disable-dependency-tracking on some distributions 2.8.3 -- 03 Nov 2021 * 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 2.8.4 -- 17 Nov 2021 * Fix a serious big 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 flint2-2.8.4/NTL-interface.h000066400000000000000000000075051414523752600155070ustar00rootroot00000000000000/* 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 2.1 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 #include #include #include #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "fq.h" #include "fq_poly.h" #ifdef __cplusplus extern "C" { #endif /* Converts an NTL ZZ to an fmpz_t. Assumes the fmpz_t has already been allocated to have sufficient space. */ FLINT_DLL void fmpz_set_ZZ(fmpz_t rop, const NTL_NNS ZZ& op); /* Converts an fmpz_t to an NTL ZZ. Allocation is automatically handled. */ FLINT_DLL void fmpz_get_ZZ(NTL_NNS ZZ& rop, const fmpz_t op); /* Converts an NTL ZZ_p to an fmpz_t. Assumes the fmpz_t has already been allocated to have sufficient space. */ FLINT_DLL void fmpz_set_ZZ_p(fmpz_t rop, const NTL_NNS ZZ_p& op); /* Converts an fmpz_t to an NTL ZZ_p. Allocation is automatically handled. */ FLINT_DLL void fmpz_get_ZZ_p(NTL_NNS ZZ_p& rop, const fmpz_t op); /* Converts an NTL zz_p to an fmpz_t. */ FLINT_DLL void fmpz_set_zz_p(fmpz_t rop, const NTL_NNS zz_p& op); /* Converts an fmpz_t to an NTL zz_p. */ FLINT_DLL void fmpz_get_zz_p(NTL_NNS zz_p& rop, const fmpz_t op); /* Converts an fmpz_poly_t to an NTL ZZX. */ FLINT_DLL void fmpz_poly_get_ZZX(NTL_NNS ZZX& rop, const fmpz_poly_t op); /* Converts an NTL ZZX to an fmpz_poly_t. */ FLINT_DLL void fmpz_poly_set_ZZX(fmpz_poly_t rop, const NTL_NNS ZZX& op); /* Converts an fmpz_mod_poly_t to an NTL ZZ_pX. */ FLINT_DLL void fmpz_mod_poly_get_ZZ_pX(NTL_NNS ZZ_pX& rop, const fmpz_mod_poly_t op, const fmpz_mod_ctx_t ctx); /* Converts an NTL ZZ_pX to an fmpz_poly_t. */ FLINT_DLL void fmpz_mod_poly_set_ZZ_pX(fmpz_mod_poly_t rop, const NTL_NNS ZZ_pX& op, const fmpz_mod_ctx_t ctx); /* Converts an fq_t to an NTL ZZ_pE. */ FLINT_DLL void fq_get_ZZ_pE(NTL_NNS ZZ_pE& rop, const fq_t op, const fq_ctx_t ctx); /* Converts an NTL ZZ_pE to an fq_t. */ FLINT_DLL void fq_set_ZZ_pE(fq_t rop, const NTL_NNS ZZ_pE& op, const fq_ctx_t ctx); /* Converts an fq_poly_t to an NTL ZZ_pEX. */ FLINT_DLL void fq_poly_get_ZZ_pEX(NTL_NNS ZZ_pEX& rop, const fq_poly_t op, const fq_ctx_t ctx); /* Converts an NTL ZZ_pEX to an fq_poly_t. */ FLINT_DLL void fq_poly_set_ZZ_pEX(fq_poly_t rop, const NTL_NNS ZZ_pEX& op, const fq_ctx_t ctx); /* Converts an fmpz_mod_poly_t to an NTL zz_pX. */ FLINT_DLL void fmpz_mod_poly_get_zz_pX(NTL_NNS zz_pX& rop, const fmpz_mod_poly_t op, const fmpz_mod_ctx_t ctx); /* Converts an NTL zz_pX to an fmpz_poly_t. */ FLINT_DLL void fmpz_mod_poly_set_zz_pX(fmpz_mod_poly_t rop, const NTL_NNS zz_pX& op, const fmpz_mod_ctx_t ctx); /* Converts an fq_t to an NTL zz_pE. */ FLINT_DLL void fq_get_zz_pE(NTL_NNS zz_pE& rop, const fq_t op, const fq_ctx_t ctx); /* Converts an NTL zz_pE to an fq_t. */ FLINT_DLL void fq_set_zz_pE(fq_t rop, const NTL_NNS zz_pE& op, const fq_ctx_t ctx); /* Converts an fq_poly_t to an NTL zz_pEX. */ FLINT_DLL void fq_poly_get_zz_pEX(NTL_NNS zz_pEX& rop, const fq_poly_t op, const fq_ctx_t ctx); /* Converts an NTL zz_pEX to an fq_poly_t. */ FLINT_DLL void fq_poly_set_zz_pEX(fq_poly_t rop, const NTL_NNS zz_pEX& op, const fq_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint2-2.8.4/README000066400000000000000000000013201414523752600136100ustar00rootroot00000000000000FLINT 2 ======= FLINT (Fast Library for Number Theory) is a C library in support of computations in number theory. It's also a research project into algorithms in number theory. FLINT 2 is a complete rewrite of the FLINT library from scratch. It includes much cleaner code and in many cases much faster algorithms and implementations. At this stage FLINT consists mainly of fast integer and polynomial arithmetic and linear algebra. In the future it is planned that FLINT will contain algorithms for algebraic number theory and other number theoretic functionality. William Hart -- 16 Jan 2011. License ------- This version is distributed under LGPL 2.1 (GNU Lesser General Public License). See the LICENSE file. flint2-2.8.4/appveyor.yml000066400000000000000000000050271414523752600153300ustar00rootroot00000000000000version: 0.2.19.{build} platform: - x64 os: Visual Studio 2019 clone_depth: 5 skip_tags: true matrix: fast_finish: false skip_commits: # Add [av skip] to commit messages message: /\[av skip\]/ environment: global: CONDA_INSTALL_LOCN_32: "C:\\Miniconda36" CONDA_INSTALL_LOCN_64: "C:\\Miniconda38-x64" VCVARSALL: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat" matrix: - COMPILER: cl ARCH: 32 - COMPILER: cl ARCH: 64 - COMPILER: gcc ARCH: 32 - COMPILER: gcc ARCH: 64 install: - if [%COMPILER%]==[gcc] set "PATH=C:\msys64\mingw%ARCH%\bin;%PATH%" - if [%COMPILER%]==[gcc] set "CMAKE_PREFIX_PATH=C:\msys64\mingw%ARCH%" - if [%COMPILER%]==[gcc] del /F /Q "C:\Program Files\Git\usr\bin\sh.exe" # - if [%COMPILER%]==[gcc] if [%ARCH%]==[64] C:\msys64\usr\bin\pacman.exe -Sy --noconfirm --noconfirm --needed base-devel mingw-w64-x86_64-gcc mingw-w64-x86_64-mpfr # - if [%COMPILER%]==[gcc] if [%ARCH%]==[32] C:\msys64\usr\bin\pacman.exe -Sy --noconfirm --noconfirm --needed base-devel mingw-w64-i686-gcc mingw-w64-i686-mpfr - if [%COMPILER%]==[cl] if [%ARCH%]==[64] set "CONDA_INSTALL_LOCN=%CONDA_INSTALL_LOCN_64%" - if [%COMPILER%]==[cl] if [%ARCH%]==[32] set "CONDA_INSTALL_LOCN=%CONDA_INSTALL_LOCN_32%" - if [%COMPILER%]==[cl] set "LIB=%CONDA_INSTALL_LOCN%\Library\lib;%LIB%" - if [%COMPILER%]==[cl] set "CPATH=%CONDA_INSTALL_LOCN%\Library\include;%CPATH%" - if [%COMPILER%]==[cl] call %CONDA_INSTALL_LOCN%\Scripts\activate.bat - if [%COMPILER%]==[cl] if [%ARCH%]==[64] call "%VCVARSALL%" x64 - if [%COMPILER%]==[cl] if [%ARCH%]==[32] call "%VCVARSALL%" x86 - if [%COMPILER%]==[cl] conda config --add channels conda-forge --force - if [%COMPILER%]==[cl] conda install --yes --quiet mpir=3.0.0 mpfr=4.* pthreads-win32 ninja - if [%COMPILER%]==[cl] set "CFLAGS=/wd4146 /wd4018 /wd4267 /wd4244" - echo int flint_test_multiplier(){return 1;} > test_helpers.c - cat test_helpers.c before_build: - ps: if (-Not (Test-Path .\build)) { mkdir build } - cd build - if [%COMPILER%]==[gcc] cmake -G "MinGW Makefiles" -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Release .. - if [%COMPILER%]==[cl] cmake -G "Ninja" -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Release .. build_script: - cmake --build . -- -j2 test_script: - ctest -j3 --output-on-failure --timeout 600 #on_finish: # - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) flint2-2.8.4/aprcl.h000066400000000000000000000242521414523752600142130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef APRCL_H #define APRCL_H #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.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; /* Useful functions */ FLINT_DLL int _aprcl_p_ind(const aprcl_config conf, ulong p); FLINT_DLL ulong aprcl_p_power_in_q(ulong q, ulong p); FLINT_DLL int aprcl_is_mul_coprime_ui_ui(ulong x, ulong y, const fmpz_t n); FLINT_DLL int aprcl_is_mul_coprime_ui_fmpz(ulong x, const fmpz_t y, const fmpz_t n); /* Primality tests -------------------------------------------------------------------------------- */ FLINT_DLL int aprcl_is_prime(const fmpz_t n); /* Gauss test configuration */ FLINT_DLL void aprcl_config_gauss_init(aprcl_config conf, const fmpz_t n); FLINT_DLL void aprcl_config_gauss_init_min_R(aprcl_config conf, const fmpz_t n, ulong R); FLINT_DLL void aprcl_config_gauss_clear(aprcl_config conf); /* Jacobi test configuration */ FLINT_DLL ulong aprcl_R_value(const fmpz_t n); FLINT_DLL void aprcl_config_jacobi_init(aprcl_config conf, const fmpz_t n); FLINT_DLL void aprcl_config_jacobi_clear(aprcl_config conf); /* Gauss sums primality test */ FLINT_DLL int aprcl_is_prime_gauss(const fmpz_t n); FLINT_DLL int aprcl_is_prime_gauss_min_R(const fmpz_t n, ulong R); FLINT_DLL primality_test_status _aprcl_is_prime_gauss(const fmpz_t n, const aprcl_config config); FLINT_DLL int _aprcl_is_gausspower_2q_equal_first(ulong q, const fmpz_t n); FLINT_DLL int _aprcl_is_gausspower_2q_equal_second(ulong q, const fmpz_t n); FLINT_DLL slong _aprcl_is_gausspower_from_unity_p(ulong q, ulong r, const fmpz_t n); /* Jacobi sums primality test */ FLINT_DLL int aprcl_is_prime_jacobi(const fmpz_t n); FLINT_DLL primality_test_status _aprcl_is_prime_jacobi(const fmpz_t n, const aprcl_config config); FLINT_DLL slong _aprcl_is_prime_jacobi_check_pk(const unity_zp j, const fmpz_t u, ulong v); FLINT_DLL slong _aprcl_is_prime_jacobi_check_21(ulong q, const fmpz_t n); FLINT_DLL slong _aprcl_is_prime_jacobi_check_22(const unity_zp j, const fmpz_t u, ulong v, ulong q); FLINT_DLL 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); FLINT_DLL int _aprcl_is_prime_jacobi_additional_test(const fmpz_t n, ulong p); /* Final division functions */ FLINT_DLL int aprcl_is_prime_divisors_in_residue(const fmpz_t n, const fmpz_t s, ulong r); FLINT_DLL int aprcl_is_prime_final_division(const fmpz_t n, const fmpz_t s, ulong r); /* Z[unity_root]/(n) operations -------------------------------------------------------------------------------- */ /* Memory management */ FLINT_DLL void unity_zp_init(unity_zp f, ulong p, ulong exp, const fmpz_t n); FLINT_DLL void unity_zp_clear(unity_zp f); FLINT_DLL void unity_zp_copy(unity_zp f, const unity_zp g); FLINT_DLL void unity_zp_swap(unity_zp f, unity_zp g); FLINT_DLL void unity_zp_set_zero(unity_zp f); /* Comparison */ FLINT_DLL slong unity_zp_is_unity(unity_zp f); FLINT_DLL int unity_zp_equal(unity_zp f, unity_zp g); /* Output */ FLINT_DLL void unity_zp_print(const unity_zp f); /* Coefficient management */ FLINT_DLL void unity_zp_coeff_set_fmpz(unity_zp f, ulong ind, const fmpz_t x); FLINT_DLL void unity_zp_coeff_set_ui(unity_zp f, ulong ind, ulong x); FLINT_DLL void unity_zp_coeff_add_fmpz(unity_zp f, ulong ind, const fmpz_t x); FLINT_DLL void unity_zp_coeff_add_ui(unity_zp f, ulong ind, ulong x); FLINT_DLL void unity_zp_coeff_inc(unity_zp f, ulong ind); FLINT_DLL void unity_zp_coeff_dec(unity_zp f, ulong ind); /* Scalar multiplication */ FLINT_DLL void unity_zp_mul_scalar_fmpz(unity_zp f, const unity_zp g, const fmpz_t s); FLINT_DLL void unity_zp_mul_scalar_ui(unity_zp f, const unity_zp g, ulong s); /* Addition */ FLINT_DLL void unity_zp_add(unity_zp f, const unity_zp g, const unity_zp h); /* General multiplication and squaring */ FLINT_DLL void unity_zp_mul(unity_zp f, const unity_zp g, const unity_zp h); FLINT_DLL void unity_zp_sqr(unity_zp f, const unity_zp g); /* Special multiplication and squaring */ FLINT_DLL void unity_zp_mul_inplace(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); FLINT_DLL void unity_zp_sqr_inplace(unity_zp f, const unity_zp g, fmpz_t * t); FLINT_DLL void unity_zp_ar1(fmpz_t * t); FLINT_DLL void unity_zp_ar2(fmpz_t * t); FLINT_DLL void unity_zp_ar3(fmpz_t * t); FLINT_DLL void unity_zp_ar4(fmpz_t * t); FLINT_DLL void unity_zp_mul3(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); FLINT_DLL void unity_zp_mul9(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); FLINT_DLL void unity_zp_mul4(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); FLINT_DLL void unity_zp_mul8(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); FLINT_DLL void unity_zp_mul16(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); FLINT_DLL void unity_zp_mul5(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); FLINT_DLL void unity_zp_mul7(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); FLINT_DLL void unity_zp_mul11(unity_zp f, const unity_zp g, const unity_zp h, fmpz_t * t); FLINT_DLL void unity_zp_sqr3(unity_zp f, const unity_zp g, fmpz_t * t); FLINT_DLL void unity_zp_sqr9(unity_zp f, const unity_zp g, fmpz_t * t); FLINT_DLL void unity_zp_sqr4(unity_zp f, const unity_zp g, fmpz_t * t); FLINT_DLL void unity_zp_sqr8(unity_zp f, const unity_zp g, fmpz_t * t); FLINT_DLL void unity_zp_sqr16(unity_zp f, const unity_zp g, fmpz_t * t); FLINT_DLL void unity_zp_sqr5(unity_zp f, const unity_zp g, fmpz_t * t); FLINT_DLL void unity_zp_sqr7(unity_zp f, const unity_zp g, fmpz_t * t); FLINT_DLL void unity_zp_sqr11(unity_zp f, const unity_zp g, fmpz_t * t); /* Powering functions */ FLINT_DLL void unity_zp_pow_fmpz(unity_zp f, const unity_zp g, const fmpz_t pow); FLINT_DLL void unity_zp_pow_ui(unity_zp f, const unity_zp g, ulong pow); FLINT_DLL ulong _unity_zp_pow_select_k(const fmpz_t n); FLINT_DLL void unity_zp_pow_2k_fmpz(unity_zp f, const unity_zp g, const fmpz_t pow); FLINT_DLL void unity_zp_pow_2k_ui(unity_zp f, const unity_zp g, ulong pow); FLINT_DLL void unity_zp_pow_sliding_fmpz(unity_zp f, unity_zp g, const fmpz_t pow); /* Cyclotomic reduction */ FLINT_DLL void _unity_zp_reduce_cyclotomic_divmod(unity_zp f); FLINT_DLL void _unity_zp_reduce_cyclotomic(unity_zp f); FLINT_DLL void unity_zp_reduce_cyclotomic(unity_zp f, const unity_zp g); /* Automorphism and inverse computation */ FLINT_DLL void unity_zp_aut(unity_zp f, const unity_zp g, ulong x); FLINT_DLL void unity_zp_aut_inv(unity_zp f, const unity_zp g, ulong x); /* Jacobi sum computation. */ FLINT_DLL mp_ptr aprcl_f_table(const ulong q); FLINT_DLL void _unity_zp_jacobi_sum_pq_general(unity_zp f, const mp_ptr table, ulong p, ulong q, ulong k, ulong a, ulong b); FLINT_DLL void unity_zp_jacobi_sum_pq(unity_zp f, ulong q, ulong p); FLINT_DLL void unity_zp_jacobi_sum_2q_one(unity_zp f, ulong q); FLINT_DLL void unity_zp_jacobi_sum_2q_two(unity_zp f, ulong q); /* Z[unity_root_q, unity_root_p]/(n) operations -------------------------------------------------------------------------------- */ /* Memory management */ FLINT_DLL void unity_zpq_init(unity_zpq f, ulong q, ulong p, const fmpz_t n); FLINT_DLL void unity_zpq_clear(unity_zpq f); FLINT_DLL void unity_zpq_copy(unity_zpq f, const unity_zpq g); FLINT_DLL void unity_zpq_swap(unity_zpq f, unity_zpq g); /* Comparison */ FLINT_DLL int unity_zpq_equal(const unity_zpq f, const unity_zpq g); FLINT_DLL slong unity_zpq_p_unity(const unity_zpq f); FLINT_DLL int unity_zpq_is_p_unity(const unity_zpq f); FLINT_DLL int unity_zpq_is_p_unity_generator(const unity_zpq f); /* Coefficient management */ FLINT_DLL void unity_zpq_coeff_set_fmpz(unity_zpq f, slong i, slong j, const fmpz_t x); FLINT_DLL void unity_zpq_coeff_set_ui(unity_zpq f, slong i, slong j, ulong x); FLINT_DLL void unity_zpq_coeff_add(unity_zpq f, slong i, slong j, const fmpz_t x); FLINT_DLL void unity_zpq_coeff_add_ui(unity_zpq f, slong i, slong j, ulong x); /* Scalar multiplication */ FLINT_DLL void unity_zpq_scalar_mul_ui(unity_zpq f, const unity_zpq g, ulong s); /* Addition and multiplication */ FLINT_DLL void unity_zpq_add(unity_zpq f, const unity_zpq g, const unity_zpq h); FLINT_DLL void unity_zpq_mul(unity_zpq f, const unity_zpq g, const unity_zpq h); FLINT_DLL void _unity_zpq_mul_unity_p(unity_zpq f); FLINT_DLL void unity_zpq_mul_unity_p_pow( unity_zpq f, const unity_zpq g, slong p); /* Powering */ FLINT_DLL void unity_zpq_pow(unity_zpq f, const unity_zpq g, const fmpz_t p); FLINT_DLL void unity_zpq_pow_ui(unity_zpq f, const unity_zpq g, ulong pow); /* Gauss sum computation */ FLINT_DLL void unity_zpq_gauss_sum(unity_zpq f, ulong q, ulong p); FLINT_DLL void unity_zpq_gauss_sum_character_pow(unity_zpq f, ulong q, ulong p, ulong pow); FLINT_DLL void unity_zpq_gauss_sum_sigma_pow( unity_zpq f, ulong q, ulong p); #ifdef __cplusplus } #endif #endif flint2-2.8.4/aprcl/000077500000000000000000000000001414523752600140355ustar00rootroot00000000000000flint2-2.8.4/aprcl/config_gauss.c000066400000000000000000000036651414523752600166620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/config_jacobi.c000066400000000000000000000135531414523752600167640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("APRCL not supported for huge numbers on 32 bits\n"); flint_abort(); 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); } flint2-2.8.4/aprcl/f_table.c000066400000000000000000000024111414523752600155730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/aprcl/is_mul_coprime.c000066400000000000000000000025511414523752600172120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/aprcl/is_prime.c000066400000000000000000000007421414523752600160130ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/aprcl/is_prime_divisors_in_residue.c000066400000000000000000000021231414523752600221360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" int aprcl_is_prime_divisors_in_residue(const fmpz_t n, const fmpz_t s, ulong r) { int result; ulong i; fmpz_t npow, nmul, fac; fmpz_init(fac); fmpz_init_set(npow, n); fmpz_mod(npow, npow, s); /* npow = n mod s */ fmpz_init_set(nmul, npow); result = 1; for (i = 1; i < r; i++) { /* if find divisor then n is composite */ if (fmpz_divisor_in_residue_class_lenstra(fac, n, npow, s) == 1) { result = 0; break; } /* npow = n^i mod s */ fmpz_mul(npow, npow, nmul); fmpz_mod(npow, npow, s); } fmpz_clear(fac); fmpz_clear(npow); fmpz_clear(nmul); return result; } flint2-2.8.4/aprcl/is_prime_final_division.c000066400000000000000000000024241414523752600210670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/aprcl/is_prime_gauss.c000066400000000000000000000271311414523752600172160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("aprcl_is_prime_gauss: failed to prove n prime\n"); fmpz_print(n); flint_printf("\n"); flint_abort(); } if (result == PRIME) return 1; return 0; } flint2-2.8.4/aprcl/is_prime_jacobi.c000066400000000000000000000565611414523752600173340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("aprcl_is_prime_jacobi: failed to prove n prime\n"); fmpz_print(n); flint_printf("\n"); flint_abort(); } /* if we prove primality, returns 1 */ if (result == PRIME) return 1; return 0; } flint2-2.8.4/aprcl/profile/000077500000000000000000000000001414523752600154755ustar00rootroot00000000000000flint2-2.8.4/aprcl/profile/p-is_prime_aprcl.c000066400000000000000000001177521414523752600211030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.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"); 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; } flint2-2.8.4/aprcl/profile/p-is_prime_aprcl_big.c000066400000000000000000000213641414523752600217150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "aprcl.h" void p_is_prime_repeat(fmpz_t n) { int i; TIMEIT_START if (aprcl_is_prime(n) == 0) { flint_printf("Primality test failed\n"); abort(); } TIMEIT_STOP } int main(void) { const int len = 5; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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 */ { int i; 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; } flint2-2.8.4/aprcl/test/000077500000000000000000000000001414523752600150145ustar00rootroot00000000000000flint2-2.8.4/aprcl/test/t-config_gauss.c000066400000000000000000000024231414523752600200710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("config_gauss...."); fflush(stdout); 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); abort(); } aprcl_config_gauss_clear(conf); fmpz_clear(n); fmpz_clear(s2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-config_jacobi.c000066400000000000000000000024301414523752600201740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("config_jacobi...."); fflush(stdout); 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); abort(); } aprcl_config_jacobi_clear(conf); fmpz_clear(s2); fmpz_clear(n); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-f_table.c000066400000000000000000000027051414523752600170210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("f_table...."); fflush(stdout); 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); abort(); } } _nmod_vec_clear(table); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-is_prime.c000066400000000000000000000025341414523752600172340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_prime...."); fflush(stdout); 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); abort(); } fmpz_clear(n); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-is_prime_gauss.c000066400000000000000000000053551414523752600204420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_prime_gauss...."); fflush(stdout); 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); 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"); abort(); } fmpz_clear(n); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-is_prime_jacobi.c000066400000000000000000000140251414523752600205410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" #include int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_prime_jacobi...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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); 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"); abort(); } fmpz_clear(n); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_add.c000066400000000000000000000040311414523752600201100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zp_add...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h1); unity_zp_clear(h2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_aut_inv.c000066400000000000000000000044721414523752600210360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { ulong i, j; FLINT_TEST_INIT(state); flint_printf("unity_zp_aut_inv...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_equal.c000066400000000000000000000031701414523752600204720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zp_equal...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_init.c000066400000000000000000000020351414523752600203250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("unity_zp_init...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_is_unity.c000066400000000000000000000026621414523752600212330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("unity_zp_is_unity...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); unity_zp_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_jacobi_sum.c000066400000000000000000000107011414523752600214740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zp_jacobi_sum...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); _nmod_vec_clear(table); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_mul.c000066400000000000000000000060721414523752600201640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zp_mul...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h1); unity_zp_clear(h2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_mul11.c000066400000000000000000000044461414523752600203310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; fmpz_t * t; FLINT_TEST_INIT(state); flint_printf("unity_zp_mul11...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_mul2.c000066400000000000000000000122201414523752600202360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; fmpz_t * t; FLINT_TEST_INIT(state); flint_printf("unity_zp_mul2...."); fflush(stdout); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_mul3.c000066400000000000000000000073121414523752600202450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; fmpz_t * t; FLINT_TEST_INIT(state); flint_printf("unity_zp_mul3...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_mul5.c000066400000000000000000000044431414523752600202510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; fmpz_t * t; FLINT_TEST_INIT(state); flint_printf("unity_zp_mul5...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_mul7.c000066400000000000000000000044431414523752600202530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; fmpz_t * t; FLINT_TEST_INIT(state); flint_printf("unity_zp_mul7...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_pow.c000066400000000000000000000040761414523752600201760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zp_pow...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h1); unity_zp_clear(h2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_pow_2k.c000066400000000000000000000036361414523752600205730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zp_pow_2k...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); fmpz_clear(pow); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_pow_sliding.c000066400000000000000000000037201414523752600217020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zp_pow_sliding...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); fmpz_clear(pow); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_reduce_cyclotomic.c000066400000000000000000000042261414523752600230620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("unity_zp_reduce_cyclotomic...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); fmpz_mod_poly_clear(cyclo_poly, ctx); unity_zp_clear(f); unity_zp_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_sqr.c000066400000000000000000000033271414523752600201740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zp_sqr...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); unity_zp_clear(f); unity_zp_clear(g); unity_zp_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_sqr11.c000066400000000000000000000037731414523752600203430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; fmpz_t * t; FLINT_TEST_INIT(state); flint_printf("unity_zp_sqr11...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_sqr2.c000066400000000000000000000104071414523752600202530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; fmpz_t * t; FLINT_TEST_INIT(state); flint_printf("unity_zp_sqr2...."); fflush(stdout); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_sqr3.c000066400000000000000000000061601414523752600202550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; fmpz_t * t; FLINT_TEST_INIT(state); flint_printf("unity_zp_sqr3...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_sqr5.c000066400000000000000000000037671414523752600202710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; fmpz_t * t; FLINT_TEST_INIT(state); flint_printf("unity_zp_sqr5...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zp_sqr7.c000066400000000000000000000037671414523752600202730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; fmpz_t * t; FLINT_TEST_INIT(state); flint_printf("unity_zp_sqr7...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zpq_add.c000066400000000000000000000042171414523752600202770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zpq_add...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); unity_zpq_clear(f); unity_zpq_clear(g); unity_zpq_clear(h1); unity_zpq_clear(h2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zpq_equal.c000066400000000000000000000033461414523752600206600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zpq_equal...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); unity_zpq_clear(f); unity_zpq_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zpq_gauss_sum.c000066400000000000000000000040661414523752600215570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zpq_gauss_sum...."); fflush(stdout); 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"); abort(); } unity_zpq_clear(gausssigma); unity_zpq_clear(gauss); unity_zpq_clear(gausspower); fmpz_clear(n); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zpq_init.c000066400000000000000000000021431414523752600205060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("unity_zpq_init...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zpq_mul.c000066400000000000000000000041171414523752600203430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zpq_mul...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); unity_zpq_clear(f); unity_zpq_clear(g); unity_zpq_clear(h1); unity_zpq_clear(h2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zpq_mul_unity_p.c000066400000000000000000000041131414523752600221060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zpq_mul_unity_p...."); fflush(stdout); 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"); abort(); } unity_zpq_clear(h1); unity_zpq_clear(h2); } fmpz_clear(n); unity_zpq_clear(f); unity_zpq_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/test/t-unity_zpq_pow.c000066400000000000000000000043071414523752600203540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "aprcl.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("unity_zpq_pow...."); fflush(stdout); 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"); abort(); } fmpz_clear(n); unity_zpq_clear(f); unity_zpq_clear(g); unity_zpq_clear(h1); unity_zpq_clear(h2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/aprcl/unity_zp_add.c000066400000000000000000000014031414523752600166700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" 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); } flint2-2.8.4/aprcl/unity_zp_aut.c000066400000000000000000000021231414523752600167310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zp_aut_inv.c000066400000000000000000000044661414523752600176210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zp_auxiliary_routine.c000066400000000000000000000274451414523752600217320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 */ } flint2-2.8.4/aprcl/unity_zp_coeff_add.c000066400000000000000000000032141414523752600200340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/aprcl/unity_zp_coeff_inc.c000066400000000000000000000022601414523752600200550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" 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)); } flint2-2.8.4/aprcl/unity_zp_coeff_set.c000066400000000000000000000012231414523752600200750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" 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); } flint2-2.8.4/aprcl/unity_zp_copy.c000066400000000000000000000011641414523752600171160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" 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); } flint2-2.8.4/aprcl/unity_zp_equal.c000066400000000000000000000012751414523752600172560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zp_init.c000066400000000000000000000012701414523752600171050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zp_is_unity.c000066400000000000000000000020721414523752600200060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/aprcl/unity_zp_jacobi_sum.c000066400000000000000000000046001414523752600202550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" #include "ulong_extras.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); } flint2-2.8.4/aprcl/unity_zp_mul.c000066400000000000000000000047271414523752600167510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" 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); } flint2-2.8.4/aprcl/unity_zp_mul11.c000066400000000000000000000072471414523752600171130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.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 */ } flint2-2.8.4/aprcl/unity_zp_mul2.c000066400000000000000000000250441414523752600170260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" /* 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 */ } flint2-2.8.4/aprcl/unity_zp_mul3.c000066400000000000000000000164411414523752600170300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" /* 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 */ } flint2-2.8.4/aprcl/unity_zp_mul5.c000066400000000000000000000074141414523752600170320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" /* 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 */ } flint2-2.8.4/aprcl/unity_zp_mul7.c000066400000000000000000000146541414523752600170400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" /* 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 */ } flint2-2.8.4/aprcl/unity_zp_mul_scalar.c000066400000000000000000000016321414523752600202660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" void unity_zp_mul_scalar_fmpz(unity_zp f, const unity_zp g, const fmpz_t s) { FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(g->ctx))); fmpz_mod_poly_scalar_mul_fmpz(f->poly, g->poly, s, f->ctx); } 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); } flint2-2.8.4/aprcl/unity_zp_pow.c000066400000000000000000000021231414523752600167450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zp_pow_2k.c000066400000000000000000000065051414523752600173510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zp_pow_select_k.c000066400000000000000000000016721414523752600206260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/aprcl/unity_zp_pow_sliding.c000066400000000000000000000062271414523752600204670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zp_print.c000066400000000000000000000010731414523752600172770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" void unity_zp_print(const unity_zp f) { flint_printf("p = %wu; exp = %wu\n", f->p, f->exp); fmpz_mod_poly_print(f->poly, f->ctx); flint_printf("\n"); } flint2-2.8.4/aprcl/unity_zp_reduce_cyclotomic.c000066400000000000000000000045521414523752600216440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zp_set_zero.c000066400000000000000000000007471414523752600200040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" void unity_zp_set_zero(unity_zp f) { fmpz_mod_poly_zero(f->poly, f->ctx); } flint2-2.8.4/aprcl/unity_zp_sqr.c000066400000000000000000000036531414523752600167560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zp_sqr11.c000066400000000000000000000076641414523752600171260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" /* 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 */ } flint2-2.8.4/aprcl/unity_zp_sqr2.c000066400000000000000000000163051414523752600170360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" /* 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 */ } flint2-2.8.4/aprcl/unity_zp_sqr3.c000066400000000000000000000111231414523752600170300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" /* 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 */ } flint2-2.8.4/aprcl/unity_zp_sqr5.c000066400000000000000000000056301414523752600170400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" /* 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 */ } flint2-2.8.4/aprcl/unity_zp_sqr7.c000066400000000000000000000124271414523752600170440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" /* 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 */ } flint2-2.8.4/aprcl/unity_zp_swap.c000066400000000000000000000011571414523752600171200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" 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); } flint2-2.8.4/aprcl/unity_zpq_add.c000066400000000000000000000015211414523752600170520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" 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); } } flint2-2.8.4/aprcl/unity_zpq_clear.c000066400000000000000000000011771414523752600174170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zpq_coeff_add.c000066400000000000000000000026661414523752600202270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/aprcl/unity_zpq_coeff_set.c000066400000000000000000000012511414523752600202570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zpq_copy.c000066400000000000000000000011051414523752600172720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/aprcl/unity_zpq_equal.c000066400000000000000000000014411414523752600174320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/aprcl/unity_zpq_gauss_sum.c000066400000000000000000000015161414523752600203340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/aprcl/unity_zpq_gauss_sum_character_pow.c000066400000000000000000000022251414523752600232330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zpq_init.c000066400000000000000000000013231414523752600172650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/aprcl/unity_zpq_is_p_unity.c000066400000000000000000000020111414523752600204770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" slong unity_zpq_p_unity(const unity_zpq f) { slong i; ulong is_punity; is_punity = f->p; for (i = 0; i < f->p; i++) { if (fmpz_equal_ui(f->polys[i]->coeffs + i, 1)) { if (is_punity != f->p) return 0; is_punity = i; } } return is_punity; } int unity_zpq_is_p_unity(const unity_zpq f) { if (unity_zpq_p_unity(f) != f->p) return 1; return 0; } int unity_zpq_is_p_unity_generator(const unity_zpq f) { slong upow = unity_zpq_p_unity(f); if (upow != f->p && upow != 0) return 1; return 0; } flint2-2.8.4/aprcl/unity_zpq_mul.c000066400000000000000000000033631414523752600171250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zpq_mul_unity_p.c000066400000000000000000000014541414523752600206730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zpq_pow.c000066400000000000000000000030741414523752600171340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/aprcl/unity_zpq_scalar_mul_fmpz.c000066400000000000000000000013321414523752600215000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" void unity_zpq_scalar_mul_fmpz(unity_zpq f, const unity_zpq g, const fmpz_t s) { slong i; FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(g->ctx))); for (i = 0; i < f->p; i++) fmpz_mod_poly_scalar_mul_fmpz(f->polys[i], g->polys[i], s, f->ctx); } flint2-2.8.4/aprcl/unity_zpq_scalar_mul_ui.c000066400000000000000000000013171414523752600211440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "aprcl.h" void unity_zpq_scalar_mul_ui(unity_zpq f, const unity_zpq g, ulong s) { slong i; FLINT_ASSERT(fmpz_equal(fmpz_mod_ctx_modulus(f->ctx), fmpz_mod_ctx_modulus(g->ctx))); for (i = 0; i < f->p; i++) fmpz_mod_poly_scalar_mul_ui(f->polys[i], g->polys[i], s, f->ctx); } flint2-2.8.4/aprcl/unity_zpq_swap.c000066400000000000000000000010351414523752600172740ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/aprcl/utility.c000066400000000000000000000016031414523752600157040ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/arith.h000066400000000000000000000175301414523752600142220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef ARITH_H #define ARITH_H #ifdef ARITH_INLINES_C #define ARITH_INLINE FLINT_DLL #else #define ARITH_INLINE static __inline__ #endif #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "fmpq.h" #include "double_extras.h" #ifdef __cplusplus extern "C" { #endif /* MPFR extras ***************************************************************/ FLINT_DLL void mpfr_zeta_inv_euler_product(mpfr_t res, ulong s, int char_4); /* Various arithmetic functions **********************************************/ #define arith_primorial fmpz_primorial FLINT_DLL void _arith_harmonic_number(fmpz_t num, fmpz_t den, slong n); FLINT_DLL void arith_harmonic_number(fmpq_t x, slong n); FLINT_DLL void arith_ramanujan_tau(fmpz_t res, const fmpz_t n); FLINT_DLL void arith_ramanujan_tau_series(fmpz_poly_t res, slong n); FLINT_DLL 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 **********************************************************/ FLINT_DLL void arith_stirling_number_1u(fmpz_t s, slong n, slong k); FLINT_DLL void arith_stirling_number_1(fmpz_t s, slong n, slong k); FLINT_DLL void arith_stirling_number_2(fmpz_t s, slong n, slong k); FLINT_DLL void arith_stirling_number_1u_vec(fmpz * row, slong n, slong klen); FLINT_DLL void arith_stirling_number_1_vec(fmpz * row, slong n, slong klen); FLINT_DLL void arith_stirling_number_2_vec(fmpz * row, slong n, slong klen); FLINT_DLL void arith_stirling_number_1u_vec_next(fmpz * row, const fmpz * prev, slong n, slong klen); FLINT_DLL void arith_stirling_number_1_vec_next(fmpz * row, const fmpz * prev, slong n, slong klen); FLINT_DLL void arith_stirling_number_2_vec_next(fmpz * row, const fmpz * prev, slong n, slong klen); FLINT_DLL void arith_stirling_matrix_1u(fmpz_mat_t mat); FLINT_DLL void arith_stirling_matrix_1(fmpz_mat_t mat); FLINT_DLL 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 extern const mp_limb_t bell_number_tab[]; FLINT_DLL double arith_bell_number_size(ulong n); FLINT_DLL void arith_bell_number(fmpz_t b, ulong n); FLINT_DLL void arith_bell_number_bsplit(fmpz_t res, ulong n); FLINT_DLL void arith_bell_number_multi_mod(fmpz_t res, ulong n); FLINT_DLL void arith_bell_number_vec(fmpz * b, slong n); FLINT_DLL void arith_bell_number_vec_recursive(fmpz * b, slong n); FLINT_DLL void arith_bell_number_vec_multi_mod(fmpz * b, slong n); FLINT_DLL mp_limb_t arith_bell_number_nmod(ulong n, nmod_t mod); FLINT_DLL void arith_bell_number_nmod_vec(mp_ptr b, slong n, nmod_t mod); FLINT_DLL void arith_bell_number_nmod_vec_recursive(mp_ptr b, slong n, nmod_t mod); FLINT_DLL void arith_bell_number_nmod_vec_series(mp_ptr b, slong n, 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 }; FLINT_DLL double arith_euler_number_size(ulong n); FLINT_DLL void arith_euler_number_vec(fmpz * res, slong n); FLINT_DLL void _arith_euler_number_zeta(fmpz_t res, ulong n); FLINT_DLL void arith_euler_number(fmpz_t res, ulong n); FLINT_DLL 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 }; FLINT_DLL void _arith_bernoulli_number(fmpz_t num, fmpz_t den, ulong n); FLINT_DLL void arith_bernoulli_number(fmpq_t x, ulong n); FLINT_DLL void _arith_bernoulli_number_vec(fmpz * num, fmpz * den, slong n); FLINT_DLL void arith_bernoulli_number_vec(fmpq * num, slong n); FLINT_DLL void arith_bernoulli_number_denom(fmpz_t den, ulong n); FLINT_DLL double arith_bernoulli_number_size(ulong n); FLINT_DLL void arith_bernoulli_polynomial(fmpq_poly_t poly, ulong n); FLINT_DLL void _arith_bernoulli_number_zeta(fmpz_t num, fmpz_t den, ulong n); FLINT_DLL void _arith_bernoulli_number_vec_multi_mod(fmpz * num, fmpz * den, slong n); FLINT_DLL void _arith_bernoulli_number_vec_recursive(fmpz * num, fmpz * den, slong n); FLINT_DLL void _arith_bernoulli_number_vec_zeta(fmpz * num, fmpz * den, slong n); /* Cyclotomic polynomials ****************************************************/ #define _arith_cyclotomic_polynomial _fmpz_poly_cyclotomic #define arith_cyclotomic_polynomial fmpz_poly_cyclotomic FLINT_DLL void _arith_cos_minpoly(fmpz * coeffs, slong d, ulong n); FLINT_DLL void arith_cos_minpoly(fmpz_poly_t poly, ulong n); /* 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 ***********************************************************/ FLINT_DLL 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]; ARITH_INLINE void trig_prod_init(trig_prod_t sum) { sum->n = 0; sum->prefactor = 1; sum->sqrt_p = 1; sum->sqrt_q = 1; } FLINT_DLL 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]; FLINT_DLL void arith_number_of_partitions_nmod_vec(mp_ptr res, slong len, nmod_t mod); FLINT_DLL void arith_number_of_partitions_vec(fmpz * res, slong len); FLINT_DLL void arith_number_of_partitions_mpfr(mpfr_t x, ulong n); FLINT_DLL void arith_number_of_partitions(fmpz_t x, ulong n); /* Number of sums of squares representations *********************************/ FLINT_DLL void arith_sum_of_squares(fmpz_t r, ulong k, const fmpz_t n); FLINT_DLL void arith_sum_of_squares_vec(fmpz * r, ulong k, slong n); #ifdef __cplusplus } #endif #endif flint2-2.8.4/arith/000077500000000000000000000000001414523752600140435ustar00rootroot00000000000000flint2-2.8.4/arith/bell_number.c000066400000000000000000000012041414523752600164720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" void arith_bell_number(fmpz_t b, ulong n) { if (n < BELL_NUMBER_TAB_SIZE) fmpz_set_ui(b, bell_number_tab[n]); else if (n < 5000) arith_bell_number_bsplit(b, n); else arith_bell_number_multi_mod(b, n); } flint2-2.8.4/arith/bell_number_bsplit.c000066400000000000000000000046241414523752600200600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "arith.h" static slong _bell_series_cutoff(slong n) { double N, log_N, log_pow, log_fac; N = n; log_N = (N==0 ? 0 : log(N)); log_pow = n * log_N; log_fac = N*log_N - N; while (log_pow - log_fac >= -2) { N++; log_N = log(N); log_pow = n * log_N; log_fac += log_N; } return N; } static void _mpz_bell_bsplit(mpz_t P, mpz_t Q, slong a, slong b, slong n, slong bmax) { if (b - a < 20) { mpz_t u; slong k; mpz_init(u); flint_mpz_set_ui(P, UWORD(0)); flint_mpz_set_ui(Q, UWORD(0)); flint_mpz_set_ui(Q, (b - 1 == bmax) ? UWORD(1) : b); for (k = b - 1; k >= a; k--) { flint_mpz_set_ui(u, k); flint_mpz_pow_ui(u, u, n); mpz_addmul(P, Q, u); if (k != a) flint_mpz_mul_ui(Q, Q, k); } mpz_clear(u); } else { slong m; mpz_t P1, Q2; m = (a + b) / 2; mpz_init(P1); mpz_init(Q2); _mpz_bell_bsplit(P1, Q, a, m, n, bmax); _mpz_bell_bsplit(P, Q2, m, b, n, bmax); mpz_mul(Q, Q, Q2); mpz_addmul(P, P1, Q2); mpz_clear(P1); mpz_clear(Q2); } } void arith_bell_number_bsplit(fmpz_t b, ulong n) { slong N; flint_bitcnt_t prec; mpz_t P, Q; mpfr_t Pf, Qf, E, one; N = _bell_series_cutoff(n); mpz_init(P); mpz_init(Q); _mpz_bell_bsplit(P, Q, 1, N + 1, n, N); prec = mpz_sizeinbase(P, 2) - mpz_sizeinbase(Q, 2) + 10; mpfr_init2(Pf, prec); mpfr_init2(Qf, prec); mpfr_init2(E, prec); mpfr_init2(one, 2); mpfr_set_z(Pf, P, GMP_RNDN); mpfr_set_z(Qf, Q, GMP_RNDN); mpfr_set_ui(one, 1, GMP_RNDN); mpfr_exp(E, one, GMP_RNDN); mpfr_mul(Qf, Qf, E, GMP_RNDN); mpfr_div(Pf, Pf, Qf, GMP_RNDN); mpfr_get_z(P, Pf, GMP_RNDN); fmpz_set_mpz(b, P); mpfr_clear(one); mpfr_clear(Pf); mpfr_clear(Qf); mpfr_clear(E); mpz_clear(P); mpz_clear(Q); } flint2-2.8.4/arith/bell_number_multi_mod.c000066400000000000000000000025671414523752600205600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" 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; slong k, num_primes; flint_bitcnt_t size, prime_bits; size = arith_bell_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)); 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_nmod(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); } flint2-2.8.4/arith/bell_number_nmod.c000066400000000000000000000056741414523752600175260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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(ulong n, nmod_t mod) { mp_limb_t s, t, u; mp_ptr facs, pows; slong i, j; 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) { mp_ptr bvec = flint_malloc(sizeof(mp_limb_t) * (n + 1)); arith_bell_number_nmod_vec_recursive(bvec, n + 1, mod); s = bvec[n]; flint_free(bvec); return s; } /* 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] = n_mulmod2_preinv(facs[i + 1], i + 1, mod.n, mod.ninv); /* Compute powers */ pows = flint_calloc(n + 1, sizeof(mp_limb_t)); pows[0] = n_powmod2_ui_preinv(0, n, mod.n, mod.ninv); pows[1] = n_powmod2_ui_preinv(1, n, mod.n, mod.ninv); for (i = 2; i <= n; i++) { if (pows[i] == 0) pows[i] = n_powmod2_ui_preinv(i, n, mod.n, mod.ninv); for (j = 2; j <= i && i * j <= n; j++) if (pows[i * j] == 0) pows[i * j] = n_mulmod2_preinv(pows[i], pows[j], mod.n, mod.ninv); } for (s = t = i = 0; i <= n; i++) { if (i % 2 == 0) t = n_addmod(t, facs[i], mod.n); else t = n_submod(t, facs[i], mod.n); u = pows[n - i]; u = n_mulmod2_preinv(u, facs[n - i], mod.n, mod.ninv); u = n_mulmod2_preinv(u, t, mod.n, mod.ninv); s = n_addmod(s, u, mod.n); } /* Remove (n!)^2 */ u = n_invmod(facs[0], mod.n); u = n_mulmod2_preinv(u, u, mod.n, mod.ninv); s = n_mulmod2_preinv(s, u, mod.n, mod.ninv); flint_free(facs); flint_free(pows); return s; } flint2-2.8.4/arith/bell_number_nmod_vec.c000066400000000000000000000011601414523752600203450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" void arith_bell_number_nmod_vec(mp_ptr b, slong n, nmod_t mod) { if (n < 2000 || mod.n <= n) arith_bell_number_nmod_vec_recursive(b, n, mod); else arith_bell_number_nmod_vec_series(b, n, mod); } flint2-2.8.4/arith/bell_number_nmod_vec_recursive.c000066400000000000000000000016641414523752600224450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" void arith_bell_number_nmod_vec_recursive(mp_ptr b, slong n, nmod_t mod) { slong i, k; mp_ptr t; if (n < BELL_NUMBER_TAB_SIZE) { for (i = 0; i < n; i++) b[i] = n_mod2_preinv(bell_number_tab[i], mod.n, mod.ninv); return; } n -= 1; t = _nmod_vec_init(n); t[0] = b[0] = b[1] = 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]; } _nmod_vec_clear(t); } flint2-2.8.4/arith/bell_number_nmod_vec_series.c000066400000000000000000000021771414523752600217300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" void arith_bell_number_nmod_vec_series(mp_ptr res, slong n, nmod_t mod) { mp_limb_t fac, c; mp_ptr tmp; slong k; if (n < 1) return; tmp = flint_malloc(sizeof(mp_limb_t) * n); /* Divide by factorials */ fac = n_factorial_mod2_preinv(n-1, mod.n, mod.ninv); c = n_invmod(fac, mod.n); for (k = n - 1; k > 0; k--) { tmp[k] = c; c = n_mulmod2_preinv(c, k, mod.n, mod.ninv); } tmp[0] = UWORD(0); _nmod_poly_exp_series(res, tmp, n, n, mod); /* Multiply by factorials */ c = UWORD(1); for (k = 1; k < n; k++) { c = n_mulmod2_preinv(c, k, mod.n, mod.ninv); res[k] = n_mulmod2_preinv(res[k], c, mod.n, mod.ninv); } flint_free(tmp); } flint2-2.8.4/arith/bell_number_size.c000066400000000000000000000010641414523752600175300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" double arith_bell_number_size(ulong n) { if (n == 0) return 2; return n * log(0.792 * n/log(n+1)) * 1.44269504088896 + 2; } flint2-2.8.4/arith/bell_number_vec.c000066400000000000000000000011061414523752600173300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/arith/bell_number_vec_multi_mod.c000066400000000000000000000051051414523752600214040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.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); 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); } flint2-2.8.4/arith/bell_number_vec_recursive.c000066400000000000000000000016661414523752600214320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/arith/bernoulli_number.c000066400000000000000000000011721414523752600175530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" void _arith_bernoulli_number(fmpz_t num, fmpz_t den, ulong n) { _arith_bernoulli_number_zeta(num, den, n); } void arith_bernoulli_number(fmpq_t x, ulong n) { _arith_bernoulli_number(fmpq_numref(x), fmpq_denref(x), n); } flint2-2.8.4/arith/bernoulli_number_denom.c000066400000000000000000000045771414523752600207510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } } flint2-2.8.4/arith/bernoulli_number_size.c000066400000000000000000000012541414523752600206060ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/arith/bernoulli_number_vec.c000066400000000000000000000021101414523752600204010ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 if (n < 3900) _arith_bernoulli_number_vec_zeta(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); } flint2-2.8.4/arith/bernoulli_number_vec_multi_mod.c000066400000000000000000000077041414523752600224700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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_fdiv_ui(den + 2*k, mod.n); 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); } flint2-2.8.4/arith/bernoulli_number_vec_recursive.c000066400000000000000000000100551414523752600224770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_abort(); #else if (m < WORD(32)) prodsize = 6; else if (m < WORD(1286)) prodsize = 3; else if (m < WORD(46336)) prodsize = 2; else flint_abort(); #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); } flint2-2.8.4/arith/bernoulli_number_vec_zeta.c000066400000000000000000000011761414523752600214370ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" void _arith_bernoulli_number_vec_zeta(fmpz * num, fmpz * den, slong n) { slong i; /* Go backwards to exploit MPFR cache for pi */ for (i = n - 1; i >= 0; i--) _arith_bernoulli_number_zeta(num + i, den + i, i); } flint2-2.8.4/arith/bernoulli_number_zeta.c000066400000000000000000000033351414523752600206010ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" void _arith_bernoulli_number_zeta(fmpz_t num, fmpz_t den, ulong n) { mpz_t r; mpfr_t t, u, z, pi; flint_bitcnt_t prec, pi_prec; 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; } prec = arith_bernoulli_number_size(n) + fmpz_bits(den); prec += 10 + 2*FLINT_BIT_COUNT(n); prec = prec * 1.001; pi_prec = prec; mpz_init(r); mpfr_init2(t, prec); mpfr_init2(u, prec); mpfr_init2(z, prec); mpfr_init2(pi, pi_prec); /* t = 2 * n! / (2*pi)^n */ flint_mpz_fac_ui(r, n); mpfr_set_z(t, r, GMP_RNDN); mpfr_mul_2exp(t, t, 1, GMP_RNDN); mpfr_const_pi(pi, GMP_RNDN); mpfr_mul_2exp(pi, pi, 1, GMP_RNDN); mpfr_pow_ui(pi, pi, n, GMP_RNDN); mpfr_div(t, t, pi, GMP_RNDN); /* t = t / zeta(n) */ mpfr_zeta_inv_euler_product(z, n, 0); mpfr_div(t, t, z, GMP_RNDN); /* round numerator */ fmpz_get_mpz(r, den); mpfr_mul_z(t, t, r, GMP_RNDN); mpfr_round(t, t); mpfr_get_z(r, t, GMP_RNDN); fmpz_set_mpz(num, r); if (n % 4 == 0) fmpz_neg(num, num); mpz_clear(r); mpfr_clear(t); mpfr_clear(u); mpfr_clear(z); mpfr_clear(pi); } flint2-2.8.4/arith/bernoulli_polynomial.c000066400000000000000000000030371414523752600204500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/arith/cyclotomic_cos_polynomial.c000066400000000000000000000203031414523752600214610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "arith.h" #define MAX_32BIT 58 static const int lookup_table[MAX_32BIT][28] = { {-1, 1}, {1, 1}, {1, 2}, {0, 1}, {-1, 2, 4}, {-1, 2}, {-1, -4, 4, 8}, {-1, 0, 2}, {1, -6, 0, 8}, {-1, -2, 4}, {1, 6, -12, -32, 16, 32}, {-3, 0, 4}, {-1, 6, 24, -32, -80, 32, 64}, {1, -4, -4, 8}, {1, 8, -16, -8, 16}, {1, 0, -8, 0, 8}, {1, -8, -40, 80, 240, -192, -448, 128, 256}, {-1, -6, 0, 8}, {1, 10, -40, -160, 240, 672, -448, -1024, 256, 512}, {5, 0, -20, 0, 16}, {1, -16, 32, 48, -96, -32, 64}, {-1, 6, 12, -32, -16, 32}, {-1, -12, 60, 280, -560, -1792, 1792, 4608, -2304, -5120, 1024, 2048}, {1, 0, -16, 0, 16}, {-1, 10, 100, -40, -800, 32, 2240, 0, -2560, 0, 1024}, {-1, -6, 24, 32, -80, -32, 64}, {1, 18, 0, -240, 0, 864, 0, -1152, 0, 512}, {-7, 0, 56, 0, -112, 0, 64}, {-1, 14, 112, -448, -2016, 4032, 13440, -15360, -42240, 28160, 67584, -24576, -53248, 8192, 16384}, {1, -8, -16, 8, 16}, {-1, -16, 112, 672, -2016, -8064, 13440, 42240, -42240, -112640, 67584, 159744, -53248, -114688, 16384, 32768}, {1, 0, -32, 0, 160, 0, -256, 0, 128}, {1, -24, 48, 344, -688, -1088, 2176, 1280, -2560, -512, 1024}, {1, 8, -40, -80, 240, 192, -448, -128, 256}, {1, 16, -160, -368, 1760, 2272, -7232, -5504, 13824, 5632, -12288, -2048, 4096}, {-3, 0, 36, 0, -96, 0, 64}, {-1, 18, 180, -960, -5280, 14784, 59136, -101376, -329472, 366080, 1025024, -745472, -1863680, 860160, 1966080, -524288, -1114112, 131072, 262144}, {-1, 10, 40, -160, -240, 672, 448, -1024, -256, 512}, {1, 24, -48, -632, 1264, 3296, -6592, -6784, 13568, 6144, -12288, -2048, 4096}, {1, 0, -48, 0, 304, 0, -512, 0, 256}, {1, -20, -220, 1320, 7920, -25344, -109824, 219648, 768768, -1025024, -3075072, 2795520, 7454720, -4587520, -11141120, 4456448, 10027008, -2359296, -4980736, 524288, 1048576}, {1, 16, 32, -48, -96, 32, 64}, {1, 22, -220, -1760, 7920, 41184, -109824, -439296, 768768, 2562560, -3075072, -8945664, 7454720, 19496960, -11141120, -26738688, 10027008, 22413312, -4980736, -10485760, 1048576, 2097152}, {-11, 0, 220, 0, -1232, 0, 2816, 0, -2816, 0, 1024}, {1, -24, -144, 248, 1680, -864, -7168, 1152, 13824, -512, -12288, 0, 4096}, {1, -12, -60, 280, 560, -1792, -1792, 4608, 2304, -5120, -1024, 2048}, {-1, -24, 264, 2288, -11440, -64064, 192192, 823680, -1647360, -5857280, 8200192, 25346048, -25346048, -70189056, 50135040, 127008768, -63504384, -149422080, 49807360, 110100480, -22020096, -46137344, 4194304, 8388608}, {1, 0, -64, 0, 320, 0, -512, 0, 256}, {-1, 28, 196, -2968, -3136, 66304, 18816, -658816, -53760, 3587584, 78848, -11741184, -57344, 24084480, 16384, -31195136, 0, 24772608, 0, -11010048, 0, 2097152}, {-1, -10, 100, 40, -800, -32, 2240, 0, -2560, 0, 1024}, {1, 32, -64, -1504, 3008, 16832, -33664, -76288, 152576, 173568, -347136, -210944, 421888, 131072, -262144, -32768, 65536}, {13, 0, -364, 0, 2912, 0, -9984, 0, 16640, 0, -13312, 0, 4096}, {-1, 26, 364, -2912, -21840, 96096, 512512, -1464320, -6223360, 12446720, 44808192, -65175552, -206389248, 222265344, 635043840, -508035072, -1333592064, 784465920, 1917583360, -807403520, -1857028096, 530579456, 1157627904, -201326592, -419430400, 33554432, 67108864}, {-1, 18, 0, -240, 0, 864, 0, -1152, 0, 512}, {1, 24, -432, -1208, 15216, 28064, -185024, -263424, 1149184, 1250304, -4177920, -3356672, 9375744, 5324800, -13123584, -4947968, 11141120, 2490368, -5242880, -524288, 1048576}, {1, 0, -96, 0, 1376, 0, -6656, 0, 13568, 0, -12288, 0, 4096}, {1, -40, 80, 2120, -4240, -31648, 63296, 194432, -388864, -613376, 1226752, 1087488, -2174976, -1097728, 2195456, 589824, -1179648, -131072, 262144}, {-1, -14, 112, 448, -2016, -4032, 13440, 15360, -42240, -28160, 67584, 24576, -53248, -8192, 16384} }; /* The coefficients in 2^d * \prod_{i=1}^d (x - cos(a_i)) are easily bounded using the binomial theorem. */ static slong magnitude_bound(slong d) { slong res; fmpz_t t; fmpz_init(t); fmpz_bin_uiui(t, d, d / 2); res = fmpz_bits(t); fmpz_clear(t); return FLINT_ABS(res) + d; } static void fmpz_mul_or_div_2exp(fmpz_t x, fmpz_t y, slong s) { if (s >= 0) fmpz_mul_2exp(x, y, s); else fmpz_fdiv_q_2exp(x, y, -s); } /* Balanced product of linear factors (x+alpha_i) using fixed-point arithmetic with prec bits */ static void balanced_product(fmpz * c, fmpz * alpha, slong len, slong prec) { if (len == 1) { fmpz_one(c + 1); fmpz_mul_2exp(c + 1, c + 1, prec); fmpz_set(c, alpha); } else if (len == 2) { fmpz_mul(c, alpha, alpha + 1); fmpz_fdiv_q_2exp(c, c, prec); fmpz_add(c + 1, alpha, alpha + 1); fmpz_one(c + 2); fmpz_mul_2exp(c + 2, c + 2, prec); } else { fmpz *L, *R; slong i, m; m = len / 2; L = _fmpz_vec_init(len + 2); R = L + m + 1; balanced_product(L, alpha, m, prec); balanced_product(R, alpha + m, len - m, prec); _fmpz_poly_mul(c, R, len - m + 1, L, m + 1); for (i = 0; i < len + 1; i++) fmpz_fdiv_q_2exp(c + i, c + i, prec); _fmpz_vec_clear(L, len + 2); } } void _arith_cos_minpoly(fmpz * coeffs, slong d, ulong n) { slong i, j; fmpz * alpha; fmpz_t half; mpfr_t t, u; flint_bitcnt_t prec; slong exp; if (n <= MAX_32BIT) { for (i = 0; i <= d; i++) fmpz_set_si(coeffs + i, lookup_table[n - 1][i]); return; } /* Direct formula for odd primes > 3 */ if (n_is_prime(n)) { slong s = (n - 1) / 2; switch (s % 4) { case 0: fmpz_set_si(coeffs, WORD(1)); fmpz_set_si(coeffs + 1, -s); break; case 1: fmpz_set_si(coeffs, WORD(1)); fmpz_set_si(coeffs + 1, s + 1); break; case 2: fmpz_set_si(coeffs, WORD(-1)); fmpz_set_si(coeffs + 1, s); break; case 3: fmpz_set_si(coeffs, WORD(-1)); fmpz_set_si(coeffs + 1, -s - 1); break; } for (i = 2; i <= s; i++) { slong b = (s - i) % 2; fmpz_mul2_uiui(coeffs + i, coeffs + i - 2, s+i-b, s+2-b-i); fmpz_divexact2_uiui(coeffs + i, coeffs + i, i, i-1); fmpz_neg(coeffs + i, coeffs + i); } return; } prec = magnitude_bound(d) + 5 + FLINT_BIT_COUNT(d); alpha = _fmpz_vec_init(d); fmpz_init(half); mpfr_init2(t, prec); mpfr_init2(u, prec); fmpz_one(half); fmpz_mul_2exp(half, half, prec - 1); mpfr_const_pi(t, prec); mpfr_div_ui(t, t, n, MPFR_RNDN); for (i = j = 0; j < d; i++) { if (n_gcd(n, i) == 1) { mpfr_mul_ui(u, t, 2 * i, MPFR_RNDN); mpfr_cos(u, u, MPFR_RNDN); mpfr_neg(u, u, MPFR_RNDN); exp = mpfr_get_z_2exp(_fmpz_promote(alpha + j), u); _fmpz_demote_val(alpha + j); fmpz_mul_or_div_2exp(alpha + j, alpha + j, exp + prec); j++; } } balanced_product(coeffs, alpha, d, prec); /* Scale and round */ for (i = 0; i < d + 1; i++) { slong r = d; if ((n & (n - 1)) == 0) r--; fmpz_mul_2exp(coeffs + i, coeffs + i, r); fmpz_add(coeffs + i, coeffs + i, half); fmpz_fdiv_q_2exp(coeffs + i, coeffs + i, prec); } fmpz_clear(half); mpfr_clear(t); mpfr_clear(u); _fmpz_vec_clear(alpha, d); } void arith_cos_minpoly(fmpz_poly_t poly, ulong n) { if (n == 0) { fmpz_poly_set_ui(poly, UWORD(1)); } else { slong d = (n <= 2) ? 1 : n_euler_phi(n) / 2; fmpz_poly_fit_length(poly, d + 1); _arith_cos_minpoly(poly->coeffs, d, n); _fmpz_poly_set_length(poly, d + 1); } } flint2-2.8.4/arith/dedekind_cosine_sum_factored.c000066400000000000000000000161171414523752600220570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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]); } flint2-2.8.4/arith/divisors.c000066400000000000000000000102611414523752600160510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" #include "fmpz.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); } flint2-2.8.4/arith/euler_number.c000066400000000000000000000007541414523752600167010ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" void arith_euler_number(fmpz_t res, ulong n) { _arith_euler_number_zeta(res, n); } flint2-2.8.4/arith/euler_number_size.c000066400000000000000000000011741414523752600177300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/arith/euler_number_vec.c000066400000000000000000000071761414523752600175430ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/arith/euler_number_zeta.c000066400000000000000000000027261414523752600177250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" void _arith_euler_number_zeta(fmpz_t res, ulong n) { mpz_t r; mpfr_t t, z, pi; flint_bitcnt_t prec, pi_prec; if (n % 2) { fmpz_zero(res); return; } if (n < SMALL_EULER_LIMIT) { fmpz_set_ui(res, euler_number_small[n / 2]); if (n % 4 == 2) fmpz_neg(res, res); return; } prec = arith_euler_number_size(n) + 10; pi_prec = prec + FLINT_BIT_COUNT(n); mpz_init(r); mpfr_init2(t, prec); mpfr_init2(z, prec); mpfr_init2(pi, pi_prec); flint_mpz_fac_ui(r, n); mpfr_set_z(t, r, GMP_RNDN); mpfr_mul_2exp(t, t, n + 2, GMP_RNDN); /* pi^(n + 1) * L(n+1) */ mpfr_zeta_inv_euler_product(z, n + 1, 1); mpfr_const_pi(pi, GMP_RNDN); mpfr_pow_ui(pi, pi, n + 1, GMP_RNDN); mpfr_mul(z, z, pi, GMP_RNDN); mpfr_div(t, t, z, GMP_RNDN); /* round */ mpfr_round(t, t); mpfr_get_z(r, t, GMP_RNDN); fmpz_set_mpz(res, r); if (n % 4 == 2) fmpz_neg(res, res); mpz_clear(r); mpfr_clear(t); mpfr_clear(z); mpfr_clear(pi); } flint2-2.8.4/arith/euler_polynomial.c000066400000000000000000000017251414523752600175730ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/arith/harmonic_number.c000066400000000000000000000013421414523752600173570ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/arith/inlines.c000066400000000000000000000010521414523752600156460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ARITH_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "arith.h" flint2-2.8.4/arith/landau_function_vec.c000066400000000000000000000023121414523752600202130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "arith.h" 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); } flint2-2.8.4/arith/number_of_partitions.c000066400000000000000000000055071414523752600204460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "arith.h" /* This nice round number precisely fits on 32 bits */ #define NUMBER_OF_SMALL_PARTITIONS 128 FLINT_DLL 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) }; void arith_number_of_partitions(fmpz_t x, ulong n) { if (n < NUMBER_OF_SMALL_PARTITIONS) { fmpz_set_ui(x, partitions_lookup[n]); } else { mpfr_t t; mpfr_init(t); arith_number_of_partitions_mpfr(t, n); mpfr_get_z(_fmpz_promote(x), t, MPFR_RNDN); _fmpz_demote_val(x); mpfr_clear(t); } } flint2-2.8.4/arith/number_of_partitions_mpfr.c000066400000000000000000000301371414523752600214670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "arith.h" #define DOUBLE_PREC 53 #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 */ #define VERBOSE 0 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_needed_terms(ulong n) { slong N; for (N = 1; partitions_remainder_bound_log2(n, N) > 10; N++); for ( ; partitions_remainder_bound(n, N) > (n > 1500 ? 0.25 : 1); 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(ulong 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; } double cos_pi_pq(mp_limb_signed_t p, mp_limb_signed_t q) { /* Force 0 <= p < q */ p = FLINT_ABS(p); p %= (2 * q); if (p >= q) p = 2 * q - p; if (4 * p <= q) return cos(p * PI / q); else if (4 * p < 3 * q) return sin((q - 2*p) * PI / (2 * q)); else return -cos((q - p) * PI / q); } void mpfr_sqrt_z(mpfr_t x, mpz_t z, mpfr_rnd_t rnd) { if (mpz_fits_ulong_p(z)) mpfr_sqrt_ui(x, flint_mpz_get_ui(z), rnd); else { mpfr_set_z(x, z, rnd); mpfr_sqrt(x, x, rnd); } } void mpfr_set_fmpz(mpfr_t c, const fmpz_t b) { if (COEFF_IS_MPZ(*b)) mpfr_set_z(c, COEFF_TO_PTR(*b), MPFR_RNDN); else mpfr_set_si(c, *b, MPFR_RNDN); } void mpfr_mul_fmpz(mpfr_t c, mpfr_srcptr a, const fmpz_t b) { if (COEFF_IS_MPZ(*b)) mpfr_mul_z(c, a, COEFF_TO_PTR(*b), MPFR_RNDN); else mpfr_mul_si(c, a, *b, MPFR_RNDN); } void mpfr_add_fmpz(mpfr_t c, mpfr_srcptr a, const fmpz_t b) { if (COEFF_IS_MPZ(*b)) mpfr_add_z(c, a, COEFF_TO_PTR(*b), MPFR_RNDN); else mpfr_add_si(c, a, *b, MPFR_RNDN); } void _fmpz_poly_evaluate_mpfr(mpfr_t res, const fmpz * f, slong len, const mpfr_t a) { if (len == 0) mpfr_set_ui(res, 0, MPFR_RNDN); else if (len == 1) mpfr_set_fmpz(res, f); else { slong i = len - 1; mpfr_t t; mpfr_init2(t, mpfr_get_prec(res)); mpfr_set_fmpz(res, f + i); for (i = len - 2; i >= 0; i--) { mpfr_mul(t, res, a, MPFR_RNDN); mpfr_add_fmpz(res, t, f + i); } mpfr_clear(t); } } void fmpz_poly_evaluate_mpfr(mpfr_t res, const fmpz_poly_t f, const mpfr_t a) { if (res == a) { mpfr_t t; mpfr_init2(t, mpfr_get_prec(res)); _fmpz_poly_evaluate_mpfr(t, f->coeffs, f->length, a); mpfr_swap(res, t); mpfr_clear(t); } else { _fmpz_poly_evaluate_mpfr(res, f->coeffs, f->length, a); } } void findroot(mpfr_t x, fmpz_poly_t poly, double x0) { slong i; slong prec, initial_prec, target_prec, guard_bits; slong precs[FLINT_BITS]; fmpz_poly_t poly2; mpfr_t t, u, xn; initial_prec = 48; target_prec = mpfr_get_prec(x) + 32; mpfr_init2(t, 53); mpfr_init2(u, 53); mpfr_init2(xn, 53); mpfr_set_d(xn, x0, MPFR_RNDN); fmpz_poly_init(poly2); fmpz_poly_derivative(poly2, poly); guard_bits = fmpz_poly_max_bits(poly2); guard_bits = FLINT_ABS(guard_bits); for (i = 0, prec = target_prec; prec >= initial_prec; i++) { precs[i] = prec; prec = prec / 2 + 8; } for (i--; i >= 0; i--) { mpfr_set_prec(t, precs[i] + guard_bits); mpfr_set_prec(u, precs[i] + guard_bits); mpfr_prec_round(xn, precs[i], MPFR_RNDN); fmpz_poly_evaluate_mpfr(t, poly, xn); fmpz_poly_evaluate_mpfr(u, poly2, xn); mpfr_div(t, t, u, MPFR_RNDN); mpfr_sub(xn, xn, t, MPFR_RNDN); } mpfr_set(x, xn, MPFR_RNDN); fmpz_poly_clear(poly2); mpfr_clear(t); mpfr_clear(u); mpfr_clear(xn); } void cos_minpoly(fmpz_poly_t poly, slong p, slong q) { if (p % 2 == 0) arith_cos_minpoly(poly, q); else arith_cos_minpoly(poly, 2 * q); } int use_newton(slong prec, slong q) { if (q < 250 && prec > 400 + 4*q*q) return 1; return 0; } void mpfr_cos_pi_pq(mpfr_t t, mp_limb_signed_t p, mp_limb_signed_t q) { /* Force 0 <= p < q */ p = FLINT_ABS(p); p %= (2 * q); if (p >= q) p = 2 * q - p; if (use_newton(mpfr_get_prec(t), q)) { fmpz_poly_t poly; slong d; fmpz_poly_init(poly); d = n_gcd(q, p); q /= d; p /= d; cos_minpoly(poly, p, q); findroot(t, poly, cos(3.1415926535897932385 * p / q)); fmpz_poly_clear(poly); } else { mpfr_const_pi(t, MPFR_RNDN); if (4 * p <= q) { mpfr_mul_si(t, t, p, MPFR_RNDN); mpfr_div_ui(t, t, q, MPFR_RNDN); mpfr_cos(t, t, MPFR_RNDN); } else if (4 * p < 3 * q) { mpfr_mul_si(t, t, q - 2*p, MPFR_RNDN); mpfr_div_ui(t, t, 2 * q, MPFR_RNDN); mpfr_sin(t, t, MPFR_RNDN); } else { mpfr_mul_si(t, t, q - p, MPFR_RNDN); mpfr_div_ui(t, t, q, MPFR_RNDN); mpfr_cos(t, t, MPFR_RNDN); mpfr_neg(t, t, MPFR_RNDN); } } } void eval_trig_prod(mpfr_t sum, trig_prod_t prod) { int i; if (prod->prefactor == 0) { mpfr_set_ui(sum, UWORD(0), MPFR_RNDN); return; } if (mpfr_get_prec(sum) <= DOUBLE_PREC) { double s; s = prod->prefactor * sqrt((double)prod->sqrt_p/(double)prod->sqrt_q); for (i = 0; i < prod->n; i++) s *= cos_pi_pq(prod->cos_p[i], prod->cos_q[i]); mpfr_set_d(sum, s, MPFR_RNDN); } else { mp_limb_t v; mpfr_t t; mpfr_init2(t, mpfr_get_prec(sum)); mpfr_set_si(sum, prod->prefactor, MPFR_RNDN); v = n_gcd(prod->sqrt_p, prod->sqrt_q); prod->sqrt_p /= v; prod->sqrt_q /= v; if (prod->sqrt_p != 1) { mpfr_sqrt_ui(t, prod->sqrt_p, MPFR_RNDN); mpfr_mul(sum, sum, t, MPFR_RNDN); } if (prod->sqrt_q != 1) { mpfr_sqrt_ui(t, prod->sqrt_q, MPFR_RNDN); mpfr_div(sum, sum, t, MPFR_RNDN); } for (i = 0; i < prod->n; i++) { mpfr_cos_pi_pq(t, prod->cos_p[i], prod->cos_q[i]); mpfr_mul(sum, sum, t, MPFR_RNDN); } mpfr_clear(t); } } void sinh_cosh_divk_precomp(mpfr_t sh, mpfr_t ch, mpfr_t ex, slong k) { mpfr_t t; #if MPFR_VERSION_MAJOR >= 4 mpfr_rootn_ui(ch, ex, k, MPFR_RNDN); #else mpfr_root(ch, ex, k, MPFR_RNDN); #endif /* The second term doesn't need full precision, but this doesn't affect performance that much... */ mpfr_init2(t, mpfr_get_prec(ch)); mpfr_ui_div(t, 1, ch, MPFR_RNDN); mpfr_sub(sh, ch, t, MPFR_RNDN); mpfr_add(ch, ch, t, MPFR_RNDN); mpfr_div_2exp(ch, ch, 1, MPFR_RNDN); mpfr_div_2exp(sh, sh, 1, MPFR_RNDN); mpfr_clear(t); } void _arith_number_of_partitions_mpfr(mpfr_t x, ulong n, slong N0, slong N) { trig_prod_t prod; mpfr_t acc, C, t1, t2, t3, t4, exp1; mpz_t n24; double Cd; slong k; slong prec, guard_bits; #if VERBOSE timeit_t t0; #endif if (n <= 2) { mpfr_set_ui(x, FLINT_MAX(1, n), MPFR_RNDN); return; } /* Compute initial precision */ guard_bits = 2 * FLINT_BIT_COUNT(N) + 32; prec = partitions_remainder_bound_log2(n, N0) + guard_bits; prec = FLINT_MAX(prec, DOUBLE_PREC); mpfr_set_prec(x, prec); mpfr_init2(acc, prec); mpfr_init2(C, prec); mpfr_init2(t1, prec); mpfr_init2(t2, prec); mpfr_init2(t3, prec); mpfr_init2(t4, prec); mpfr_set_ui(x, 0, MPFR_RNDN); mpfr_set_ui(acc, 0, MPFR_RNDN); mpz_init(n24); flint_mpz_set_ui(n24, n); flint_mpz_mul_ui(n24, n24, 24); flint_mpz_sub_ui(n24, n24, 1); #if VERBOSE timeit_start(t0); #endif /* C = (pi/6)*sqrt(24*n-1) */ mpfr_const_pi(t1, MPFR_RNDN); mpfr_sqrt_z(t2, n24, MPFR_RNDN); mpfr_mul(t1, t1, t2, MPFR_RNDN); mpfr_div_ui(C, t1, 6, MPFR_RNDN); Cd = mpfr_get_d(C, MPFR_RNDN); mpfr_init2(exp1, prec); mpfr_exp(exp1, C, prec); #if VERBOSE timeit_stop(t0); flint_printf("TERM 1: %wd ms\n", t0->cpu); #endif for (k = N0; k <= N; k++) { trig_prod_init(prod); arith_hrr_expsum_factored(prod, k, n % k); if (prod->prefactor != 0) { if (prec > DOUBLE_PREC) { prec = partitions_prec_bound(n, k, N); mpfr_set_prec(t1, prec); mpfr_set_prec(t2, prec); mpfr_set_prec(t3, prec); mpfr_set_prec(t4, prec); } /* Compute A_k(n) * sqrt(3/k) * 4 / (24*n-1) */ prod->prefactor *= 4; prod->sqrt_p *= 3; prod->sqrt_q *= k; eval_trig_prod(t1, prod); mpfr_div_z(t1, t1, n24, MPFR_RNDN); /* Multiply by (cosh(z) - sinh(z)/z) where z = C / k */ if (prec <= DOUBLE_PREC) { double z = Cd / k; mpfr_mul_d(t1, t1, cosh(z) - sinh(z)/z, MPFR_RNDN); } else { mpfr_div_ui(t2, C, k, MPFR_RNDN); if (k < 35) sinh_cosh_divk_precomp(t3, t4, exp1, k); else mpfr_sinh_cosh(t3, t4, t2, MPFR_RNDN); mpfr_div(t3, t3, t2, MPFR_RNDN); mpfr_sub(t2, t4, t3, MPFR_RNDN); mpfr_mul(t1, t1, t2, MPFR_RNDN); } /* Add to accumulator */ mpfr_add(acc, acc, t1, MPFR_RNDN); if (mpfr_get_prec(acc) > 2 * prec + 32) { mpfr_add(x, x, acc, MPFR_RNDN); mpfr_set_prec(acc, prec + 32); mpfr_set_ui(acc, 0, MPFR_RNDN); } } } mpfr_add(x, x, acc, MPFR_RNDN); mpz_clear(n24); mpfr_clear(acc); mpfr_clear(exp1); mpfr_clear(C); mpfr_clear(t1); mpfr_clear(t2); mpfr_clear(t3); mpfr_clear(t4); } void arith_number_of_partitions_mpfr(mpfr_t x, ulong n) { _arith_number_of_partitions_mpfr(x, n, 1, partitions_needed_terms(n)); } flint2-2.8.4/arith/number_of_partitions_nmod_vec.c000066400000000000000000000020731414523752600223130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/arith/number_of_partitions_vec.c000066400000000000000000000017761414523752600213070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/arith/profile/000077500000000000000000000000001414523752600155035ustar00rootroot00000000000000flint2-2.8.4/arith/profile/p-bernoulli.c000066400000000000000000000047031414523752600201030ustar00rootroot00000000000000/* Copyright 2009 William Hart Copyright 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "profiler.h" #include "flint.h" #include "fmpz_mat.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" typedef struct { ulong n; int algorithm; } bernoulli_vec_t; void sample(void * arg, ulong count) { fmpz * num; fmpz * den; bernoulli_vec_t * params = (bernoulli_vec_t *) arg; ulong n = params->n; slong i; int algorithm = params->algorithm; num = _fmpz_vec_init(n); den = _fmpz_vec_init(n); prof_start(); for (i = 0; i < count; i++) { if (algorithm == 0) { _arith_bernoulli_number_vec_recursive(num, den, n); } else if (algorithm == 1) { _arith_bernoulli_number_vec_multi_mod(num, den, n); } else if (algorithm == 2) { _arith_bernoulli_number_vec_zeta(num, den, n); mpfr_free_cache(); } } prof_stop(); _fmpz_vec_clear(num, n); _fmpz_vec_clear(den, n); } int main(void) { double min_recursive, min_multi_mod, min_zeta, max; bernoulli_vec_t params; slong n; flint_printf("n / recursive / multi_mod / zeta / best [times in us]\n"); for (n = 2; n <= 10000; n = (slong) ((double) n * 1.2) + 1) { params.n = n; if (n < 1500) { params.algorithm = 0; prof_repeat(&min_recursive, &max, sample, ¶ms); } else min_recursive = 0.0; params.algorithm = 1; prof_repeat(&min_multi_mod, &max, sample, ¶ms); params.algorithm = 2; prof_repeat(&min_zeta, &max, sample, ¶ms); flint_printf("%wd %.2f %.2f %.2f ", n, min_recursive, min_multi_mod, min_zeta); if (min_recursive && min_recursive < min_multi_mod && \ min_recursive < min_zeta) flint_printf("(recursive)\n"); else if (min_multi_mod < min_zeta) flint_printf("(multi_mod)\n"); else flint_printf("(zeta)\n"); } return 0; } flint2-2.8.4/arith/ramanujan_tau.c000066400000000000000000000051111414523752600170320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.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); } flint2-2.8.4/arith/stirling1.c000066400000000000000000000060621414523752600161270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" static void _rising_factorial(fmpz * res, slong a, slong b, slong trunc) { const slong span = b - a; switch (span) { case 0: fmpz_one(res); break; case 1: fmpz_set_ui(res, a); if (trunc > 1) fmpz_one(res+1); break; case 2: fmpz_set_ui(res, a); fmpz_mul_ui(res, res, a + UWORD(1)); if (trunc > 1) { fmpz_set_ui(res+1, 2*a + UWORD(1)); if (trunc > 2) fmpz_one(res+2); } break; case 3: fmpz_set_ui(res, a); fmpz_mul_ui(res, res, a + UWORD(1)); fmpz_mul_ui(res, res, a + UWORD(2)); if (trunc > 1) { fmpz_set_ui(res+1, 3*a); fmpz_mul_ui(res+1, res+1, a + UWORD(2)); fmpz_add_ui(res+1, res+1, 2); if (trunc > 2) { fmpz_set_ui(res+2, 3*(a+1)); if (trunc > 3) fmpz_one(res+3); } } break; default: { const slong mid = (a + b) / 2; const int chk = (b - a + 1 < trunc); /* i.e. nprod < trunc */ const slong nleft = chk ? mid - a + 1 : trunc; const slong nright = chk ? b - mid + 1 : trunc; fmpz *left = _fmpz_vec_init(nleft); fmpz *right = _fmpz_vec_init(nright); _rising_factorial(left, a, mid, trunc); _rising_factorial(right, mid, b, trunc); if (chk) _fmpz_poly_mul(res, right, nright, left, nleft); else _fmpz_poly_mullow(res, left, nleft, right, nright, trunc); _fmpz_vec_clear(left, nleft); _fmpz_vec_clear(right, nright); } } } void arith_stirling_number_1u(fmpz_t s, slong n, slong k) { /* Various special cases TODO: factorials, binomial coefficients, harmonic numbers ... */ if (k < 1) { fmpz_set_ui(s, (n == 0) & (k == 0)); } if (k >= n) { fmpz_set_ui(s, n == k); } else { fmpz *tmp = _fmpz_vec_init(k+1); _rising_factorial(tmp, 0, n, k+1); fmpz_set(s, tmp+k); _fmpz_vec_clear(tmp, k+1); } } void arith_stirling_number_1(fmpz_t s, slong n, slong k) { arith_stirling_number_1u(s, n, k); if ((n + k) % 2) fmpz_neg(s, s); } void arith_stirling_number_1u_vec(fmpz * row, slong n, slong klen) { if (klen > 0) _rising_factorial(row, 0, n, klen); } void arith_stirling_number_1_vec(fmpz * row, slong 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); } flint2-2.8.4/arith/stirling2.c000066400000000000000000000047751414523752600161410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" static __inline__ void _fmpz_addmul_alt(fmpz_t s, fmpz_t t, fmpz_t u, int parity) { if (parity % 2) fmpz_submul(s, t, u); else fmpz_addmul(s, t, u); } static void _fmpz_stirling2_powsum(fmpz_t s, slong n, slong k) { fmpz_t t, u; fmpz * bc; slong j, m, max_bc; fmpz_init(t); fmpz_init(u); max_bc = (k+1) / 2; bc = _fmpz_vec_init(max_bc + 1); fmpz_one(bc); for (j = 1; j <= max_bc; j++) { fmpz_set(bc+j, bc+j-1); fmpz_mul_ui(bc+j, bc+j, k+1-j); fmpz_divexact_ui(bc+j, bc+j, j); } fmpz_zero(s); for (j = 1; j <= k; j += 2) { fmpz_set_ui(u, j); fmpz_pow_ui(u, u, n); m = j; /* Process each m = 2^p * j */ while (1) { if (m > max_bc) _fmpz_addmul_alt(s, bc+k-m, u, k + m); else _fmpz_addmul_alt(s, bc+m, u, k + m); m *= 2; if (m > k) break; fmpz_mul_2exp(u, u, n); } } _fmpz_vec_clear(bc, max_bc + 1); fmpz_fac_ui(t, k); fmpz_divexact(s, s, t); fmpz_clear(t); fmpz_clear(u); } void arith_stirling_number_2(fmpz_t s, slong n, slong k) { if (n < 0 || k < 0 || k > n) { fmpz_zero(s); return; } /* Topmost diagonals */ if (k >= n - 1) { if (k == n) fmpz_one(s); else /* k == n - 1 */ { /* S(n,n-1) = binomial(n,2) */ fmpz_set_ui(s, n); fmpz_mul_ui(s, s, n-1); fmpz_divexact_ui(s, s, UWORD(2)); } return; } /* Leftmost columns */ if (k <= 2) { if (k < 2) fmpz_set_ui(s, k); else { /* S(n,2) = 2^(n-1)-1 */ fmpz_one(s); fmpz_mul_2exp(s, s, n-1); fmpz_sub_ui(s, s, UWORD(1)); } return; } _fmpz_stirling2_powsum(s, n, k); } void arith_stirling_number_2_vec(fmpz * row, slong n, slong klen) { slong m; for (m = 0; m <= n; m++) arith_stirling_number_2_vec_next(row, row, m, klen); } flint2-2.8.4/arith/stirlingmat.c000066400000000000000000000045761414523752600165600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "arith.h" void arith_stirling_number_1u_vec_next(fmpz * row, const fmpz * prev, slong n, slong klen) { slong k; if (klen > n) fmpz_one(row + n); if (n != 0 && klen != 0) fmpz_zero(row); for (k = FLINT_MIN(n, klen) - 1; k >= 1; k--) { fmpz_mul_ui(row + k, prev + k, n - UWORD(1)); fmpz_add(row + k, prev + k - 1, row + k); } for (k = n + 1; k < klen; k++) fmpz_zero(row + k); } void arith_stirling_number_1_vec_next(fmpz * row, const fmpz * prev, slong n, slong klen) { slong k; if (klen > n) fmpz_one(row + n); if (n != 0 && klen != 0) fmpz_zero(row); for (k = FLINT_MIN(n, klen) - 1; k >= 1; k--) { fmpz_mul_ui(row + k, prev + k, n - UWORD(1)); fmpz_sub(row + k, prev + k - 1, row + k); } for (k = n + 1; k < klen; k++) fmpz_zero(row + k); } void arith_stirling_number_2_vec_next(fmpz * row, const fmpz * prev, slong n, slong klen) { slong k; if (klen > n) fmpz_one(row + n); if (n != 0 && klen != 0) fmpz_zero(row); for (k = FLINT_MIN(n, klen) - 1; k >= 1; k--) { fmpz_mul_ui(row + k, prev + k, k); fmpz_add(row + k, prev + k - 1, row + k); } for (k = n + 1; k < klen; k++) fmpz_zero(row + k); } void arith_stirling_matrix_1u(fmpz_mat_t mat) { slong n; if (fmpz_mat_is_empty(mat)) return; for (n = 0; n < mat->r; n++) arith_stirling_number_1u_vec_next(mat->rows[n], mat->rows[n - (n != 0)], n, mat->c); } void arith_stirling_matrix_1(fmpz_mat_t mat) { slong n; if (fmpz_mat_is_empty(mat)) return; for (n = 0; n < mat->r; n++) arith_stirling_number_1_vec_next(mat->rows[n], mat->rows[n - (n != 0)], n, mat->c); } void arith_stirling_matrix_2(fmpz_mat_t mat) { slong n; if (fmpz_mat_is_empty(mat)) return; for (n = 0; n < mat->r; n++) arith_stirling_number_2_vec_next(mat->rows[n], mat->rows[n - (n != 0)], n, mat->c); } flint2-2.8.4/arith/sum_of_squares.c000066400000000000000000000050601414523752600172430ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.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, n, 1); fmpz_mul_ui(r, r, 8); } else { fmpz_tdiv_q_2exp(r, n, v); arith_divisor_sigma(r, r, 1); 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_printf("Exception (arith_sum_of_squares). n is too large.\n"); flint_abort(); } } flint2-2.8.4/arith/sum_of_squares_vec.c000066400000000000000000000036141414523752600201030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/arith/test/000077500000000000000000000000001414523752600150225ustar00rootroot00000000000000flint2-2.8.4/arith/test/t-bell_number.c000066400000000000000000000046151414523752600177230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "arith.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { fmpz * b1; fmpz * b2; slong n, k; const slong maxn = 400; FLINT_TEST_INIT(state); flint_printf("bell_number...."); fflush(stdout); b1 = _fmpz_vec_init(maxn); /* Consistency test */ for (n = 0; n < maxn; n++) arith_bell_number(b1 + n, n); for (n = 0; n < maxn; n++) { b2 = _fmpz_vec_init(n); arith_bell_number_vec(b2, n); if (!_fmpz_vec_equal(b1, b2, n)) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); abort(); } _fmpz_vec_clear(b2, n); } /* Compare with B_n = sum of Stirling numbers of 2nd kind */ for (n = 0; n < 1000; n += (n < 50) ? + 1 : n/4) { b2 = _fmpz_vec_init(n+1); arith_stirling_number_2_vec(b2, n, n+1); for (k = 1; k <= n; k++) fmpz_add(b2, b2, b2 + k); arith_bell_number(b1, n); if (!fmpz_equal(b1, b2)) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); fmpz_print(b1); flint_printf("\n"); fmpz_print(b2); flint_printf("\n"); abort(); } /* Also check nmod value */ { nmod_t mod; mp_limb_t bb; nmod_init(&mod, n_randtest_prime(state, 0)); bb = arith_bell_number_nmod(n, mod); if (fmpz_fdiv_ui(b1, mod.n) != bb) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); fmpz_print(b1); flint_printf("\n"); flint_printf("should be %wu mod %wu\n", bb, mod.n); abort(); } } _fmpz_vec_clear(b2, n+1); } _fmpz_vec_clear(b1, maxn); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-bell_number_multi_mod.c000066400000000000000000000022751414523752600217740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "arith.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("bell_number_multi_mod...."); fflush(stdout); 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_bsplit(b1, n); arith_bell_number_multi_mod(b2, n); if (!fmpz_equal(b1, b2)) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); abort(); } fmpz_clear(b1); fmpz_clear(b2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-bell_number_nmod.c000066400000000000000000000025111414523752600207310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "arith.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("bell_number_nmod...."); fflush(stdout); for (i = 0; i < 10; i++) { mp_ptr b; slong n; nmod_t mod; mp_limb_t p; n = n_randint(state, 1000); 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 (j = 0; j <= n; j++) { mp_limb_t u = arith_bell_number_nmod(j, mod); if (u != b[j]) { flint_printf("FAIL: p = %wu, i = %wd\n", p, j); abort(); } } _nmod_vec_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-bell_number_nmod_vec.c000066400000000000000000000025651414523752600215770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "arith.h" #include "nmod_vec.h" #include "ulong_extras.h" int main(void) { mp_ptr b1, b2; slong n; const slong maxn = 3000; FLINT_TEST_INIT(state); flint_printf("bell_number_nmod_vec...."); fflush(stdout); b1 = _nmod_vec_init(maxn); b2 = _nmod_vec_init(maxn); for (n = 0; n < maxn; n += (n < 50) ? + 1 : n/4) { nmod_t mod; mp_limb_t p; do { p = n_randtest_prime(state, 0); } while (p < n); nmod_init(&mod, p); arith_bell_number_nmod_vec_recursive(b1, n, mod); arith_bell_number_nmod_vec_series(b2, n, mod); if (!_nmod_vec_equal(b1, b2, n)) { flint_printf("FAIL:\n"); flint_printf("n = %wd\n", n); abort(); } } _nmod_vec_clear(b1); _nmod_vec_clear(b2); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-bell_number_vec.c000066400000000000000000000023231414523752600205520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "arith.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { fmpz * b1; fmpz * b2; slong n; const slong maxn = 1000; FLINT_TEST_INIT(state); flint_printf("bell_number_vec...."); fflush(stdout); 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); abort(); } } _fmpz_vec_clear(b1, maxn); _fmpz_vec_clear(b2, maxn); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-bernoulli_number.c000066400000000000000000000046701414523752600210010ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "arith.h" #include "profiler.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_poly.h" #include "fmpq.h" int main() { fmpz * num1; fmpz * den1; fmpz_t num2; fmpz_t den2; slong n, N; FLINT_TEST_INIT(state); flint_printf("bernoulli_number...."); fflush(stdout); 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"); 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"); 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); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-bernoulli_number_denom.c000066400000000000000000000021531414523752600221550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "arith.h" #include "fmpz.h" #include "ulong_extras.h" int main() { fmpz_t s, t; slong n; FLINT_TEST_INIT(state); flint_printf("bernoulli_number_denom...."); fflush(stdout); 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"); abort(); } fmpz_clear(s); fmpz_clear(t); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-bernoulli_number_vec.c000066400000000000000000000047561414523752600216430ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "arith.h" #include "profiler.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_poly.h" int main() { fmpz * num1; fmpz * num2; fmpz * num3; fmpz * den1; fmpz * den2; fmpz * den3; slong i, n, N; FLINT_TEST_INIT(state); flint_printf("bernoulli_number_vec...."); fflush(stdout); N = 2000; num1 = _fmpz_vec_init(N); num2 = _fmpz_vec_init(N); num3 = _fmpz_vec_init(N); den1 = _fmpz_vec_init(N); den2 = _fmpz_vec_init(N); den3 = _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); _arith_bernoulli_number_vec_zeta(num3, den3, n); for (i = 0; i < n; i++) { if (!fmpz_equal(num1 + i, num2 + i) || !fmpz_equal(num1 + i, num3 + 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"); flint_printf("zeta: "); fmpz_print(num3 + i); flint_printf("\n"); abort(); } if (!fmpz_equal(den1 + i, den2 + i) || !fmpz_equal(den1 + i, den3 + 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"); flint_printf("zeta: "); fmpz_print(den3 + i); flint_printf("\n"); abort(); } } } _fmpz_vec_clear(num1, N); _fmpz_vec_clear(num2, N); _fmpz_vec_clear(num3, N); _fmpz_vec_clear(den1, N); _fmpz_vec_clear(den2, N); _fmpz_vec_clear(den3, N); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-bernoulli_polynomial.c000066400000000000000000000032701414523752600216670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "arith.h" #include "profiler.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_poly.h" int main() { fmpq_poly_t P, Q; mpz_t t; slong k, n; FLINT_TEST_INIT(state); flint_printf("bernoulli_polynomial...."); fflush(stdout); for (n = 0; n <= 100; n++) { fmpq_poly_init(P); fmpq_poly_init(Q); mpz_init(t); for (k = 0; k <= n; k++) { arith_bernoulli_polynomial(P, k); flint_mpz_bin_uiui(t, n+1, k); fmpq_poly_scalar_mul_mpz(P, P, t); fmpq_poly_add(Q, Q, P); } fmpq_poly_scalar_div_ui(Q, Q, n+1); mpz_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"); abort(); } fmpq_poly_clear(P); fmpq_poly_clear(Q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-chebyshev_t_polynomial.c000066400000000000000000000031711414523752600221770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "arith.h" #include "fmpz.h" #include "fmpz_poly.h" int main() { fmpz_poly_t T0, T1, T2, t; slong n; FLINT_TEST_INIT(state); flint_printf("chebyshev_t_polynomial...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-chebyshev_u_polynomial.c000066400000000000000000000025211414523752600221760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "arith.h" #include "fmpz.h" #include "fmpz_poly.h" int main() { fmpz_poly_t T, U; slong n; FLINT_TEST_INIT(state); flint_printf("chebyshev_u_polynomial...."); fflush(stdout); 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"); abort(); } } fmpz_poly_clear(T); fmpz_poly_clear(U); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-cyclotomic_cos_polynomial.c000066400000000000000000000113461414523752600227100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "arith.h" #include "fmpz.h" #include "fmpz_poly.h" /* Generated with Mathematica: Table[Mod[MinimalPolynomial[Cos[2 Pi/n]][1337], 31337], {n,1,500}] */ static const short testdata[] = { 1, 1336, 1338, 2675, 1337, 8113, 2673, 6283, 2719, 29508, 2765, 6949, 5437, 2788, 26742, 25554, 26194, 29376, 29506, 30945, 15614, 8957, 16643, 9263, 21050, 30556, 10533, 1570, 11562, 3988, 16546, 26642, 4041, 3581, 109, 9839, 27175, 11691, 1460, 28287, 18369, 16503, 3184, 13336, 23083, 12495, 3246, 14160, 8081, 5301, 8652, 28989, 24149, 17733, 1568, 4800, 28863, 29280, 13741, 30919, 29819, 28584, 8913, 550, 6207, 13930, 23373, 12644, 15265, 27975, 30386, 1603, 15894, 22276, 3138, 11610, 2208, 515, 30817, 23050, 4333, 25031, 13615, 5116, 18609, 25490, 14555, 22663, 8425, 21751, 19293, 3, 10688, 26829, 14467, 1426, 12413, 5305, 25377, 27164, 3711, 9613, 22340, 7457, 3704, 1795, 22877, 31060, 17472, 11317, 22274, 11036, 7796, 27242, 22174, 3663, 10507, 16599, 18192, 15208, 7257, 7022, 10810, 27891, 18495, 7032, 11383, 20768, 27351, 31089, 27723, 10486, 2075, 25298, 20531, 28548, 25342, 6510, 20657, 15608, 5534, 22145, 30150, 25222, 12128, 389, 21860, 9631, 4536, 4704, 3677, 27282, 26668, 20784, 15684, 12847, 1307, 10586, 24355, 27553, 10952, 8886, 25029, 29278, 29964, 17943, 1006, 5895, 11466, 16679, 17500, 5414, 3420, 17644, 5165, 6255, 2807, 30577, 26277, 14032, 2425, 13945, 27988, 17437, 28204, 11853, 12265, 8097, 24919, 10703, 18081, 19121, 23364, 14035, 2382, 1722, 21617, 11863, 27682, 8538, 26401, 1487, 14570, 14213, 18315, 30244, 14611, 25421, 13954, 29802, 29118, 5788, 7547, 9710, 21645, 17858, 20672, 2295, 21286, 7217, 30405, 5090, 22674, 5747, 5809, 13789, 16385, 23732, 12258, 10944, 14669, 2043, 1453, 13510, 12422, 24073, 3025, 28094, 2770, 9198, 27411, 24736, 28958, 23508, 27897, 17838, 10690, 5375, 29469, 22458, 9466, 28541, 16308, 20491, 10320, 9836, 673, 26630, 20819, 25687, 19263, 16620, 28683, 30268, 1113, 26632, 18450, 17555, 20121, 18083, 12796, 26659, 9788, 10448, 2828, 29753, 26653, 13636, 6270, 10398, 16224, 1481, 1153, 26387, 17835, 19289, 2683, 1937, 16760, 14372, 12632, 15716, 12423, 24202, 14543, 10763, 27059, 437, 18647, 17133, 27774, 2039, 3931, 7737, 20470, 11068, 26238, 28463, 22610, 28349, 23819, 22780, 4101, 13218, 12878, 25048, 25163, 11032, 10129, 2571, 9319, 11708, 6704, 19105, 11593, 24863, 26090, 15235, 18038, 22056, 19624, 12066, 9798, 16508, 22376, 15776, 10595, 28391, 18898, 11645, 16655, 19391, 11364, 28198, 4348, 6653, 11962, 22652, 18750, 22125, 21504, 23718, 25662, 6768, 24234, 29605, 8280, 5246, 23064, 1360, 21538, 4374, 8186, 7540, 24091, 3017, 23007, 12000, 11289, 8698, 22118, 5505, 18535, 29647, 15878, 4416, 8598, 13062, 8878, 9674, 5066, 17770, 24888, 20643, 1345, 22570, 1363, 3710, 18429, 11731, 14885, 12983, 18600, 26334, 27101, 17858, 22221, 2471, 911, 12033, 2824, 6354, 984, 28507, 3521, 17963, 6558, 11166, 24004, 24367, 8572, 19198, 6937, 15220, 13122, 3540, 589, 17503, 14073, 14954, 26020, 12974, 20684, 19844, 17852, 1097, 10831, 23848, 7013, 15683, 15954, 22290, 30257, 15807, 22775, 13607, 9428, 30055, 11607, 30426, 2579, 340, 29747, 25213, 28551, 5705, 15704, 10625, 16932, 3215, 16716, 6698, 21470, 29839, 511, 23506, 4338, 30506, 18038, 20430, 20586, 18225, 7721, 15812, 3140, 22149, 4949, 8125, 9897, 6323, 20612, 2012, 23744, 9414, 16497, 5557, 5225, 8518, 30549, 21805, 5692, 25222, 16326, 22995, 27432, 16385, 23506, 9911, 23131, 3880, 30647, 13222, 10416, 5619, 2078, 9411, 12398, 22772, 7328, 17932, 19965, -1 }; int main() { fmpz_poly_t p; slong n; FLINT_TEST_INIT(state); flint_printf("cyclotomic_cos_polynomial...."); fflush(stdout); fmpz_poly_init(p); for (n = 0; testdata[n] != -1; n++) { mp_limb_t y; arith_cos_minpoly(p, n); y = fmpz_poly_evaluate_mod(p, 1337, 31337); if (y != testdata[n]) { flint_printf("FAIL: n = %wd\n", n); flint_printf("y = %wu\n", y); flint_printf("\n"); abort(); } } fmpz_poly_clear(p); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-cyclotomic_polynomial.c000066400000000000000000000063341414523752600220450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "arith.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.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); } int main() { fmpz_poly_t A, B; slong n; FLINT_TEST_INIT(state); flint_printf("cyclotomic_polynomial...."); fflush(stdout); for (n = 0; n <= 1000; n++) { fmpz_poly_init(A); fmpz_poly_init(B); arith_cyclotomic_polynomial(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"); 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); arith_cyclotomic_polynomial(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"); abort(); } fmpz_poly_clear(A); fmpz_clear(h); fmpz_clear(ref); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-divisors.c000066400000000000000000000026651414523752600173020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.h" #include "arith.h" #include "ulong_extras.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++; } } } int main(void) { fmpz_t t; fmpz_poly_t a, b; slong n; FLINT_TEST_INIT(state); flint_printf("divisors...."); fflush(stdout); 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); abort(); } } fmpz_clear(t); fmpz_poly_clear(a); fmpz_poly_clear(b); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-euler_number_vec.c000066400000000000000000000027331414523752600207550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "arith.h" #include "profiler.h" #include "fmpz.h" #include "fmpz_vec.h" int main() { fmpz * r; fmpz_t s, t; slong k, n; FLINT_TEST_INIT(state); flint_printf("euler_number_vec...."); fflush(stdout); 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); abort(); } fmpz_clear(s); fmpz_clear(t); _fmpz_vec_clear(r, n + 1); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-euler_number_zeta.c000066400000000000000000000023541414523752600211420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "arith.h" #include "profiler.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_poly.h" int main() { fmpz * ress; fmpz_t res; slong n, N; FLINT_TEST_INIT(state); flint_printf("euler_number_zeta...."); fflush(stdout); N = 3000; 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"); abort(); } fmpz_clear(res); } _fmpz_vec_clear(ress, N); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-euler_polynomial.c000066400000000000000000000033631414523752600210130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "arith.h" #include "profiler.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_poly.h" int main() { fmpq_poly_t P, Q; mpz_t t; slong k, n; FLINT_TEST_INIT(state); flint_printf("euler_polynomial...."); fflush(stdout); for (n = 0; n <= 100; n++) { fmpq_poly_init(P); fmpq_poly_init(Q); mpz_init(t); for (k = 0; k < n; k++) { arith_euler_polynomial(P, k); flint_mpz_bin_uiui(t, n, k); fmpq_poly_scalar_mul_mpz(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); mpz_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"); abort(); } fmpq_poly_clear(P); fmpq_poly_clear(Q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-harmonic.c000066400000000000000000000066121414523752600172340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "arith.h" #include "fmpz.h" #include "fmpq.h" #include "ulong_extras.h" #include "profiler.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); 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); } int main(void) { slong i; mpq_t x, y; fmpq_t t; FLINT_TEST_INIT(state); flint_printf("harmonic_number...."); fflush(stdout); 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); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-landau_function_vec.c000066400000000000000000000026171414523752600214430ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "arith.h" #include "fmpz_vec.h" 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 }; int main(void) { fmpz * res; slong k, n; FLINT_TEST_INIT(state); flint_printf("landau_function_vec...."); fflush(stdout); 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]); abort(); } } _fmpz_vec_clear(res, n); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-number_of_partitions.c000066400000000000000000000067201414523752600216640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "arith.h" #include "ulong_extras.h" /* 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}, }; int main(void) { fmpz_t p; fmpz * v; slong i; FLINT_TEST_INIT(state); flint_printf("number_of_partitions...."); fflush(stdout); fmpz_init(p); v = _fmpz_vec_init(3000); arith_number_of_partitions_vec(v, 3000); for (i = 0; i < 3000; i++) { arith_number_of_partitions(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"); abort(); } } _fmpz_vec_clear(v, 3000); for (i = 0; testdata[i][0] != 0; i++) { arith_number_of_partitions(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]); abort(); } } fmpz_clear(p); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-number_of_partitions_vec.c000066400000000000000000000046731414523752600225260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "arith.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include "profiler.h" #include "nmod_vec.h" int main(void) { fmpz * p; mp_ptr pmod; slong k, n; const slong maxn = 1000; FLINT_TEST_INIT(state); flint_printf("number_of_partitions_vec...."); fflush(stdout); 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); 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"); abort(); } fmpz_clear(s); fmpz_clear(t); } } _fmpz_vec_clear(p, maxn); _nmod_vec_clear(pmod); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-ramanujan_tau.c000066400000000000000000000104331414523752600202550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "arith.h" #include "ulong_extras.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); 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); abort(); } for (k=0; k. */ #include #include #include #include #include "flint.h" #include "arith.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" #include "profiler.h" int main(void) { fmpz_mat_t mat, mat2, mat3; fmpz * row; fmpz_t s; slong n, k, mm, nn; const slong maxn = 40; FLINT_TEST_INIT(state); flint_printf("stirling...."); fflush(stdout); fmpz_init(s); 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); 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); 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); 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); 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); 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); 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); abort(); } } } fmpz_mat_clear(mat); fmpz_mat_clear(mat2); fmpz_mat_clear(mat3); } fmpz_clear(s); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-sum_of_squares.c000066400000000000000000000036001414523752600204610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "arith.h" #include "fmpz_vec.h" #define N 10 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} }; int main(void) { fmpz * r; fmpz_t t; slong i, j; FLINT_TEST_INIT(state); flint_printf("sum_of_squares...."); fflush(stdout); 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]); abort(); } } } _fmpz_vec_clear(r, N); fmpz_clear(t); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/test/t-swinnerton_dyer_polynomial.c000066400000000000000000000026751414523752600231350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "arith.h" #include "profiler.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_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) }; int main() { fmpz_poly_t S; mp_limb_t r; slong n; FLINT_TEST_INIT(state); flint_printf("swinnerton_dyer_polynomial...."); fflush(stdout); 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); abort(); } fmpz_poly_clear(S); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/arith/zeta_inv_euler_product.c000066400000000000000000000041411414523752600207620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "arith.h" void mpfr_zeta_inv_euler_product(mpfr_t res, ulong s, int char_4) { mpz_t z, x, y, r; mp_limb_t p; slong prec, powprec, yexp, shift; mpz_init(x); mpz_init(y); mpz_init(z); mpz_init(r); prec = mpfr_get_prec(res) + 32 + 2*FLINT_BIT_COUNT(s); flint_mpz_set_ui(z, UWORD(1)); mpz_mul_2exp(z, z, prec); if (!char_4) { flint_mpz_set_ui(r, UWORD(1)); mpz_mul_2exp(r, r, prec - s); mpz_sub(z, z, r); } p = UWORD(3); while (1) { slong i; powprec = prec - s*log(p)*1.4426950408889634 + 1; /* flint_printf("prime %wu, powprec %wd\n", p, powprec); */ if (powprec < 5) break; flint_mpz_set_ui(x, p); flint_mpz_set_ui(y, UWORD(1)); yexp = 0; /* Slow equivalent: flint_mpz_pow_ui(y, x, s) */ flint_mpz_set_ui(y, p); for (i = FLINT_BIT_COUNT(s) - 2; i >= 0; i--) { mpz_mul(y, y, y); yexp += yexp; shift = mpz_sizeinbase(y, 2) - powprec - 4; if (shift >= 0) { mpz_tdiv_q_2exp(y, y, shift); yexp += shift; } if (s & (UWORD(1)<= 0) mpz_tdiv_q_2exp(r, z, shift); else mpz_mul_2exp(r, z, -shift); mpz_tdiv_q(r, r, y); if (char_4 && (p % 4 == 3)) mpz_add(z, z, r); else mpz_sub(z, z, r); p = n_nextprime(p, 0); } mpfr_set_z_2exp(res, z, -prec, GMP_RNDN); mpz_clear(x); mpz_clear(y); mpz_clear(z); mpz_clear(r); } flint2-2.8.4/arithxx.h000066400000000000000000000276401414523752600146050ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef ARITHXX_H #define ARITHXX_H #include "arith.h" #include "fmpq_polyxx.h" #include "fmpqxx.h" #include "fmpz_matxx.h" #include "fmpz_vecxx.h" #include "fmpzxx.h" #include "nmod_vecxx.h" // TODO namespace arith? // TODO arith_hrr_expsum_factored // TODO codegen / vector improvements namespace flint { namespace detail { template inline typename T::wrapped_traits::data_srcref_t extract_data(const T& t, typename mp::enable_if >::type* = 0) { return t._data().inner; } template inline typename T::wrapped_traits::data_ref_t extract_data(T& t, typename mp::enable_if >::type* = 0) { return t._data().inner; } template const T& extract_data(const T& t, typename mp::disable_if >::type* = 0) { return t; } template typename T::arrayref_t extract_data(T& t, typename mp::disable_if >::type* = 0, typename mp::enable_if, rules::FMPQ_VECXX_COND_S > >::type* = 0) { return t._array(); } } #define ARITHXX_DEFINE_UNOP(name, Return, Cond) \ FLINT_DEFINE_UNOP(name) \ namespace rules { \ FLINT_DEFINE_UNARY_EXPR_COND(name##_op, Return, Cond, \ arith_##name(detail::extract_data(to), detail::extract_data(from))) \ } #define ARITHXX_DEFINE_BINOP(name, Return, Cond1, Cond2) \ FLINT_DEFINE_BINOP(name) \ namespace rules { \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, Return, Cond1, Cond2, \ arith_##name(detail::extract_data(to), detail::extract_data(e1), \ detail::extract_data(e2))) \ } namespace at { template struct slong : traits::fits_into_slong { }; template struct ulong : traits::is_unsigned_integer { }; } // at ARITHXX_DEFINE_UNOP(primorial, fmpzxx, at::slong) ARITHXX_DEFINE_UNOP(harmonic_number, fmpqxx, at::slong) ARITHXX_DEFINE_BINOP(stirling_number_1u, fmpzxx, at::slong, at::slong) ARITHXX_DEFINE_BINOP(stirling_number_1, fmpzxx, at::slong, at::slong) ARITHXX_DEFINE_BINOP(stirling_number_2, fmpzxx, at::slong, at::slong) ARITHXX_DEFINE_BINOP(stirling_number_1u_vec, fmpz_vecxx, at::slong, at::slong) ARITHXX_DEFINE_BINOP(stirling_number_1_vec, fmpz_vecxx, at::slong, at::slong) ARITHXX_DEFINE_BINOP(stirling_number_2_vec, fmpz_vecxx, at::slong, at::slong) FLINT_DEFINE_BINOP(stirling_number_1u_vec_next) FLINT_DEFINE_BINOP(stirling_number_1_vec_next) FLINT_DEFINE_BINOP(stirling_number_2_vec_next) FLINT_DEFINE_BINOP(stirling_matrix_1u) FLINT_DEFINE_BINOP(stirling_matrix_1) FLINT_DEFINE_BINOP(stirling_matrix_2) namespace vectors { template<> struct outsize { template static unsigned get(const Expr& e) {return e._data().second();} }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize { template static unsigned get(const Expr& e) { slong r = e._data().first().size(); if(r == e._data().second()) return r + 1; return r; } }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; } // vectors namespace matrices { template<> struct outsize { template static slong rows(const Expr& e) {return e._data().first();} template static slong cols(const Expr& e) {return e._data().second();} }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; } // matrices namespace rules { FLINT_DEFINE_BINARY_EXPR_COND2(stirling_number_1u_vec_next_op, fmpz_vecxx, FMPZ_VECXX_COND_S, at::slong, arith_stirling_number_1u_vec_next(to._array(), e1._array(), e2, e1.size() + (e1.size() == e2))) FLINT_DEFINE_BINARY_EXPR_COND2(stirling_number_1_vec_next_op, fmpz_vecxx, FMPZ_VECXX_COND_S, at::slong, arith_stirling_number_1_vec_next(to._array(), e1._array(), e2, e1.size() + (e1.size() == e2))) FLINT_DEFINE_BINARY_EXPR_COND2(stirling_number_2_vec_next_op, fmpz_vecxx, FMPZ_VECXX_COND_S, at::slong, arith_stirling_number_2_vec_next(to._array(), e1._array(), e2, e1.size() + (e1.size() == e2))) FLINT_DEFINE_BINARY_EXPR_COND2(stirling_matrix_1u_op, fmpz_matxx, at::slong, at::slong, arith_stirling_matrix_1u(to._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(stirling_matrix_1_op, fmpz_matxx, at::slong, at::slong, arith_stirling_matrix_1(to._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(stirling_matrix_2_op, fmpz_matxx, at::slong, at::slong, arith_stirling_matrix_2(to._mat())) } // rules ARITHXX_DEFINE_UNOP(bell_number, fmpzxx, at::ulong) ARITHXX_DEFINE_UNOP(bell_number_bsplit, fmpzxx, at::ulong) ARITHXX_DEFINE_UNOP(bell_number_multi_mod, fmpzxx, at::ulong) ARITHXX_DEFINE_UNOP(bell_number_vec, fmpz_vecxx, at::slong) ARITHXX_DEFINE_UNOP(bell_number_vec_recursive, fmpz_vecxx, at::slong) ARITHXX_DEFINE_UNOP(bell_number_vec_multi_mod, fmpz_vecxx, at::slong) FLINT_DEFINE_BINOP(bell_number_nmod) FLINT_DEFINE_BINOP(bell_number_nmod_vec) FLINT_DEFINE_BINOP(bell_number_nmod_vec_recursive) FLINT_DEFINE_BINOP(bell_number_nmod_vec_series) namespace vectors { template<> struct outsize { template static unsigned get(const Expr& e) {return e._data().first();} }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; } // vectors namespace at { template struct nmod : mp::or_, mp::equal_types > { }; } // at #define NMODXX_DEFINE_FIND_CTX_BY_OP(exprname, eval) \ namespace traits { \ template \ struct has_nmodxx_ctx< exprname, Data> > : mp::true_ { }; \ } \ namespace detail { \ template \ struct get_nmodxx_ctx > \ { \ template \ static nmodxx_ctx_srcref get(const T& e) {return eval;} \ }; \ } #define FLINTXX_COMMA() , NMODXX_DEFINE_FIND_CTX_BY_OP(nmodxx_expression struct outsize { template static unsigned get(const Expr& e) {return e._data().first();} }; } // vectors ARITHXX_DEFINE_UNOP(euler_number, fmpzxx, at::ulong) ARITHXX_DEFINE_UNOP(euler_number_vec, fmpz_vecxx, at::ulong) ARITHXX_DEFINE_UNOP(euler_polynomial, fmpq_polyxx, at::ulong) namespace vectors { template<> struct outsize : outsize { }; } ARITHXX_DEFINE_UNOP(legendre_polynomial, fmpq_polyxx, at::ulong) ARITHXX_DEFINE_UNOP(chebyshev_t_polynomial, fmpz_polyxx, at::ulong) ARITHXX_DEFINE_UNOP(chebyshev_u_polynomial, fmpz_polyxx, at::ulong) ARITHXX_DEFINE_UNOP(euler_phi, fmpzxx, FMPZXX_COND_S) ARITHXX_DEFINE_BINOP(divisor_sigma, fmpzxx, FMPZXX_COND_S, at::ulong) ARITHXX_DEFINE_UNOP(divisors, fmpz_polyxx, FMPZXX_COND_S) ARITHXX_DEFINE_UNOP(ramanujan_tau, fmpzxx, FMPZXX_COND_S) ARITHXX_DEFINE_UNOP(ramanujan_tau_series, fmpz_polyxx, at::slong) ARITHXX_DEFINE_UNOP(cyclotomic_polynomial, fmpz_polyxx, at::ulong) ARITHXX_DEFINE_UNOP(cos_minpoly, fmpz_polyxx, at::ulong) ARITHXX_DEFINE_UNOP(swinnerton_dyer_polynomial, fmpz_polyxx, at::ulong) ARITHXX_DEFINE_UNOP(landau_function_vec, fmpz_vecxx, at::slong) namespace vectors { template<> struct outsize : outsize { }; } ARITHXX_DEFINE_BINOP(dedekind_sum_naive, fmpqxx, FMPZXX_COND_S, FMPZXX_COND_S) ARITHXX_DEFINE_BINOP(dedekind_sum, fmpqxx, FMPZXX_COND_S, FMPZXX_COND_S) ARITHXX_DEFINE_UNOP(number_of_partitions_vec, fmpz_vecxx, at::slong) ARITHXX_DEFINE_UNOP(number_of_partitions, fmpzxx, at::ulong) FLINT_DEFINE_BINOP(number_of_partitions_nmod_vec) namespace vectors { template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; } NMODXX_DEFINE_FIND_CTX_BY_OP(vector_expression struct outsize : outsize { }; } inline double bell_number_size(ulong n) {return arith_bell_number_size(n);} inline double bernoulli_number_size(ulong n) {return arith_bernoulli_number_size(n);} inline double euler_number_size(ulong n) {return arith_euler_number_size(n);} template inline typename mp::enable_if, int>::type moebius_mu( const Fmpz& n) { return arith_moebius_mu(n.evaluate()._fmpz()); } } // flint #endif flint2-2.8.4/clz_tab.c000066400000000000000000000025761414523752600145300ustar00rootroot00000000000000/* __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" #include "longlong.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 }; #endif int dummy_fn_to_prevent_ISOC_warning(void) { return 0; } flint2-2.8.4/code_conventions.txt000066400000000000000000000226451414523752600170450ustar00rootroot00000000000000Code conventions ================ Language dialect ---------------- For greater portability, the code should be ANSI C compatible where possible. We note the following exceptions: - Inlined functions, inlined assembly. We define alternative keywords __asm__ and __inline__ in flint.h so that gcc allows compiling with the flags "-ansi -pendatic" nonetheless. Build system ------------ 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 | ulong, or ulong long | | mp_size_t | long, or long long | | mp_limb_t | ulong, or ulong long | | mp_ptr | mp_limb_t * | | mp_srcptr | const mp_limb_t * | | slong | long or long long | | ulong | ulong or ulong 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: 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 specifers %lu/%ld in printf. For this purpose we provide the flint_printf functions, which is the same as printf, except that it supports: 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: a = n_randint(state, n) if the function sets its first argument to a random value, the state comes second, e.g. 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. Function prototypes ------------------- All function prototypes in .h files in FLINT require a FLINT_DLL declaration in front of them. Please keep the initial part of the prototype all on a single line, rather than placing the FLINT_DLL and/or return type on a different line, e.g. prototypes should look like this: FLINT_DLL void myfunc(blah, .... ...., blah, blah) Note that dll import/export is handled differently for inlines. Please don't add FLINT_DLL to inline functions. Rather, add a single FLINT_DLL to the non-inline branch inside the relevant BLAH_INLINES_C #define at the top of the .h file. 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. Threading --------- 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 function 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. Code formatting --------------- 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 flint2-2.8.4/config.h.in000066400000000000000000000017101414523752600147560ustar00rootroot00000000000000/* 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 #cmakedefine FLINT_USES_POPCNT #cmakedefine01 FLINT_USES_BLAS #cmakedefine01 FLINT_USES_FENV #ifdef _MSC_VER #define access _access #define strcasecmp _stricmp #define strncasecmp _strnicmp #define alloca _alloca #define MSC_C_(x) #x #define MSC_CC_(x) MSC_C_(x) #define MSC_VERSION "Microsoft C++ (Version " MSC_CC_(_MSC_FULL_VER) ")" #endif #if defined (FLINT_BUILD_DLL) #define FLINT_DLL __declspec(dllexport) #elif defined(MSC_USE_DLL) #define FLINT_DLL __declspec(dllimport) #else #define FLINT_DLL #endif flint2-2.8.4/configure000077500000000000000000000562651414523752600146610ustar00rootroot00000000000000#!/bin/sh # (C) 2007, Robert Bradshaw, William Hart, William Stein, Michael Abshoff # (C) 2011, William Hart # (C) 2012, William Hart, Jean-Pierre Flori, Thomas DuBuisson # (C) 2012, Jan Engelhardt PREFIX="/usr/local" GMP_DIR="/usr/local" MPFR_DIR="/usr/local" NTL_DIR="/usr/local" GC_DIR="/usr/local" BLAS_DIR="/usr" WANT_NTL=0 WANT_BLAS=0 WANT_DEPS=1 SHARED=1 STATIC=1 TLS=1 PTHREAD=1 REENTRANT=0 WANT_GC=0 WANT_TLS=0 WANT_CXX=0 ASSERT=0 BUILD= EXTENSIONS= EXT_MODS= EXTRA_BUILD= FLINT_DLL=0 FLINT_LIBNAME= FLINT_SOLIB=0 # soname version, minor release number and patch number # 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 FLINT_MAJOR=16 FLINT_MINOR=1 FLINT_PATCH=4 usage() { echo "Usage: ./configure " echo " where may be" echo " -h display usage information" echo " where may be:" echo " --prefix= Specify path to installation location (default: /usr/local)" echo " --with-mpir= Specify location of MPIR (default: /usr/local)" echo " --with-gmp= Specify location of GMP (default: /usr/local)" echo " --with-mpfr= Specify location of MPFR (default: /usr/local)" echo " --with-blas[=] Use BLAS and specify its location (default: /usr)" echo " --without-blas Do not use BLAS (default)" echo " --with-ntl[=] Build NTL interface and specify its location (default: /usr/local)" echo " --without-ntl Do not build NTL interface (default)" echo " --extensions= Specify location of extension modules" echo " --build=arch-os Specify architecture/OS combination rather than use values from uname -m/-s" echo " --enable-shared Build a shared library (default)" echo " --disable-shared Do not build a shared library" echo " --enable-static Build a static library (default)" echo " --disable-static Do not build a static library" echo " --single Faster [non-reentrant if tls or pthread not used] version of library (default)" echo " --reentrant Build fully reentrant [with or without tls, with pthread] version of library" echo " --with-gc= GC safe build with path to gc" echo " --enable-pthread Use pthread (default)" echo " --disable-pthread Do not use pthread" echo " --enable-tls Use thread-local storage (default)" echo " --disable-tls Do not use thread-local storage" echo " --enable-assert Enable use of asserts (use for debug builds only)" echo " --disable-assert Disable use of asserts (default)" echo " --enable-cxx Enable C++ wrapper tests" echo " --disable-cxx Disable C++ wrapper tests (default)" echo " --disable-dependency-tracking Disable gcc automated dependency tracking" echo " CC= Use the C compiler with the given name (default: gcc)" echo " CXX= Use the C++ compiler with the given name (default: g++)" echo " AR= Use the AR library builder with the given name (default: ar)" echo " LDCONFIG= Use the given ldconfig tool" echo " CFLAGS= Pass the given flags to the compiler" echo " CXXFLAGS= Pass the given flags to the C++ compiler" echo " ABI=[32|64] Tell the compiler to use given ABI (default: empty)" } absolute_path(){ dirlist="$1" retval="" for dir in $dirlist; do case $dir in /*) dir=$dir;; *) dir=$PWD/$dir;; esac retval=$retval" "$dir done echo $retval } #begin config.log echo "/* This file is autogenerated by ./configure -- do not edit! */" > config.log echo "./configure $@" >> config.log while [ "$1" != "" ]; do PARAM=`echo $1 | sed 's/=.*//'` VALUE=`echo $1 | sed 's/[^=]*//; s/=//'` case "$PARAM" in -h|--help) usage exit 0 ;; --with-mpir|--with-gmp) GMP_DIR=$(absolute_path "$VALUE") ;; --with-mpfr) MPFR_DIR=$(absolute_path "$VALUE") ;; --with-ntl) WANT_NTL=1 if [ ! -z "$VALUE" ]; then NTL_DIR=$(absolute_path "$VALUE") fi ;; --without-ntl) WANT_NTL=0 ;; --with-blas) WANT_BLAS=1 if [ ! -z "$VALUE" ]; then BLAS_DIR=$(absolute_path "$VALUE") fi ;; --without-blas) WANT_BLAS=0 ;; --extensions) EXTENSIONS=$(absolute_path "$VALUE") ;; --build) BUILD="$VALUE" ;; --prefix) PREFIX=$(absolute_path "$VALUE") ;; --enable-shared) SHARED=1 ;; --disable-shared) SHARED=0 ;; --enable-static) STATIC=1 ;; --disable-static) STATIC=0 ;; --single) REENTRANT=0 ;; --reentrant) REENTRANT=1 ;; --with-gc) WANT_GC=1 if [ ! -z "$VALUE" ]; then GC_DIR="$VALUE" fi ;; --enable-pthread) PTHREAD=1 ;; --disable-pthread) PTHREAD=0 ;; --enable-tls) TLS=1 WANT_TLS=1;; --disable-tls) TLS=0 WANT_TLS=2;; --enable-assert) ASSERT=1 ;; --disable-assert) ASSERT=0 ;; --enable-cxx) WANT_CXX=1 ;; --disable-cxx) WANT_CXX=0 ;; --disable-dependency-tracking) WANT_DEPS=0 ;; AR) AR="$VALUE" ;; CC) CC="$VALUE" ;; LDCONFIG) LDCONFIG="$VALUE" ;; CXX) CXX="$VALUE" ;; CFLAGS) CFLAGS="$VALUE" ;; CXXFLAGS) CXXFLAGS="$VALUE" ;; ABI) ABI="$VALUE" ;; *) usage exit 1 ;; esac shift done #find dependencies LIBS="m" if [ -d "${GMP_DIR}/lib" ]; then GMP_LIB_DIR="${GMP_DIR}/lib" GMP_INC_DIR="${GMP_DIR}/include" elif [ -d "${GMP_DIR}/lib64" ]; then GMP_LIB_DIR="${GMP_DIR}/lib64" GMP_INC_DIR="${GMP_DIR}/include" elif [ -d "${GMP_DIR}/.libs" ]; then GMP_LIB_DIR="${GMP_DIR}/.libs" GMP_INC_DIR="${GMP_DIR}" else echo "Invalid GMP directory" echo "Invalid GMP directory: ${GMP_DIR}" >> config.log exit 1 fi LIB_DIRS="${LIB_DIRS} ${GMP_LIB_DIR}" INC_DIRS="${INC_DIRS} ${GMP_INC_DIR}" LIBS="${LIBS} gmp" if [ -d "${MPFR_DIR}/lib" ]; then MPFR_LIB_DIR="${MPFR_DIR}/lib" MPFR_INC_DIR="${MPFR_DIR}/include" elif [ -d "${MPFR_DIR}/lib64" ]; then MPFR_LIB_DIR="${MPFR_DIR}/lib64" MPFR_INC_DIR="${MPFR_DIR}/include" elif [ -d "${MPFR_DIR}/.libs" ]; then MPFR_LIB_DIR="${MPFR_DIR}/.libs" MPFR_INC_DIR="${MPFR_DIR}" elif [ -d "${MPFR_DIR}/src/.libs" ]; then MPFR_LIB_DIR="${MPFR_DIR}/src/.libs" MPFR_INC_DIR="${MPFR_DIR}/src" else echo "Invalid MPFR directory" echo "Invalid MPFR directory: ${MPFR_DIR}" >> config.log exit 1 fi LIB_DIRS="${LIB_DIRS} ${MPFR_LIB_DIR}" INC_DIRS="${INC_DIRS} ${MPFR_INC_DIR}" LIBS="${LIBS} mpfr" #configure extra libraries if [ "$WANT_NTL" = "1" ]; then if [ -d "${NTL_DIR}/lib" ]; then NTL_LIB_DIR="${NTL_DIR}/lib" NTL_INC_DIR="${NTL_DIR}/include" elif [ -d "${NTL_DIR}/lib64" ]; then NTL_LIB_DIR="${NTL_DIR}/lib64" NTL_INC_DIR="${NTL_DIR}/include" else echo "Invalid NTL directory" echo "Invalid NTL directory: ${NTL_DIR}" >> config.log exit 1 fi EXTRA_INC_DIRS="${EXTRA_INC_DIRS} ${NTL_INC_DIR}" EXTRA_LIB_DIRS="${EXTRA_LIB_DIRS} ${NTL_LIB_DIR}" EXTRA_LIBS="${EXTRA_LIBS} ntl" fi if [ "$WANT_BLAS" = "1" ]; then if [ -d "${BLAS_DIR}/lib/x86_64-linux-gnu/openblas-pthread" ]; then BLAS_LIB_DIR="${BLAS_DIR}/lib/x86_64-linux-gnu" BLAS_INC_DIR="${BLAS_DIR}/include/x86_64-linux-gnu" elif [ -d "${BLAS_DIR}/lib" ]; then BLAS_LIB_DIR="${BLAS_DIR}/lib" BLAS_INC_DIR="${BLAS_DIR}/include" elif [ -d "${BLAS_DIR}" ]; then BLAS_LIB_DIR="${BLAS_DIR}" BLAS_INC_DIR="${BLAS_DIR}" else echo "Invalid BLAS directory" echo "Invalid BLAS directory: ${BLAS_DIR}" >> config.log exit 1 fi EXTRA_INC_DIRS="${EXTRA_INC_DIRS} ${BLAS_INC_DIR}" EXTRA_LIB_DIRS="${EXTRA_LIB_DIRS} ${BLAS_LIB_DIR}" EXTRA_LIBS="${EXTRA_LIBS} openblas" fi CONFIG_BLAS="#define FLINT_USES_BLAS ${WANT_BLAS}" if [ "$WANT_GC" = "1" ]; then if [ -d "${GC_DIR}" ]; then GC_LIB_DIR="${GC_DIR}/lib" GC_INC_DIR="${GC_DIR}/include" else echo "Invalid GC directory" echo "Invalid GC directory: ${GC_DIR}" >> config.log exit 1 fi EXTRA_INC_DIRS="${EXTRA_INC_DIRS} ${GC_INC_DIR}" EXTRA_LIB_DIRS="${EXTRA_LIB_DIRS} ${GC_LIB_DIR}" EXTRA_LIBS="${EXTRA_LIBS} gc" fi CONFIG_GC="#define FLINT_USES_GC ${WANT_GC}" # defaults for CC, CXX and AR if [ -z "$CC" ]; then CC=gcc fi if [ -z "$CXX" ]; then CXX=g++ fi if [ -z "$AR" ]; then AR=ar fi #handle gc and reentrant flags if [ "$WANT_GC" = "1" ]; then TLS=0 if [ "$WANT_TLS" = "1" ]; then echo "****WARNING**** GC does not support TLS....disabling TLS" echo "GC does not support TLS....disabling TLS" >> config.log fi cp fmpz/link/fmpz_gc.c fmpz/fmpz.c cp fmpz-conversions-gc.in fmpz-conversions.h else if [ "$REENTRANT" = "1" ]; then cp fmpz/link/fmpz_reentrant.c fmpz/fmpz.c cp fmpz-conversions-reentrant.in fmpz-conversions.h else cp fmpz/link/fmpz_single.c fmpz/fmpz.c cp fmpz-conversions-single.in fmpz-conversions.h fi fi # Architecture handler KERNEL=`uname` if [ -z "$BUILD" ]; then ARCH=`uname -m` if [ "$(uname | cut -d_ -f1)" = "MSYS" ]; then if [ "$ARCH" = "x86_64" ]; then OS="MINGW64" else OS="MINGW32" fi elif [ "$(uname | cut -d_ -f1)" = "MINGW32" ]; then if [ "$ABI" = "64" ]; then OS="MINGW64" else OS="MINGW32" fi elif [ "$(uname | cut -d_ -f1)" = "MINGW64" ]; then if [ "$ABI" = "32" ]; then OS="MINGW32" else OS="MINGW64" fi elif [ "$(uname | cut -d_ -f1)" = "CYGWIN" ]; then if [ "$ARCH" = "x86_64" ]; then if [ "$ABI" = "32" ]; then OS="CYGWIN32" else OS="CYGWIN64" ABI="64" fi else OS="CYGWIN32" fi else OS=`uname -s` fi else ARCH=`echo "$BUILD" | cut -d- -f1` OS=`echo "$BUILD" | cut -d- -f2` fi case "$ARCH" in x86_64 | amd64) MACHINE="x86_64";; x86 | i*86 | pc) MACHINE="x86";; ia64) MACHINE="ia64";; sparc | sun4*) MACHINE="sparc";; sparc64) MACHINE="sparc64";; ppc64 | powerpc64) MACHINE="ppc64";; ppc | powerpc | [P|p]ower*) MACHINE="ppc";; mips64) MACHINE="mips64";; *) MACHINE="unknown";; esac #ABI flag if [ "$ABI" = "32" ]; then ABI_FLAG="-m32" case "$MACHINE" in x86_64) MACHINE="x86";; sparc64) MACHINE="sparc";; ppc64) MACHINE="ppc";; *) ;; esac elif [ "$ABI" = "64" ]; then ABI_FLAG="-m64" if [ "$MACHINE" = "sparc" ]; then MACHINE="sparc64" fi if [ "$MACHINE" = "x86" ]; then MACHINE="x86_64" fi fi if [ "$MACHINE" = "sparc" ] || [ "$MACHINE" = "sparc64" ]; then if [ "$CC" = "gcc" ]; then CC="gcc -mno-relax" fi fi echo "Configuring...${MACHINE}-${OS}" echo "Configuring...${MACHINE}-${OS}" >> config.log #FLINT shared library if [ -z "$FLINT_LIB" ]; then case "$OS" in Darwin) FLINT_LIBNAME="libflint.dylib" FLINT_LIB="libflint-$FLINT_MAJOR.dylib" EXTRA_SHARED_FLAGS="-install_name `pwd`/$FLINT_LIB" EXTRA_SHARED_FLAGS="$EXTRA_SHARED_FLAGS -compatibility_version $FLINT_MAJOR.$FLINT_MINOR" EXTRA_SHARED_FLAGS="$EXTRA_SHARED_FLAGS -current_version $FLINT_MAJOR.$FLINT_MINOR.$FLINT_PATCH" ;; CYGWIN* | MINGW*) FLINT_LIBNAME="libflint.dll" FLINT_LIB="libflint-$FLINT_MAJOR.dll" EXTRA_SHARED_FLAGS="-static-libgcc" EXTRA_SHARED_FLAGS="$EXTRA_SHARED_FLAGS -shared" EXTRA_SHARED_FLAGS="$EXTRA_SHARED_FLAGS -Wl,--export-all-symbols" EXTRA_SHARED_FLAGS="$EXTRA_SHARED_FLAGS -Wl,-soname,libflint-$FLINT_MAJOR.dll.$FLINT_MINOR.$FLINT_PATCH" FLINT_DLL=1 ;; android) FLINT_LIBNAME="libflint.so" FLINT_LIB="libflint.so.$FLINT_MAJOR.$FLINT_MINOR.$FLINT_PATCH" EXTRA_SHARED_FLAGS="-Wl,-soname,libflint.so" FLINT_SOLIB=1 ;; *) FLINT_LIBNAME="libflint.so" FLINT_LIB="libflint.so.$FLINT_MAJOR.$FLINT_MINOR.$FLINT_PATCH" EXTRA_SHARED_FLAGS="-Wl,-soname,libflint.so.$FLINT_MAJOR" FLINT_SOLIB=1 ;; esac EXTRA_SHARED_FLAGS="$EXTRA_SHARED_FLAGS -Wl,-rpath,$GMP_LIB_DIR" EXTRA_SHARED_FLAGS="$EXTRA_SHARED_FLAGS -Wl,-rpath,$MPFR_LIB_DIR" fi # sometimes LDCONFIG is not to be found in the path. Look at some common places. case "$OS" in MINGW*|CYGWIN*|Darwin|FreeBSD) LDCONFIG="true";; *) if [ -z "$LDCONFIG" ]; then LDCONFIG="true" if [ "$FLINT_SOLIB" = "1" ]; then if command -v ldconfig > /dev/null; then LDCONFIG="ldconfig" elif [ -x /sbin/ldconfig ]; then LDCONFIG="/sbin/ldconfig" fi fi fi;; esac #extension for executables if [ -z "$EXEEXT" ]; then case "$OS" in CYGWIN* | MINGW*) EXEEXT=".exe";; *) EXEEXT="";; esac fi #don't build both shared and static lib on MinGW and Cygwin case "$OS" in CYGWIN* | MINGW*) if [ "$STATIC" = "1" ] && [ "$SHARED" = "1" ]; then echo "Building both static and shared versions of MPIR/GMP on $OS is currently" echo "unsupported, and so is it for MPFR and FLINT." echo "You should pass --disable-shared or --disable-static to configure" echo "depending on the versions of MPIR/GMP and MPFR you built." echo "Both static and shared libraries is not permitted on $OS" >> config.log exit 1 fi ;; *) ;; esac #select fft_tuning parameters case "$MACHINE" in x86_64 | ia64 | sparc64 | ppc64) cp fft_tuning64.in fft_tuning.h;; *) cp fft_tuning32.in fft_tuning.h;; esac #test for popcnt flag and set needed CFLAGS mkdir -p build rm -f build/test-popcnt > /dev/null 2>&1 MSG="Testing __builtin_popcountl..." printf "%s" "$MSG" printf "%s" "$MSG" >> config.log echo "int main(int argc, char ** argv) { #if defined(_WIN64) return __builtin_popcountll(argc) == 100; #else return __builtin_popcountl(argc) == 100; #endif }" > build/test-popcnt.c $CC build/test-popcnt.c -o ./build/test-popcnt > /dev/null 2>&1 if [ $? -eq 0 ]; then printf "%s\n" "yes" echo "yes" >> config.log CONFIG_POPCNT_INTRINSICS="#define FLINT_USES_POPCNT" if [ "$MACHINE" = "x86_64" ]; then MSG="Testing native popcount..." printf "%s" "$MSG" printf "%s" "$MSG" >> config.log touch build/test-popcnt.c rm build/test-popcnt $CC -mpopcnt build/test-popcnt.c -o ./build/test-popcnt > /dev/null 2>&1 build/test-popcnt > /dev/null 2>&1 if [ $? -eq 0 ]; then printf "%s\n" "yes" echo "yes" >> config.log POPCNT_FLAG="-mpopcnt" else printf "%s\n" "no" echo "no" >> config.log fi rm -f build/test-popcnt{,.c} #in case -mpopcnt is not available, the test program will use an illegal #instruction and that will print out something on stderr when the if #construction is exited, whence the following "2> /dev/null" fi 2> /dev/null else rm -f build/test-popcnt.c printf "%s\n" "no" echo "no" >> config.log fi #defaults for CFLAGS if [ -z "$CFLAGS" ]; then if [ "$OS" = "MINGW64" ]; then CFLAGS="-std=c99 -O2 -funroll-loops -g $POPCNT_FLAG $ABI_FLAG" ANSI_FLAG="" elif [ "$OS" = "CYGWIN64" ]; then CFLAGS="-O2 -funroll-loops -g -D _WIN64 $POPCNT_FLAG $ABI_FLAG" ANSI_FLAG="" elif [ "$MACHINE" = "mips64" ]; then CFLAGS="-O2 -funroll-loops -g $POPCNT_FLAG $ABI_FLAG" ANSI_FLAG="" elif test "$KERNEL" = "FreeBSD" -o "$OS" = "OpenBSD"; then CFLAGS="-std=c99 -pedantic -Wall -O2 -funroll-loops -g $POPCNT_FLAG $ABI_FLAG" ANSI_FLAG="" CXXFLAGS="-std=c++11 -pedantic -Wall -O2 -funroll-loops -g $POPCNT_FLAG $ABI_FLAG" else ANSI_FLAG="-ansi" CFLAGS="-pedantic -Wall -O2 -funroll-loops -g $POPCNT_FLAG $ABI_FLAG" fi fi #this is needed on PPC G5 and does not hurt on other OS Xes if [ "$KERNEL" = Darwin ]; then CFLAGS="-fno-common $CFLAGS" fi #PIC flag if [ -z "$PIC_FLAG" ]; then case "$OS" in CYGWIN* | MINGW*) ;; *) PIC_FLAG="-fPIC";; esac fi #test support for thread-local storage CONFIG_TLS="#define FLINT_USES_TLS 0" if [ "$TLS" = "1" ]; then mkdir -p build rm -f build/test-tls > /dev/null 2>&1 MSG="Testing __thread..." printf "%s" "$MSG" printf "%s" "$MSG" >> config.log echo "__thread int x = 42; int main(int argc, char ** argv) { return x != 42; }" > build/test-tls.c $CC build/test-tls.c -o ./build/test-tls > /dev/null 2>&1 if [ $? -eq 0 ]; then build/test-tls > /dev/null 2>&1 if [ $? -eq 0 ]; then printf "%s\n" "yes" echo "yes" >> config.log CONFIG_TLS="#define FLINT_USES_TLS 1" else printf "%s\n" "no" echo "no" >> config.log fi rm -f build/test-tls{,.c} else rm -f build/test-tls.c printf "%s\n" "no" echo "no" >> config.log #build-tls can segfault on systems where tls is not available fi 2> /dev/null fi #fenv configuration CONFIG_FENV="#define FLINT_USES_FENV 0" mkdir -p build MSG="Testing fenv..." printf "%s" "$MSG" printf "%s" "$MSG" >> config.log echo "#include " > build/test-fenv.h echo "#ifndef FE_DOWNWARD" >> build/test-fenv.h echo "#error FE_DOWNWARD not available" >> build/test-fenv.h echo "#endif" >> build/test-fenv.h if ($CC -E build/test-fenv.h > /dev/null 2>&1) then printf "%s\n" "yes" echo "yes" >> config.log CONFIG_FENV="#define FLINT_USES_FENV 1" else printf "%s\n" "no" echo "no" >> config.log fi rm -f build/test-fenv.h CONFIG_BIG_ENDIAN="#define FLINT_BIG_ENDIAN 0" mkdir -p build MSG="Testing big endian..." printf "%s" "$MSG" printf "%s" "MSG" >> config.log echo "int main(int argc, char ** argv){ union { unsigned int i; char c[4]; } be_int = {0x01020304}; return be_int.c[0] == 1; }" > build/test-endian.c $CC build/test-endian.c -o ./build/test-endian > /dev/null 2>&1 build/test-endian > /dev/null 2>&1 if [ $? -eq 0 ]; then printf "%s\n" "no" echo "no" >> config.log else printf "%s\n" "yes" echo "yes" >> config.log CONFIG_BIG_ENDIAN="#define FLINT_BIG_ENDIAN 1" fi rm -f build/test-endian{,.c} #pthread configuration CONFIG_PTHREAD="#define FLINT_USES_PTHREAD ${PTHREAD}" #cpu_set_t configuration CONFIG_CPU_SET_T="#define FLINT_USES_CPUSET 0" mkdir -p build MSG="Testing cpu_set_t..." printf "%s" "$MSG" printf "%s" "$MSG" >> config.log echo "#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;}" > build/test-cpu_set_t.c $CC build/test-cpu_set_t.c -lpthread -o ./build/test-cpu_set_t > /dev/null 2>&1 if [ $? -eq 0 ]; then rm -f build/test-cpu_set_t printf "%s\n" "yes" echo "yes" >> config.log CONFIG_CPU_SET_T="#define FLINT_USES_CPUSET 1" else printf "%s\n" "no" echo "no" >> config.log fi rm -f build/test-cpu_set_t.c #external modules EXTRA_INC_DIRS="${EXTRA_INC_DIRS} ${EXTENSIONS}" #include paths INCS="-I\$(CURDIR) -I\$(CURDIR)/build" for INC_DIR in ${INC_DIRS} ${EXTRA_INC_DIRS}; do INCS="${INCS} -I${INC_DIR}" done #library paths LLIBS="-L\$(CURDIR)" for LIB_DIR in ${LIB_DIRS} ${EXTRA_LIB_DIRS}; do LLIBS="${LLIBS} -L${LIB_DIR}" done #linker params if [ "$PTHREAD" = "1" ]; then lLIBS2="-lpthread ${lLIBS2}" fi for LIB in ${EXTRA_LIBS} ${LIBS}; do lLIBS2="-l${LIB} ${lLIBS2}" done lLIBS="-lflint $lLIBS2" LIBS2="$LLIBS $lLIBS2" LIBS="$LLIBS $lLIBS" #cxx if [ "$WANT_CXX" = "1" ]; then EXTRA_BUILD="$EXTRA_BUILD flintxx" fi if [ -z "$CXXFLAGS" ]; then CXXFLAGS="$CFLAGS" fi #write out flint-config.h echo "/* This file is autogenerated by ./configure -- do not edit! */" > flint-config.h echo "$CONFIG_POPCNT_INTRINSICS" >> flint-config.h echo "$CONFIG_BLAS" >> flint-config.h echo "$CONFIG_TLS" >> flint-config.h echo "$CONFIG_FENV" >> flint-config.h echo "$CONFIG_PTHREAD" >> flint-config.h echo "$CONFIG_BIG_ENDIAN" >> flint-config.h echo "$CONFIG_GC" >> flint-config.h echo "$CONFIG_CPU_SET_T" >> flint-config.h echo "#define FLINT_REENTRANT $REENTRANT" >> flint-config.h echo "#define FLINT_WANT_ASSERT $ASSERT" >> flint-config.h if [ "$FLINT_DLL" = "1" ]; then echo "#ifdef FLINT_USE_DLL" >> flint-config.h echo "#define FLINT_DLL __declspec(dllimport)" >> flint-config.h echo "#else" >> flint-config.h echo "#define FLINT_DLL __declspec(dllexport)" >> flint-config.h echo "#endif" >> flint-config.h else echo "#define FLINT_DLL" >> flint-config.h fi #write out Makefile echo "# This file is autogenerated by ./configure -- do not edit!" > Makefile echo "" >> Makefile echo "SHELL=/bin/sh" >> Makefile echo "" >> Makefile echo "GMP_LIB_DIR=$GMP_LIB_DIR" >> Makefile echo "MPFR_LIB_DIR=$MPFR_LIB_DIR" >> Makefile echo "" >> Makefile echo "FLINT_STATIC=$STATIC" >> Makefile echo "FLINT_SHARED=$SHARED" >> Makefile echo "FLINT_LIB=$FLINT_LIB" >> Makefile echo "FLINT_LIBNAME=$FLINT_LIBNAME" >> Makefile echo "OS=$OS" >> Makefile echo "FLINT_SOLIB=$FLINT_SOLIB" >> Makefile echo "FLINT_MAJOR=$FLINT_MAJOR" >> Makefile echo "EXEEXT=$EXEEXT" >> Makefile echo "PREFIX=$PREFIX" >> Makefile echo "" >> Makefile echo "WANT_NTL=$WANT_NTL" >> Makefile echo "" >> Makefile echo "INCS=$INCS" >> Makefile echo "LIBS=$LIBS" >> Makefile echo "LIBS2=$LIBS2" >> Makefile echo "" >> Makefile echo "CC=$CC" >> Makefile echo "CXX=$CXX" >> Makefile echo "AR=$AR" >> Makefile echo "LDCONFIG=$LDCONFIG" >> Makefile echo "" >> Makefile echo "CFLAGS=$ANSI_FLAG $CFLAGS" >> Makefile echo "CXXFLAGS=$CXXFLAGS" >> Makefile echo "ABI_FLAG=$ABI_FLAG" >> Makefile echo "PIC_FLAG=$PIC_FLAG" >> Makefile echo "EXTRA_SHARED_FLAGS=$EXTRA_SHARED_FLAGS" >> Makefile echo "" >> Makefile echo "EXTENSIONS=$EXTENSIONS" >> Makefile echo "EXTRA_BUILD_DIRS=$EXTRA_BUILD" >> Makefile echo "" >> Makefile echo "WANT_DEPS=$WANT_DEPS" >> Makefile echo "" >> Makefile cat Makefile.in >> Makefile echo "FLINT was successfully configured." echo "FLINT was successfully configured." >> config.log flint2-2.8.4/d_mat.h000066400000000000000000000067211414523752600141770ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define D_MAT_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "d_vec.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 double * d_mat_entry_ptr(const d_mat_t mat, slong i, slong j) { return mat->rows[i] + j; } D_MAT_INLINE double d_mat_get_entry(const d_mat_t mat, slong i, slong j) { return 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 ********************************************************/ FLINT_DLL void d_mat_init(d_mat_t mat, slong rows, slong cols); FLINT_DLL void d_mat_swap(d_mat_t mat1, d_mat_t mat2); 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++) DOUBLE_SWAP(row1[j], row2[j]); } } FLINT_DLL void d_mat_set(d_mat_t mat1, const d_mat_t mat2); FLINT_DLL void d_mat_clear(d_mat_t mat); FLINT_DLL int d_mat_equal(const d_mat_t mat1, const d_mat_t mat2); FLINT_DLL int d_mat_approx_equal(const d_mat_t mat1, const d_mat_t mat2, double eps); FLINT_DLL int d_mat_is_zero(const d_mat_t mat); FLINT_DLL int d_mat_is_approx_zero(const d_mat_t mat, double eps); D_MAT_INLINE int d_mat_is_empty(const d_mat_t mat) { return (mat->r == 0) || (mat->c == 0); } D_MAT_INLINE int d_mat_is_square(const d_mat_t mat) { return (mat->r == mat->c); } FLINT_DLL void d_mat_zero(d_mat_t mat); FLINT_DLL void d_mat_one(d_mat_t mat); /* Input and output *********************************************************/ FLINT_DLL void d_mat_print(const d_mat_t mat); /* Random matrix generation *************************************************/ FLINT_DLL void d_mat_randtest(d_mat_t mat, flint_rand_t state, slong minexp, slong maxexp); /* Transpose */ FLINT_DLL void d_mat_transpose(d_mat_t B, const d_mat_t A); /* Multiplication */ FLINT_DLL void d_mat_mul_classical(d_mat_t C, const d_mat_t A, const d_mat_t B); /* Permutations */ D_MAT_INLINE void d_mat_swap_rows(d_mat_t mat, slong r, slong s) { if (r != s) { double * u; u = mat->rows[s]; mat->rows[s] = mat->rows[r]; mat->rows[r] = u; } } /* Gram-Schmidt Orthogonalisation and QR Decomposition ********************************************************/ FLINT_DLL void d_mat_gso(d_mat_t B, const d_mat_t A); FLINT_DLL void d_mat_qr(d_mat_t Q, d_mat_t R, const d_mat_t A); #ifdef __cplusplus } #endif #endif flint2-2.8.4/d_mat/000077500000000000000000000000001414523752600140205ustar00rootroot00000000000000flint2-2.8.4/d_mat/approx_equal.c000066400000000000000000000015251414523752600166670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/d_mat/clear.c000066400000000000000000000012431414523752600152520ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/d_mat/equal.c000066400000000000000000000014661414523752600153020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/d_mat/gso.c000066400000000000000000000040061414523752600147540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "d_mat.h" void d_mat_gso(d_mat_t B, const d_mat_t A) { slong i, j, k; int flag; double t, s; if (B->r != A->r || B->c != A->c) { flint_printf("Exception (d_mat_gso). Incompatible dimensions.\n"); flint_abort(); } if (B == A) { d_mat_t t; d_mat_init(t, A->r, A->c); d_mat_gso(t, A); d_mat_swap_entrywise(B, t); d_mat_clear(t); return; } if (A->r == 0) { return; } for (k = 0; k < A->c; k++) { for (j = 0; j < A->r; j++) { d_mat_entry(B, j, k) = d_mat_entry(A, j, k); } flag = 1; while (flag) { t = 0; for (i = 0; i < k; i++) { s = 0; for (j = 0; j < A->r; j++) { s += d_mat_entry(B, j, i) * d_mat_entry(B, j, k); } t += s * s; for (j = 0; j < A->r; j++) { d_mat_entry(B, j, k) -= s * d_mat_entry(B, j, i); } } s = 0; for (j = 0; j < A->r; j++) { s += d_mat_entry(B, j, k) * d_mat_entry(B, j, k); } t += s; flag = 0; if (s < t) { if (fabs(s * D_EPS) < 1.0e-308) s = 0; else flag = 1; } } s = sqrt(s); if (s != 0) s = 1 / s; for (j = 0; j < A->r; j++) { d_mat_entry(B, j, k) *= s; } } } flint2-2.8.4/d_mat/init.c000066400000000000000000000020541414523752600151300ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/d_mat/inlines.c000066400000000000000000000010521414523752600156230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define D_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "d_mat.h" flint2-2.8.4/d_mat/is_approx_zero.c000066400000000000000000000013131414523752600172250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "d_mat.h" int d_mat_is_approx_zero(const d_mat_t mat, double eps) { slong j; if (mat->r == 0 || mat->c == 0) return 1; for (j = 0; j < mat->r; j++) { if (!_d_vec_is_approx_zero(mat->rows[j], mat->c, eps)) return 0; } return 1; } flint2-2.8.4/d_mat/is_zero.c000066400000000000000000000012541414523752600156400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "d_mat.h" int d_mat_is_zero(const d_mat_t mat) { slong j; if (mat->r == 0 || mat->c == 0) return 1; for (j = 0; j < mat->r; j++) { if (!_d_vec_is_zero(mat->rows[j], mat->c)) return 0; } return 1; } flint2-2.8.4/d_mat/mul_classical.c000066400000000000000000000034121414523752600167770ustar00rootroot00000000000000/* 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 2.1 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_printf ("Exception (d_mat_mul_classical). Incompatible dimensions.\n"); flint_abort(); } 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); } flint2-2.8.4/d_mat/one.c000066400000000000000000000011431414523752600147440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "d_mat.h" void d_mat_one(d_mat_t mat) { slong i, n; d_mat_zero(mat); n = FLINT_MIN(mat->r, mat->c); for (i = 0; i < n; i++) d_mat_entry(mat, i, i) = 1; } flint2-2.8.4/d_mat/print.c000066400000000000000000000014661414523752600153270ustar00rootroot00000000000000/* 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 2.1 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"); } flint2-2.8.4/d_mat/qr.c000066400000000000000000000045031414523752600146100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "d_mat.h" void d_mat_qr(d_mat_t Q, d_mat_t R, const d_mat_t A) { slong i, j, k; int flag, orig; double t, s; if (Q->r != A->r || Q->c != A->c || R->r != A->c || R->c != A->c) { flint_printf("Exception (d_mat_qr). Incompatible dimensions.\n"); flint_abort(); } if (Q == A) { d_mat_t t; d_mat_init(t, A->r, A->c); d_mat_qr(t, R, A); d_mat_swap_entrywise(Q, t); d_mat_clear(t); return; } if (A->r == 0) { return; } for (k = 0; k < A->c; k++) { for (j = 0; j < A->r; j++) { d_mat_entry(Q, j, k) = d_mat_entry(A, j, k); } orig = flag = 1; while (flag) { t = 0; for (i = 0; i < k; i++) { s = 0; for (j = 0; j < A->r; j++) { s += d_mat_entry(Q, j, i) * d_mat_entry(Q, j, k); } if (orig) { d_mat_entry(R, i, k) = s; } else { d_mat_entry(R, i, k) += s; } t += s * s; for (j = 0; j < A->r; j++) { d_mat_entry(Q, j, k) -= s * d_mat_entry(Q, j, i); } } s = 0; for (j = 0; j < A->r; j++) { s += d_mat_entry(Q, j, k) * d_mat_entry(Q, j, k); } t += s; flag = 0; if (s < t) { orig = 0; if (fabs(s * D_EPS) < 1.0e-308) s = 0; else flag = 1; } } d_mat_entry(R, k, k) = s = sqrt(s); if (s != 0) s = 1 / s; for (j = 0; j < A->r; j++) { d_mat_entry(Q, j, k) *= s; } } } flint2-2.8.4/d_mat/randtest.c000066400000000000000000000013141414523752600160070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/d_mat/set.c000066400000000000000000000013301414523752600147540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/d_mat/swap.c000066400000000000000000000011471414523752600151410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "d_mat.h" void d_mat_swap(d_mat_t mat1, d_mat_t mat2) { if (mat1 != mat2) { d_mat_struct tmp; tmp = *mat1; *mat1 = *mat2; *mat2 = tmp; } } flint2-2.8.4/d_mat/test/000077500000000000000000000000001414523752600147775ustar00rootroot00000000000000flint2-2.8.4/d_mat/test/t-entry.c000066400000000000000000000031301414523752600165420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("entry...."); fflush(stdout); /* 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) { flint_printf("FAIL: get/set entry %wd, %wd\n", j, k); abort(); } } } d_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_mat/test/t-equal.c000066400000000000000000000037071414523752600165220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("equal...."); fflush(stdout); /* 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)) { flint_printf("FAIL: different dimensions should not be equal\n"); abort(); } d_mat_randtest(A, state, 0, 0); d_mat_set(B, A); if (!d_mat_equal(A, B)) { flint_printf("FAIL: copied matrices should be equal\n"); abort(); } if (m && n) { j = n_randint(state, m * n); A->entries[j] += 1; if (d_mat_equal(A, B)) { flint_printf("FAIL: modified matrices should not be equal\n"); abort(); } } d_mat_clear(A); d_mat_clear(B); d_mat_clear(C); d_mat_clear(D); d_mat_clear(E); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_mat/test/t-gso.c000066400000000000000000000043671414523752600162060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "d_mat.h" #include "ulong_extras.h" #define D_MAT_GSO_NORM_EPS (4 * D_EPS) #define D_MAT_GSO_ORTHO_EPS (2 * D_EPS) int main(void) { int i, tmul = 100; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 1; #endif flint_printf("gso...."); fflush(stdout); /* check norm(column(gso)) = 1 or 0 * check dot product of columns of gso is zero */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { double dot; int j, k, l; d_mat_t A; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); d_mat_init(A, m, n); d_mat_randtest(A, state, 0, 0); d_mat_gso(A, A); for (j = 0; j < n; j++) { double norm = 0; for (l = 0; l < m; l++) { norm += d_mat_entry(A, l, j) * d_mat_entry(A, l, j); } if (norm != 0 && fabs(norm - 1) > D_MAT_GSO_NORM_EPS) { flint_printf("FAIL:\n"); flint_printf("A:\n"); d_mat_print(A); flint_printf("%g\n", norm); flint_printf("%d\n", j); abort(); } for (k = j + 1; k < n; k++) { dot = 0; for (l = 0; l < m; l++) { dot += d_mat_entry(A, l, j) * d_mat_entry(A, l, k); } if (fabs(dot) > D_MAT_GSO_ORTHO_EPS) { flint_printf("FAIL:\n"); flint_printf("A:\n"); d_mat_print(A); flint_printf("%g\n", dot); flint_printf("%d %d\n", j, k); abort(); } } } d_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/d_mat/test/t-init_clear.c000066400000000000000000000022041414523752600175130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); /* 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_mat/test/t-is_empty.c000066400000000000000000000022301414523752600172320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_empty...."); fflush(stdout); /* check if a non-zero value is returned for non-empty 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_empty(A) != (rows == 0 || cols == 0)) { flint_printf("FAIL!\n"); abort(); } d_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_mat/test/t-is_square.c000066400000000000000000000022211414523752600173740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_square...."); fflush(stdout); /* 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)) { flint_printf("FAIL!\n"); abort(); } d_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_mat/test/t-mul_classical.c000066400000000000000000000041711414523752600202220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_mat.h" #include "ulong_extras.h" #define D_MAT_MUL_CLASSICAL_EPS (1e-11) int main(void) { d_mat_t A, B, C, D, E, F, G; slong i; FLINT_TEST_INIT(state); flint_printf("mul_classical...."); fflush(stdout); /* 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)) { flint_printf("FAIL: results not equal\n"); d_mat_print(F); d_mat_print(G); abort(); } if (n == k) { d_mat_mul_classical(A, A, B); if (!d_mat_equal(A, E)) { flint_printf("FAIL: aliasing failed\n"); abort(); } } 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_mat/test/t-one.c000066400000000000000000000030721414523752600161670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, i, j, rep; FLINT_TEST_INIT(state); flint_printf("one...."); fflush(stdout); /* check if diagonal elements are one and off diagonal elements are 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_one(A); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { if (i == j && d_mat_entry(A, i, j) != 1) { flint_printf("FAIL: entry not one\n"); abort(); } else if (i != j && d_mat_entry(A, i, j) != 0) { flint_printf("FAIL: entry not zero\n"); abort(); } } } d_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_mat/test/t-qr.c000066400000000000000000000056251414523752600160360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "d_mat.h" #include "ulong_extras.h" #define D_MAT_QR_EQ_EPS (3 * D_EPS) #define D_MAT_QR_NORM_EPS (4 * D_EPS) #define D_MAT_QR_ORTHO_EPS (2 * D_EPS) int main(void) { int i; int tmul = 100; #ifdef _WIN32 tmul = 1; #endif FLINT_TEST_INIT(state); flint_printf("qr...."); fflush(stdout); /* check QR = A * check norm(column(Q)) = 1 or 0 * check dot product of columns of Q is zero */ for (i = 0; i < tmul * flint_test_multiplier(); i++) { double dot; int j, k, l; d_mat_t A, Q, R, B; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); d_mat_init(A, m, n); d_mat_init(Q, m, n); d_mat_init(R, n, n); d_mat_init(B, m, n); d_mat_randtest(A, state, 0, 0); d_mat_zero(R); d_mat_qr(Q, R, A); d_mat_mul_classical(B, Q, R); if (!d_mat_approx_equal(A, B, D_MAT_QR_EQ_EPS)) { flint_printf("FAIL:\n"); flint_printf("A:\n"); d_mat_print(A); flint_printf("Q:\n"); d_mat_print(Q); flint_printf("R:\n"); d_mat_print(R); flint_printf("B:\n"); d_mat_print(B); abort(); } for (j = 0; j < n; j++) { double norm = 0; for (l = 0; l < m; l++) { norm += d_mat_entry(Q, l, j) * d_mat_entry(Q, l, j); } if (norm != 0 && fabs(norm - 1) > D_MAT_QR_NORM_EPS) { flint_printf("FAIL:\n"); flint_printf("Q:\n"); d_mat_print(Q); flint_printf("%g\n", norm); flint_printf("%d\n", j); abort(); } for (k = j + 1; k < n; k++) { dot = 0; for (l = 0; l < m; l++) { dot += d_mat_entry(Q, l, j) * d_mat_entry(Q, l, k); } if (fabs(dot) > D_MAT_QR_ORTHO_EPS) { flint_printf("FAIL:\n"); flint_printf("Q:\n"); d_mat_print(Q); flint_printf("%g\n", dot); flint_printf("%d %d\n", j, k); abort(); } } } d_mat_clear(A); d_mat_clear(Q); d_mat_clear(R); d_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/d_mat/test/t-transpose.c000066400000000000000000000043301414523752600174220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "d_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep; FLINT_TEST_INIT(state); flint_printf("transpose...."); fflush(stdout); /* 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)) { flint_printf("FAIL: C != A\n"); flint_printf("C:\n"); d_mat_print(C); flint_printf("A:\n"); d_mat_print(A); abort(); } 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)) { flint_printf("FAIL: B != A\n"); flint_printf("B:\n"); d_mat_print(B); flint_printf("A:\n"); d_mat_print(A); abort(); } d_mat_clear(A); d_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_mat/test/t-zero.c000066400000000000000000000024721414523752600163700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, i, j, rep; FLINT_TEST_INIT(state); flint_printf("zero...."); fflush(stdout); /* 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) { flint_printf("FAIL: nonzero entry\n"); abort(); } } } d_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_mat/transpose.c000066400000000000000000000023071414523752600162040ustar00rootroot00000000000000/* 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 2.1 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_printf ("Exception (d_mat_transpose). Incompatible dimensions.\n"); flint_abort(); } 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); } flint2-2.8.4/d_mat/zero.c000066400000000000000000000011311414523752600151370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/d_vec.h000066400000000000000000000044671414523752600142000ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define D_VEC_INLINE static __inline__ #endif #include #include "double_extras.h" #include "flint.h" #ifdef __cplusplus extern "C" { #endif /* Memory management *******************************************************/ FLINT_DLL double * _d_vec_init(slong len); FLINT_DLL void _d_vec_clear(double * vec); /* Randomisation ***********************************************************/ FLINT_DLL void _d_vec_randtest(double * f, flint_rand_t state, slong len, slong minexp, slong maxexp); /* Assignment and basic manipulation ***************************************/ FLINT_DLL void _d_vec_set(double * vec1, const double * vec2, slong len2); FLINT_DLL void _d_vec_zero(double * vec, slong len); /* Comparison **************************************************************/ FLINT_DLL int _d_vec_equal(const double * vec1, const double * vec2, slong len); FLINT_DLL int _d_vec_approx_equal(const double * vec1, const double * vec2, slong len, double eps); FLINT_DLL int _d_vec_is_zero(const double * vec, slong len); FLINT_DLL int _d_vec_is_approx_zero(const double * vec, slong len, double eps); /* Addition ****************************************************************/ FLINT_DLL void _d_vec_add(double * res, const double * vec1, const double * vec2, slong len2); FLINT_DLL void _d_vec_sub(double * res, const double * vec1, const double * vec2, slong len2); /* Dot product and norm **************************************/ FLINT_DLL double _d_vec_dot(const double * vec1, const double * vec2, slong len2); FLINT_DLL double _d_vec_norm(const double * vec, slong len); FLINT_DLL double _d_vec_dot_heuristic(const double * vec1, const double * vec2, slong len2, double * err); FLINT_DLL double _d_vec_dot_thrice(const double * vec1, const double * vec2, slong len2, double * err); #ifdef __cplusplus } #endif #endif flint2-2.8.4/d_vec/000077500000000000000000000000001414523752600140145ustar00rootroot00000000000000flint2-2.8.4/d_vec/add.c000066400000000000000000000012021414523752600147030ustar00rootroot00000000000000/* 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 2.1 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]; } flint2-2.8.4/d_vec/approx_equal.c000066400000000000000000000013601414523752600166600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "d_vec.h" 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; } flint2-2.8.4/d_vec/clear.c000066400000000000000000000007541414523752600152540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "d_vec.h" void _d_vec_clear(double *vec) { flint_free(vec); } flint2-2.8.4/d_vec/dot.c000066400000000000000000000012331414523752600147450ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/d_vec/dot_heuristic.c000066400000000000000000000021161414523752600170250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 = ldexp(1.0, pexp - D_BITS); n = ldexp(1.0, nexp - D_BITS); d = FLINT_MAX(p, n); *err = 2 * len2 * d; } return psum - nsum; } flint2-2.8.4/d_vec/dot_thrice.c000066400000000000000000000040631414523752600163070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/d_vec/equal.c000066400000000000000000000012411414523752600152650ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/d_vec/init.c000066400000000000000000000010221414523752600151160ustar00rootroot00000000000000/* 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 2.1 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)); } flint2-2.8.4/d_vec/is_approx_zero.c000066400000000000000000000011611414523752600172220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "d_vec.h" 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; } flint2-2.8.4/d_vec/is_zero.c000066400000000000000000000011271414523752600156330ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/d_vec/norm.c000066400000000000000000000012031414523752600151270ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/d_vec/randtest.c000066400000000000000000000011441414523752600160040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/d_vec/set.c000066400000000000000000000012241414523752600147520ustar00rootroot00000000000000/* 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 2.1 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]; } } flint2-2.8.4/d_vec/sub.c000066400000000000000000000012021414523752600147440ustar00rootroot00000000000000/* 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 2.1 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]; } flint2-2.8.4/d_vec/test/000077500000000000000000000000001414523752600147735ustar00rootroot00000000000000flint2-2.8.4/d_vec/test/t-add.c000066400000000000000000000037601414523752600161360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); abort(); } _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) { flint_printf("FAIL:\n"); abort(); } _d_vec_clear(a); _d_vec_clear(b); _d_vec_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_vec/test/t-dot.c000066400000000000000000000030711414523752600161670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_vec.h" #include "ulong_extras.h" #define D_VEC_SP_EPS (1e-14) int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("dot...."); fflush(stdout); /* check sum of scalar products of parts of vectors is equal to the scalar product of vectors */ for (i = 0; i < 10000 * 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) { flint_printf("FAIL:\n"); printf("%g\n", fabs(res1 + res2 - res3)); abort(); } _d_vec_clear(a); _d_vec_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_vec/test/t-dot_heuristic.c000066400000000000000000000035771414523752600202610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_vec.h" #include "ulong_extras.h" #define D_VEC_SP_EPS (1e-14) int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("dot_heuristic...."); fflush(stdout); /* check sum of scalar products of parts of vectors is equal to the scalar product of vectors */ for (i = 0; i < 10000 * 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) { flint_printf("FAIL:\n"); flint_printf("%g\n", fabs(res1 + res2 - res3)); flint_printf("%g\n", res1); flint_printf("%g\n", res2); flint_printf("%g\n", res3); flint_printf("%g\n", err1); flint_printf("%g\n", err2); flint_printf("%g\n", err3); abort(); } _d_vec_clear(a); _d_vec_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_vec/test/t-dot_thrice.c000066400000000000000000000035631414523752600175330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_vec.h" #include "ulong_extras.h" #define D_VEC_SP_EPS (1e-14) int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("dot_thrice...."); fflush(stdout); /* check sum of scalar products of parts of vectors is equal to the scalar product of vectors */ for (i = 0; i < 10000 * 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) { flint_printf("FAIL:\n"); flint_printf("%g\n", fabs(res1 + res2 - res3)); flint_printf("%g\n", res1); flint_printf("%g\n", res2); flint_printf("%g\n", res3); flint_printf("%g\n", err1); flint_printf("%g\n", err2); flint_printf("%g\n", err3); abort(); } _d_vec_clear(a); _d_vec_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_vec/test/t-init_clear.c000066400000000000000000000020071414523752600175100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); /* 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_vec/test/t-norm.c000066400000000000000000000026641414523752600163630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_vec.h" #include "ulong_extras.h" #define D_VEC_NORM_EPS (1e-14) int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("norm...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); printf("%g\n", fabs(res1 + res2 - res3)); abort(); } _d_vec_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_vec/test/t-set_equal.c000066400000000000000000000043541414523752600173700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set/equal...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); abort(); } _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) { flint_printf("FAIL:\n"); abort(); } _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) { flint_printf("FAIL:\n"); abort(); } _d_vec_clear(a); _d_vec_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_vec/test/t-sub.c000066400000000000000000000052741414523752600162010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); /* 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_sub(c, a, b, len); _d_vec_sub(a, a, b, len); result = (_d_vec_equal(a, c, len)); if (!result) { flint_printf("FAIL:\n"); abort(); } _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_sub(c, a, b, len); _d_vec_sub(b, a, b, len); result = (_d_vec_equal(b, c, len)); if (!result) { flint_printf("FAIL:\n"); abort(); } _d_vec_clear(a); _d_vec_clear(b); _d_vec_clear(c); } /* Check a + b - b = a */ for (i = 0; i < 1000 * 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) { flint_printf("FAIL:\n"); abort(); } _d_vec_clear(a); _d_vec_clear(b); _d_vec_clear(c); _d_vec_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_vec/test/t-zero.c000066400000000000000000000023111414523752600163540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "d_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("zero...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); abort(); } _d_vec_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/d_vec/zero.c000066400000000000000000000011111414523752600151310ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/deprecations.txt000066400000000000000000000012501414523752600161530ustar00rootroot00000000000000# Deprecated in Flint 2.6.0 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 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 flint2-2.8.4/doc/000077500000000000000000000000001414523752600135015ustar00rootroot00000000000000flint2-2.8.4/doc/Makefile000066400000000000000000000011361414523752600151420ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = 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)flint2-2.8.4/doc/latex/000077500000000000000000000000001414523752600146165ustar00rootroot00000000000000flint2-2.8.4/doc/latex/flint-manual.bib000066400000000000000000000362341414523752600176730ustar00rootroot00000000000000@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}, } flint2-2.8.4/doc/latex/flint-manual.tex000066400000000000000000004240671414523752600177440ustar00rootroot00000000000000% vim: spell spelllang=en textwidth=80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % This file is part of FLINT. % % FLINT is free software: you can redistribute it and/or modify it under % the terms of the GNU Lesser General Public License (LGPL) as published % by the Free Software Foundation; either version 2.1 of the License, or % (at your option) any later version. See . % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Copyright (C) 2007 William Hart, David Harvey % Copyright (C) 2010 Sebastian Pancratz % Copyright (C) 2013 Tom Bachmann % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \documentclass[a4paper,10pt]{book} %%%%%%%%%%%% % geometry % %%%%%%%%%%%% \usepackage[hmargin=3.8cm,vmargin=3cm,a4paper,centering,twoside]{geometry} \setlength{\headheight}{14pt} % Dutch style of paragraph formatting, i.e. no indents \setlength{\parskip}{1.3ex plus 0.2ex minus 0.2ex} \setlength{\parindent}{0pt} %%%%%%%%%%%%%%%%%% % Other packages % %%%%%%%%%%%%%%%%%% \usepackage{amsmath,amsthm,amscd,amsfonts,amssymb} \usepackage{cases} \usepackage[all]{xy} \usepackage{ifpdf} \usepackage{paralist} \usepackage{fancyhdr} \usepackage{sectsty} \usepackage{epigraph} \usepackage{natbib} \usepackage{url} \usepackage[T1]{fontenc} \usepackage{ae,aecompl} \usepackage{booktabs} \usepackage{multirow} \usepackage{verbatim} \usepackage{listings} %%%%%%%%%%%% % hyperref % %%%%%%%%%%%% \usepackage{hyperref} \hypersetup{ colorlinks=true, % false: boxed links; true: colored links citecolor=green, % color of links to bibliography filecolor=red, % color of file links linkcolor=blue, % color of internal links urlcolor=blue % color of external links } \makeatletter \newcommand\org@hypertarget{} \let\org@hypertarget\hypertarget \renewcommand\hypertarget[2]{% \Hy@raisedlink{\org@hypertarget{#1}{}}#2% } \makeatother \ifpdf \hypersetup{ pdftitle={FLINT}, pdfauthor={}, pdfsubject={Computational mathematics}, bookmarks=true, bookmarksnumbered=true, unicode=true, pdfstartview={FitH}, pdfpagemode={UseOutlines} } \fi %%%%%%%%%% % natbib % %%%%%%%%%% \bibpunct{[}{]}{,}{n}{}{} \renewcommand{\bibname}{References} %%%%%%%%%%% % sectsty % %%%%%%%%%%% \allsectionsfont{\nohang\centering} \sectionfont{\nohang\centering\large} \makeatletter \renewcommand{\@makechapterhead}[1]{% \vspace*{50 pt}% \begin{center} \bfseries\Huge\S \thechapter.\ #1 \end{center} \vspace*{40 pt}} \makeatother %%%%%%%%%%%%%%%%%%%%% % Table of contents % %%%%%%%%%%%%%%%%%%%%% \usepackage{tocloft} \addtolength{\cftsecnumwidth}{0.8em} \addtolength{\cftsubsecnumwidth}{0.8em} \addtolength{\cftbeforesecskip}{0.05em} %%%%%%%%%%%% % fancyhdr % %%%%%%%%%%%% \newcommand\nouppercase[1]{{% \let\uppercase\relax \let\MakeUppercase\relax \expandafter\let\csname MakeUppercase \endcsname\relax#1}% } \pagestyle{fancyplain} \renewcommand{\chaptermark}[1]{\markboth{#1}{}} \renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}} \fancyhf{} \fancyhead[LE,RO]{\bfseries\thepage} \fancyhead[LO]{\itshape\nouppercase{\rightmark}} \fancyhead[RE]{\itshape\nouppercase{\leftmark}} \renewcommand{\headrulewidth}{0pt} \renewcommand{\footrulewidth}{0pt} \fancypagestyle{plain}{% \fancyhead{} \renewcommand{\headrulewidth}{0pt} } \makeatletter \def\cleardoublepage{\clearpage\if@twoside \ifodd\c@page\else \hbox{} \thispagestyle{plain} \newpage \if@twocolumn\hbox{}\newpage\fi\fi\fi} \makeatother \clearpage{\pagestyle{plain}\cleardoublepage} %%%%%%% % url % %%%%%%% \makeatletter \def\url@leostyle{% \@ifundefined{selectfont}{\def\UrlFont{\sf}}{\def\UrlFont{\small\ttfamily}}} \makeatother \urlstyle{leostyle} %%%%%%%%%%%%%%%% % Enumerations % %%%%%%%%%%%%%%%% \setlength{\pltopsep}{0.24em} \setlength{\plpartopsep}{0em} \setlength{\plitemsep}{0.24em} % This should do what we want % \setdefaultenum{(i)}{(a)}{1.}{A} % but it does not work for references, dropping the % parentheses. The following hack does work. \renewcommand{\theenumi}{(\roman{enumi})} \renewcommand{\theenumii}{(\alph{enumii})} \renewcommand{\theenumiii}{\arabic{enumiii}.} \renewcommand{\theenumiv}{\Alph{enumiv}} \renewcommand{\labelenumi}{\theenumi} \renewcommand{\labelenumii}{\theenumii} \renewcommand{\labelenumiii}{\theenumiii} \renewcommand{\labelenumiv}{\theenumiv} %%%%%%%%%%%%%%%%%%%%%%%%% % Mathematical commands % %%%%%%%%%%%%%%%%%%%%%%%%% \renewcommand{\to}{\rightarrow}% Right arrow \newcommand{\into}{\hookrightarrow}% Injection arrow \newcommand{\onto}{\twoheadrightarrow}% Surjection arrow \providecommand{\abs}[1]{\lvert#1\rvert}% Absolute value \providecommand{\absbig}[1]{\bigl\lvert#1\bigr\rvert}% Absolute value \providecommand{\absBig}[1]{\Bigl\lvert#1\Bigr\rvert}% Absolute value \providecommand{\absbigg}[1]{\biggl\lvert#1\biggr\rvert}% Absolute value \providecommand{\norm}[1]{\lVert#1\rVert}% Norm \providecommand{\normbig}[1]{\bigl\lVert#1\bigr\rVert}% Norm \providecommand{\normBig}[1]{\Bigl\lVert#1\Bigr\rVert}% Norm \providecommand{\floor}[1]{\left\lfloor#1\right\rfloor}% Floor \providecommand{\floorbig}[1]{\bigl\lfloor#1\bigr\rfloor}% Floor \providecommand{\floorBig}[1]{\Bigl\lfloor#1\Bigr\rfloor}% Floor \providecommand{\ceil}[1]{\left\lceil#1\right\rceil}% Ceiling \providecommand{\ceilbig}[1]{\bigl\lceil#1\bigr\rceil}% Ceiling \providecommand{\ceilBig}[1]{\Bigl\lceil#1\Bigr\rceil}% Ceiling \newcommand{\N}{\mathbf{N}}% Natural numbers \newcommand{\Z}{\mathbf{Z}}% Integers \newcommand{\Q}{\mathbf{Q}}% Rationals \newcommand{\F}{\mathbf{F}}% Finite fields \DeclareMathOperator{\sgn}{sgn} \DeclareMathOperator{\ord}{ord} \DeclareMathOperator{\lcm}{lcm} \DeclareMathOperator{\Gal}{Gal} \DeclareMathOperator{\Norm}{N} \DeclareMathOperator{\Trace}{Tr} \DeclareMathOperator{\Res}{Res} \allowdisplaybreaks[4] %\numberwithin{equation}{section} %%%%%%%%%%%% % listings % %%%%%%%%%%%% \lstset{language=c} \lstset{basicstyle=\ttfamily} \lstset{breaklines=true} \lstset{breakatwhitespace=true} \lstset{keywordstyle=} \lstset{morekeywords={mpz_t, mpq_t, mpz_poly_t, fmpz, fmpz_t, fmpz_poly_t}} \lstset{escapechar=} \lstset{showstringspaces=false} %%%%%%%%%%%%%%%%%%%%%%%%%%% % FLINT specific commands % %%%%%%%%%%%%%%%%%%%%%%%%%%% \newcommand{\code}{\lstinline} \DeclareMathOperator{\len}{len} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % DOCUMENT % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{document} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % FRONTMATTER % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \frontmatter \input{input/title.tex} \clearpage \tableofcontents %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % MAINMATTER % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \mainmatter \chapter{Introduction} FLINT is a C library of functions for doing number theory. It is highly optimised and can be compiled on numerous platforms. FLINT also has the aim of providing support for multicore and multiprocessor computer architectures. To this end, the library is threadsafe, with few exceptions noted in the appropriate place. FLINT is currently maintained by William Hart of Technische Universit\"{a}t in Kaiserslautern and 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. (See the Contributors list below for a list.) FLINT 2 and following should compile on any machine with GCC and a standard GNU toolchain, however it is specially optimised for x86 (32 and 64 bit) machines. There is also limited optimisation for ARM and ia64 machines. As of version 2.0, FLINT required GCC version 2.96 or later, either MPIR (2.6.0 or later) or GMP (5.1.1 or later), and MPFR 3.0.0 or later. It is also required that the platform provide a \code{uint64_t} type if a native 64 bit type is not available. Full C99 compliance is \textbf{not} required. FLINT is supplied as a set of modules, \code{fmpz}, \code{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 \code{fmpz_poly_add} located in\\ \code{fmpz_poly/add.c} has test code in the file \code{fmpz_poly/test/t-add.c}. FLINT is distributed under the GNU Lesser General Public License (LGPL). There is a copy of the license included with this document. \chapter{Configuring FLINT} The easiest way to use FLINT is to build a shared library. Simply download the FLINT tarball and untar it on your system. FLINT requires either MPIR (version 2.6.0 or later) or GMP (version 5.1.1 or later). If MPIR is used, MPIR must be built with the \code{--enable-gmpcompat} option. FLINT also requires MPFR 3.0.0 or later and a pthread implementation. Some of the input/output tests require \code{fork} and \code{pipe}, however these are disabled on MinGW which does not provide a posix implementation. If it happens that GMP/MPIR and MPFR are not in a standard location on your system (e.g. not in /usr/include/ and /usr/lib/), you need to tell the configure script where they are with the options \code{--with-gmp}, \code{--with-mpir} or \code{--with-mpfr}. For example \begin{lstlisting}[language=bash] ./configure --with-gmp=/my/directory/ --with-mpfr=/my/directory/ \end{lstlisting} or alternatively when using MPIR \begin{lstlisting}[language=bash] ./configure --with-mpir=/my/directory/ --with-mpfr=/my/directory/ \end{lstlisting} FLINT can also handle a source build of GMP/MPIR and MPFR. Though programs using FLINT will require GMP/MPIR and MPFR to be installed (via \code{make install} if built from sources). This is in particular true for the test code for FLINT: running \code{make check} requires GMP/MPIR and MPFR to be installed. Note that 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 \code{--disable-static} or \code{--disable-shared} to \code{configure}. If you intend to install the FLINT library and header files, you can specify where they should be placed by passing \code{--prefix=path} to configure, where \code{path} is the directory under which the \code{lib} and \code{include} directories exist into which you wish to place the FLINT files when it is installed. \chapter{TLS, reentrancy and single mode} If you wish to use FLINT on a single core machine then it can be configured for single mode. This mode can also be explicitly selected by passing the \code{--single} option to configure. Single mode is slightly faster, but by default uses thread local storage if threads are used, and this is not available on some machines. FLINT uses thread local storage by default (\code{--enable-tls}). However, if reentrancy is required on systems that do not support this, one can pass \code{--disable-tls} and mutexes will be used instead (requires POSIX). If you wish to build a threadsafe version of FLINT which uses a less complicated memory model (slower, but still works in the absence of TLS) you can pass the \code{--reentrant} option to configure. \chapter{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 \code{ABI=64} or \code{ABI=32} to configure. To build on MinGW64 it is necessary to pass \code{ABI=64} to configure, as FLINT is otherwise unable to distinguish it from MinGW32. In some cases, it is necessary to override the entire CPU/OS defaults. This can be done by passing \code{--build=cpu-os} to configure. The available choices for CPU include \code{x86_64}, \code{x86}, \code{ia64}, \code{sparc}, \code{sparc64}, \code{ppc}, \code{ppc64}. Other CPU types are unrecognised and FLINT will build with generic code on those machines. The choices for OS include \code{Linux}, \code{MINGW32}, \code{MINGW64}, \code{CYGWIN32}, \code{CYGWIN64}, \code{Darwin}, \code{FreeBSD}, \code{SunOS} and numerous other operating systems. It is also possible to override the default CC, AR and CFLAGS used by FLINT by passing \code{CC=full_path_to_compiler}, etc., to FLINT's configure. \chapter{Building FLINT2 with Microsoft Visual Studio 2015} Dr. Brian Gladman has kindly provided the build scripts for building Flint with Microsoft Visual Studio. Building FLINT2 with Microsoft Visual Studio requires Visual Studio 2015 Community (or higher version) and: \begin{itemize} \item an installed version of Python 3 \item an installed version of Python Tools for Visual Studio (\url{https://github.com/Microsoft/PTVS}) \end{itemize} Obtain FLINT2 either as a released distribution or clone it using GIT from: \indent \url{git@github.com:BrianGladman/flint2.git} FLINT2 depends on the MPIR, MPFR and PTHREADS libraries that have to be installed and built using Visual Studio before FLINT2 can be built. The application directories are assumed to be in the same root directory with the names and layouts: \begin{verbatim} mpir build.vc14 lib dll mpfr build.vc14 lib dll pthreads build.vc14 lib dll flint2 build.vc14 lib dll \end{verbatim} where the build.vc14 directories hold the Visual Studio build files and the lib and dll directories hold the static and dynamic library outputs for each package. Libraries on which FLINT2 depends have to be built for the same configuration that will be used to build FLINT2 before FLINT2 itself can be built: \begin{itemize} \item \item \item \end{itemize} where shows the choices (a or b) that have to be made. Opening the solution file flint.sln in Visual Studio 2015 provides the following build projects: \begin{verbatim} dll_flint - a Visual Studio build project for FLINT2 as a Dynamic Link Library lib_flint - a Visual Studio build project for FLINT2 as a Static Library flint_config - a Python program for creating the Visual Studio build files build_tests - a Python program for building the FLINT2 tests (after they have been created) run_tests - a Python program for running the FLINT2 tests (after they have been built) \end{verbatim} The projects \code{lib_flint} and \code{dll_flint} can be used immediately to build FLINT2 as a Static and Dynamic Link Library respectively. Before building one or both of these, you need to select the architecture (Win32 or x64) and the build type (Release or Debug). To run the FLINT2 tests, the necessary Visual Studio build files have to be created. If you have Python and Python Tools for Visual Studio (PTVS) installed, this is done by setting the project \code{flint_config} (loaded into Visual Studio by the solution file flint.sln) as the start-up project and then running it. If you don't have PTVS installed but you do have Python, you can run \code{flint_config.py} directly without Visual Studio. By default \code{flint_config} creates only the FLINT2 tests and profiling. But it can also recreate the Visual Studio 2015 build files for the FLINT2 DLL and Static Libraries by changing the defines at the start of \code{flint_config.py}: \begin{verbatim} build_lib = False build_dll = False build_tests = True build_profiles = True \end{verbatim} Rebuilding the library build files in this way may be necessary if FLINT2 has been updated since it was first downloaded. After the FLINT2 tests have been created using \code{flint_config.py}, they can then be built by setting \code{build_tests.py} as the start up project and then running it. There are also a number of Visual Studio solution files that provide an \emph{alternative} way of building the FLINT2 tests and profiling. However, their use is not recommended because each of the multiple solution files \code{flint-tests.sln} (where NN is a number) has to be loaded and built by Visual Studio (this approach is used because it takes Visual Studio too long to load the tests from a single solution file). Once the tests have been built, the Python project \code{run_tests} can be set as the start-up project and started to run all the tests (or the file \code{run_tests.py} can be run outside Visual Studio). After building FLINT2, the libraries and the header files that you need to use FLINT2 are placed in the directories: \begin{itemize} \item \code{lib\\} \item \code{dll\\} \end{itemize} depending on the version(s) that have been built. \chapter{C++ wrapper} If you wish to enable the test functions for the FLINT C$++$ wrapper \code{flintxx} you must pass \code{--enable-cxx} to configure. The \code{C++} wrapper is always available, but tests will only run if this option is selected. It is disabled by default (\code{--disable-cxx}) because some \code{C++} compilers internally segfault when compiling the tests, or exhaust memory due to the complexity of the \code{C++} code. \chapter{Exceptions} When FLINT encounters a problem, mostly illegal input, it currently aborts. There is an experimental interface for generating proper exceptions \code{flint_throw}, but this is almost nowhere used (currently) and experimental - you should expect for this to change. At the end, all of FLINT's exceptions call \code{abort()} to terminate the program. Using \code{flint_set_abort(void (*abort_func)(void))}, the user can install a function that will be called instead. Similar to the exceptions, this should be regarded as experimental. \chapter{Garbage collection} If building FLINT as part of an application that uses the Boehm-Demers-Weiser GC library, you may wish to pass the \code{--with-gc= // other system headers #undef ulong #define ulong mp_limb_t \end{lstlisting} This prevents FLINT's definition of \code{ulong} interfering with your system headers. The FLINT make system responds to the standard commands \begin{lstlisting}[language=bash] make make library make check make clean make distclean make install \end{lstlisting} In addition, if you wish to simply check a single module of FLINT you can pass the option \code{MOD=modname} to \code{make check}. You can also pass a list of module names in inverted commas, e.g: \begin{lstlisting}[language=bash] make check MOD=ulong_extras make check MOD="fft fmpz_mat" \end{lstlisting} To specify an individual test(s) for any module you can add it (or comma separated test list) after chosen module name followed by the colon, e.g.: \begin{lstlisting}[language=bash] make check MOD=ulong_extras:clog,factor,is_prime make check MOD="fft fmpz_mat:add_sub,charpoly fq_vec:add" \end{lstlisting} FLINT has an assert system. If you want a debug build you can pass \code{--enable-assert} to configure. However, this will slow FLINT considerably, so asserts should not be enabled (\code{--disable-assert}, the default) for deployment. If your system supports parallel builds, FLINT will build in parallel, e.g: \begin{lstlisting}[language=bash] make -j4 check \end{lstlisting} Note that on some systems, most notably MinGW, parallel make is supported but can be problematic. \chapter{FLINT extension modules} Numerous developers have been building libraries on top of FLINT, extending its functionality. These projects are known as FLINT extension modules. To build a FLINT extension module as part of FLINT, do the following: $\bullet$ Download the flint extension module and place it somewhere in your file system. $\bullet$ Pass \code{--extensions=/path/to/extension} to FLINT's configure, or if more than one extension is desired use \code{--extensions="/path/to/extension1 /path/to/extension2"}, etc. Now most of the options that are available for FLINT are also available for those extension modules. Some examples of FLINT extension modules include: $\bullet$ Arb (by Fredrik Johansson) -- Arbitrary precision floating point ball arithmetic with rigorous error bounds, over the real and complex numbers (including polynomials, matrices, calculus and special functions). \url{http://fredrikj.net/arb/} $\bullet$ ANTIC (by William Hart and Claus Fieker) -- Algebraic Number Theory in C. Includes general number field arithmetic and class group computation. \url{https://github.com/wbhart/antic} $\bullet$ Bland (by Fredrik Johansson) -- Generic recursive rings over the basic FLINT types. \url{https://github.com/fredrik-johansson/bland} See the FLINT website \url{http://flintlib.org/} for a full list. Writing extension modules is trivial. One should include a top level directory containing a single directory for each module one wishes to supply. FLINT expects to find, in the top level, a \code{.h} file with the same name as each module directory. Inside each module directory there must be at least one \code{.c} file. There should also be a \code{test} subdirectory. Test files in the \code{test} subdirectories should be of the form \code{t-*.c} or \code{t-*.cpp}. You may optionally add \code{doc}, \code{profile} and \code{tune} subdirectories to each module directory. These may be supported by some later version of FLINT. \chapter{Test code} Each module of FLINT has an extensive associated test module. We strongly recommend running the test programs before relying on results from FLINT on your system. To make and run the test programs, simply type: \begin{lstlisting}[language=bash] make check \end{lstlisting} in the main FLINT directory after configuring FLINT. \chapter{Reporting bugs} The maintainer wishes to be made aware of any and all bugs. Please send an email with your bug report to \url{hart_wb@yahoo.com} or report them on the FLINT devel list \url{https://groups.google.com/group/flint-devel?hl=en}. If possible please include details of your system, the version of GCC, the versions of GMP/MPIR and MPFR as well as precise details of how to replicate the bug. Note that FLINT needs to be linked against version 2.6.0 or later of MPIR (or version 5.1.1 or later of GMP), version 3.0.0 or later of MPFR and must be compiled with gcc version 2.96 or later. \chapter{Contributors} FLINT 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. The authors of FLINT to date: $\bullet$ William Hart -- integer and polynomial arithmetic, factorisation and primality testing, general infrastructure (supported by EPSRC Grant EP/G004870/1 and DFG Priority programme SPP1489) $\bullet$ Sebastian Pancratz -- polynomial arithmetic over $\Z$, $\Z/n\Z$ and $\Q$, $p$-adic and $q$-adic arithmetic, including polynomials and matrices (supported by ERC Grant 204083) $\bullet$ Andy Novocin -- LLL, polynomial factorisation over $Z$, polynomial composition $\bullet$ Fredrik Johansson -- matrices, polynomial and power series arithmetic, special functions (supported by Austrian Science Fund FWF Grant Y464-N18) $\bullet$ Tom Bachmann -- \code{C++} expressions template wrapper, documentation parser (Google Summer of Code 2013) $\bullet$ 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$ (supported by Macaulay2 developers NSF Grant 1002171) $\bullet$ Martin Lee -- Fast factorisation of polynomials over $\Z/n\Z$, faster Brent-Kung modular composition $\bullet$ David Harvey -- Fast Fourier Transform code, \code{zn_poly} for polynomial arithmetic over $\Z/n\Z$, \code{mpz_poly}, profiling and graphing code and many other parts of the FLINT library $\bullet$ Jan Tuitman -- helped with the $p$-adic interface $\bullet$ Jason Papadopoulos -- Block Lanczos code for quadratic sieve and multiprecision complex root finding code for polynomials. $\bullet$ Gonzalo Tornaria -- Theta function module, Montgomery multiplication and significant contributions to the $\Z[x]$ modular multiplication code. $\bullet$ 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. (Supported by DFG Priority programme SPP1489.) $\bullet$ Tom Boothby -- Improved factoring of unsigned longs, detection of perfect powers $\bullet$ Andres Goens -- $\F_q$ module and polynomials over $\F_q$ (supported by DFG Priority program SPP1489) $\bullet$ Lina Kulakova -- factorisation for polynomials over $\F_p$ for large $p$ (Google Summer of Code 2012) $\bullet$ Abhinav Baid -- LLL implementation, Ogita, Rump, Oishi dot product, Villard algorithm for LLL certification, Schwarz-Rutishauser algorithms for GSO and QR-decomposition (Google Summer of Code 2014) $\bullet$ Curtis Bright -- Mentoring/planning of LLL implementation, numerous patches including 32 bit support $\bullet$ Alex Best -- Hermite Normal Form implementation including the Pernet-Stein algorithm and Smith Normal Form implementation including the Iliopoulos and Kannan-Bachem algorithms. Numerous improvements to nullspace, rref and rank computations (Google Summer of Code 2014) $\bullet$ Thomas DuBuisson -- logical ops for fmpz module, patches to the build system $\bullet$ Jean-Pierre Flori -- many build system patches and Sage integration $\bullet$ Frithjof Schulze -- some fmpz functions and various patches $\bullet$ Daniel Woodhouse -- Contributed an implementation of multivariate multiplication over $\Z/n\Z$ and used this to implement a fast ``saturation'' algorithm for Laurent polynomials. (Funded by Alessio Corti and Tom Coates at Imperial College) $\bullet$ Tomasz Lechowski -- Contributed some NTL and Pari polynomial profiling code and researched algorithms for polynomials over finite fields. (Funded by the Nuffield Foundation) $\bullet$ Daniel Scott -- Researched lazy and relaxed algorithms of Joris van der Hoeven. (Funded by Warwick University's Undergraduate Research Scholars Scheme) $\bullet$ David Howden -- Wrote code for computing Bernoulli numbers mod many primes, including fast polynomial multiplication over $\Z/p\Z$ specifically for the task. (Funded by Warwick University's Undergraduate Research Scholars Scheme) $\bullet$ Daniel Ellam -- Helped design a module for $p$-adic arithmetic for FLINT. (Funded by Warwick University's Undergraduate Research Scholars Scheme) $\bullet$ Richard Howell-Peak -- Wrote polynomial factorisation and irreducibility testing code for polynomials over $\Z/p\Z$. (Funded by Warwick University's Undergraduate Research Scholars Scheme) $\bullet$ Peter Shrimpton -- Wrote code for a basic prime sieve, Pocklington-Lehmer, Lucas, Fibonacci, BSPW and $n-1$ primality tests and a Weiferich prime search. (Funded by the Nuffield Foundation) $\bullet$ Brian Gladman -- MSVC support $\bullet$ Dana Jacobsen -- test BPSW primality code up to $2^{64}$ against Feitma's tables and sped up and corrected \code{n_is_prime} and \code{n_is_probabprime}. Improvements to \code{n_nextprime} and \code{n_isprime}. $\bullet$ Anubhav Srivastava contributed horizontal and vertical concatenation of matrices over $\mathbb{Z}$ and an implementation of the Bodrato matrix squaring algorithm. $\bullet$ Dharak Kharod and Prabhdeep Singh Walia both independently contributed matrix content. $\bullet$ Alena Sergeicheva contributed a patch to the build system for individual file testing and also contributed numerous matrix concatenation functions. $\bullet$ Kushagra Singh contributed fast cube root and nth root code for word sized integers, including magic number, Newton iteration, Kahan iteration and Chebyshev approximation code, he also contributed ECM and Pollard's Rho factoring algorithm implementations as part of a Google Summer of Code. $\bullet$ Andreas Enge help with a port to MIPS64. $\bullet$ Tommy Hofmann implemented Howell and strong echelon form and supplied some inline functions. $\bullet$ Ashish Kedia contributed an implementation of the Paterson-Stockmeyer algorithm $\bullet$ Nitin Kumar contributed under a Google Summer of Code project to the quadratic sieve $\bullet$ Vladimir Glazachev contributed an implementation of the APRCL primality testing algorithm and Shoup multiplication as part of a Google Summer of Code $\bullet$ Dan Roche contributed randprime and nextprime functions for the fmpz module $\bullet$ Shivin Shrivastava contributed Fibonacci polynomials and some Taylor shift improvements $\bullet$ Alex Griffing contributed integer factor refinement and numerous small patches $\bullet$ Vincent Delecroix contributed power sums and some patches $\bullet$ Aaditya Thakkar contributed Strassen multiplication over Z $\bullet$ Ralf Stephan contributed Hermite polynomials $\bullet$ Patches and bug reports have been made by Michael Abshoff, Didier Deshommes, Craig Citro, Timothy Abbot, Carl Witty, Gonzalo Tornaria, Jaap Spies, Kiran Kedlaya, William Stein, Kate Minola, Didier Deshommes, Robert Bradshaw, Serge Torres, Dan Grayson, Martin Lee, Bob Smith, Antony Vennard, Fr\'{e}d\'{e}ric Chyzak, Julien Puydt, Dana Jacobsen, Michael Jacobson Jr., Mike Stillman, Jan Englehardt, Jean-Pierre Flori, Jeroen Demeyer, Shi Bai, Qingwen Guan, Frithjof Schulze, Robert Baillie, Oleksandr Motsak, Hans Schoenemann, Janko Boehm, Ahmed Soliman, Francois Bissey, Anton Mellit, Daniel Roche, Denis Kryskov, Daniel Fabian, Julien Ospald, mgkurtz, Max Goldfar, Max $\bullet$ In addition Michael Abshoff, William Stein and Robert Bradshaw have contributed to the build system of FLINT. $\bullet$ Michael Abshoff deserves special recognition for his help in resolving a number of difficult build issues which came to light as FLINT was incorporated into SAGE and for bringing numerous bugs to the attention of the FLINT maintainers. Michael regularly checked FLINT for memory leaks and corruption, which directly led to numerous issues being identified early! He also helped with setting up various pieces of infrastructure for the FLINT project. $\bullet$ Numerous people have contributed to wrapping FLINT in Sage and debugging, including Mike Hansen, Jean-Pierre Flori, Burcin Erocal, Robert Bradshaw, Martin Albrecht, Sebastian Pancratz, Fredrik Johansson, Jeroen Demeyer and Leif Lionhardy, amongst others. Some code (notably \code{longlong.h} and \code{clz_tab.c}) has been used from the GMP library, whose main author is Torbjorn Granlund. FLINT 2 was a complete rewrite from scratch which began in about 2010. \chapter{Tuning FLINT} FLINT uses a highly optimised Fast Fourier Transform routine for polynomial multiplication and some integer multiplication routines. This can be tuned by first typing \code{make tune} and then running the program \code{build/fft/tune/tune_fft}. The output of the program can be pasted into \code{fft_tuning64.in} or \code{fft_tuning32.in} depending on the ABI of the current platform. FLINT must then be configured again and a clean build initiated. Tuning is only necessary if you suspect that very large polynomial and integer operations (millions of bits) are taking longer than they should. \chapter{Example programs} FLINT comes with example programs to demonstrate current and future FLINT features. To build the example programs, type: \begin{lstlisting}[language=bash] make examples \end{lstlisting} The example programs are built in the \code{build/examples} directory. You must set your \code{LD_LIBRARY_PATH} or equivalent for the flint, mpir and mpfr libraries. See your operating system documentation to see how to set this. The current example programs are: \code{partitions} Demonstrates the partition counting code, e.g.\\ \code{build/examples/partitions 1000000000} will compute the number of partitions of \code{10^9}. \code{delta_qexp} Computes the $n$-th term of the delta function, e.g.\\ \code{build/examples/delta_qexp 1000000} will compute the one million-th term of the $q$-expansion of delta. \code{crt} Demonstrates the integer Chinese Remainder code, e.g.\ \code{build/examples/crt 10382788} will build up the given integer from its value mod various primes. \code{multi_crt} Demonstrates the fast tree version of the integer Chinese Remainder code, e.g.\ \code{build/examples/multi_crt 100493287498239 13} will build up the given integer from its value mod the given number of primes. \code{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 \code{build/examples/stirling_matrix 10} does this with 10 by 10 matrices. \code{fmpz_poly_factor_zassenhaus} Demonstrates the factorisation of a small polynomial. A larger polynomials 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. \code{padic} Gives examples of the usage of many functions in the padic module. \code{fmpz_poly_q} Gives a very simple example of the \code{fmpz_poly_q} module. \code{fmpz_poly} Gives a very simple example of the \code{fmpz_poly} module. \code{fmpq_poly} Gives a very simple example of the \code{fmpq_poly} module. Some of the example programs have associated C$++$ versions. \chapter{FLINT macros} The file \code{flint.h} contains various useful macros. The macro constant \code{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 \code{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 \code{FLINT_D_BITS} bits, hence the macro. The macro \code{FLINT_ABS(x)} returns the absolute value of \code{x} for primitive signed numerical types. It might fail for least negative values such as \code{INT_MIN} and \code{WORD_MIN}. The macro \code{FLINT_MIN(x, y)} returns the minimum of \code{x} and \code{y} for primitive signed or unsigned numerical types. This macro is only safe to use when \code{x} and \code{y} are of the same type, to avoid problems with integer promotion. Similar to the previous macro, \code{FLINT_MAX(x, y)} returns the maximum of \code{x} and \code{y}. The function \code{FLINT_BIT_COUNT(x)} returns the number of binary bits required to represent an \code{ulong x}. If \code{x} is zero, returns~$0$. Derived from this there are the two macros \code{FLINT_FLOG2(x)} and \code{FLINT_CLOG2(x)} which, for any $x \geq 1$, compute $\floor{\log_2{x}}$ and $\ceil{\log_2{x}}$. To determine the current FLINT version a number of macros are available. For example, if the current FLINT version is \code{2.4.0} then \code{__FLINT_VERSION} will have the value $2$, \code{__FLINT_MINOR} will have the value $4$ and \code{__FLINT_PATCHLEVEL} will have the value $0$. The \code{__FLINT_RELEASE} macro will have the value $20400$. The \code{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. \chapter{Memory management} The file \code{flint.h} defines functions \code{flint_malloc}, \code{flint_realloc}, \code{flint_calloc} and \code{flint_free}. They have the same interface as the standard library functions, but may perform additional error checking. 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, cached data is kept in thread-local storage by default (unless configured otherwise). Cached data can be freed by calling the \code{flint_cleanup()} function. It is recommended to call \code{flint_cleanup()} right before exiting a thread, and at the end of the main program. The user can register additional cleanup functions to be invoked by \code{flint_cleanup()} by passing a pointer to a function with signature \code{void cleanup_function(void)} to \code{flint_register_cleanup_function()}. Flint also makes use of \code{malloc}, \code{realloc}, \code{calloc} and \code{free} by default to allocate memory internally. The user is able to override this behaviour by calling \code{__flint_set_memory_functions} passing the \code{malloc}, \code{realloc}, \code{calloc} and \code{free} function pointers as parameters (see \code{flint.h} for the exact prototype). \chapter{Temporary allocation} FLINT allows for temporary allocation of memory using \code{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. \begin{lstlisting}[language=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 */ } \end{lstlisting} It is very important to note that temporary allocations should not be made in recursive functions, as many small allocations on the stack can exhaust the stack causing a stack overflow. \chapter{Platform-safe types, format specifiers and constants} For platform independence, FLINT provides two types \code{ulong} and \code{slong} to replace \code{unsigned long} and \code{long} respectively. These are guaranteed to be the same size as GMP's \code{mp_limb_t} and \code{mp_limb_signed_t} types, respectively. A full list of types provided by FLINT is available in \code{code_conventions.txt} in the top-level source tree. As FLINT supports Windows 64 on which the FLINT \code{ulong} and \code{slong} types are 64 bits, whilst \code{unsigned long} and \code{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 \code{"%lu"} and \code{"%ld"}. For this purpose FLINT provides its own I/O functions, \code{flint_printf}, \code{flint_fprintf}, \code{flint_sprintf}, \code{flint_scanf}, \code{flint_fscanf} and \code{flint_sscanf}, which work exactly as the usual system versions, but which take the \code{"%wu"} and \code{"%wd"} format specifiers, which support FLINT \code{ulong} and \code{slong} types respectively. Also, instead of using constants \code{123UL} and \code{123L}, FLINT provides the macros \code{UWORD(123)} and \code{WORD(123)} respectively for constants of type \code{ulong} and \code{slong} respectively. The maximum and minimum values that can be represented by these types are given by \code{UWORD_MAX} and \code{WORD_MAX} respectively. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Integers % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpz : Arbitrary precision integers} \epigraph{Arbitrary precision integers}{} \section{Introduction} By default, an \code{fmpz_t} is implemented as an array of \code{fmpz}'s of length one to allow passing by reference as one can do with GMP/ MPIR's \code{mpz_t} type. The \code{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, \code{fmpz_t}'s act precisely like GMP/ MPIR's \code{mpz_t}'s, with automatic memory management, however, in the first place only one limb is used to implement them. Once an \code{fmpz_t} overflows a limb then a multiprecision integer is automatically allocated and instead of storing the actual integer data the \code{slong} which implements the type becomes an index into a FLINT wide array of \code{mpz_t}'s. These internal implementation details are not important for the user to understand, except for three important things. Firstly, \code{fmpz_t}'s will be more efficient than \code{mpz_t}'s for single limb operations, or more precisely for signed quantities whose absolute value does not exceed \code{FLINT_BITS - 2} bits. Secondly, for small integers that fit into \code{FLINT_BITS - 2} bits much less memory will be used than for an \code{mpz_t}. When very many \code{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 \code{fmpz_t}'s. As for \code{mpz_t}'s, there is an underlying type, an \code{fmpz}, which can be used to create the array, e.g.\ \begin{lstlisting} fmpz myarr[100]; \end{lstlisting} Now recall that an \code{fmpz_t} is an array of length one of \code{fmpz}'s. Thus, a pointer to an \code{fmpz} can be used in place of an \code{fmpz_t}. For example, to find the sign of the third integer in our array we would write \begin{lstlisting} int sign = fmpz_sgn(myarr + 2); \end{lstlisting} The \code{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. \section{Simple example} The following example computes the square of the integer $7$ and prints the result. \begin{lstlisting}[language=c] #include "fmpz.h" ... 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); \end{lstlisting} The output is: \begin{lstlisting} 7^2 = 49 \end{lstlisting} We now describe the functions available in the \code{fmpz} module. \input{input/fmpz.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Integer vectors % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpz\_vec: Vectors over arbitrary precision integers} \epigraph{Vectors over $\Z$}{} \input{input/fmpz_vec.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Integer factorisation % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpz\_factor: Factorisation of arbitrary precision integers} \epigraph{Factorisation in $\Z$}{} The \code{fmpz_factor} module is included automatically with \code{fmpz.h}. One should not try to include \code{fmpz_factor.h} directly. \input{input/fmpz_factor.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Integer matrices % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpz\_mat: Matrices over arbitrary precision integers} \epigraph{Matrices over $\Z$}{} \section{Introduction} The \code{fmpz_mat_t} data type represents dense matrices of multiprecision integers, implemented using \code{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 \emph{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 \code{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 \code{fmpz_t} variable to any function in the \code{fmpz} module for direct manipulation. \section{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. \begin{lstlisting}[language=c] #include "fmpz.h" #include "fmpz_mat.h" ... 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); \end{lstlisting} The output is: \begin{lstlisting} A = [[0 1] [2 3]] A^2 = [[2 3] [6 11]] \end{lstlisting} \input{input/fmpz_mat.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Integer polynomials % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpz\_poly: Polynomials over arbitrary precision integers} \epigraph{Polynomials over $\Z$}{} \section{Introduction} The \code{fmpz_poly_t} data type represents elements of $\Z[x]$. The \code{fmpz_poly} module provides routines for memory management, basic arithmetic, and conversions from or to other types. Each coefficient of an \code{fmpz_poly_t} is an integer of the FLINT \code{fmpz_t} type. There are two advantages of this model. Firstly, the \code{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 \code{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. \section{Simple example} The following example computes the square of the polynomial $5x^3 - 1$. \begin{lstlisting}[language=c] #include "fmpz_poly.h" ... 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); \end{lstlisting} The output is: \begin{lstlisting} 4 -1 0 0 5 7 1 0 0 -10 0 0 25 \end{lstlisting} \section{Definition of the fmpz\_poly\_t type} The \code{fmpz_poly_t} type is a typedef for an array of length~1 of \code{fmpz_poly_struct}'s. This permits passing parameters of type \code{fmpz_poly_t} by reference in a manner similar to the way GMP integers of type \code{mpz_t} can be passed by reference. In reality one never deals directly with the \code{struct} and simply deals with objects of type \code{fmpz_poly_t}. For simplicity we will think of an \code{fmpz_poly_t} as a \code{struct}, though in practice to access fields of this \code{struct}, one needs to dereference first, e.g.\ to access the \code{length} field of an \code{fmpz_poly_t} called \code{poly1} one writes \code{poly1->length}. An \code{fmpz_poly_t} is said to be \emph{normalised} if either \code{length} is zero, or if the leading coefficient of the polynomial is non-zero. All \code{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 \code{fmpz_poly_t} or its coefficient data directly, but make use of the functions designed for this purpose, detailed below. Functions in \code{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. We now describe the functions available in \code{fmpz_poly}. \input{input/fmpz_poly.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Integer polynomial factorisation % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpz\_poly\_factor: Polynomial factorisation over $\Z$} \epigraph{Factorisation of polynomials over $\Z$}{} \input{input/fmpz_poly_factor.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Multivariate integer polynomials %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpz\_mpoly: Multivariate polynomials over arbitrary precision integers} \epigraph{Multivariate polynomials over $\Z$}{} \input{input/fmpz_mpoly.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Rational numbers % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpq: Arbitrary precision rationals} \epigraph{Arbitrary-precision rational numbers}{} \section{Introduction} The \code{fmpq_t} data type represents rational numbers as fractions of multiprecision integers. An \code{fmpq_t} is an array of length 1 of type \code{fmpq}, with \code{fmpq} being implemented as a pair of \code{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 \code{fmpq_t} arithmetic is roughly the same as that of \code{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 \code{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 \code{fmpq_t} as arbitrary integers, but then becomes responsible for canonicalising the number (for example by calling \code{fmpq_canonicalise}) before passing it to any library function. For most operations, both a function operating on \code{fmpq_t}'s and an underscore version operating on \code{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. \input{input/fmpq.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Rational matrices % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpq\_mat: Matrices over the rationals} \epigraph{Matrices over $\Q$}{} \section{Introduction} The \code{fmpq_mat_t} data type represents matrices over $\Q$. A rational matrix is stored as an array of \code{fmpq} elements in order to allow convenient and efficient manipulation of individual entries. In general, \code{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 \code{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. \input{input/fmpq_mat.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Rational polynomials % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpq\_poly: Polynomials over the rationals} \epigraph{Polynomials over $\Q$}{} \section{Introduction} The \code{fmpq_poly_t} data type represents elements of $\Q[x]$. The \code{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 \code{fmpq_poly_numref()} and the denominator with \code{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 \code{fmpz_poly_t} case, an \code{fmpq_poly_t} object also has a \code{length} parameter, which denotes the length of the vector of coefficients of the numerator. We say a polynomial is \emph{normalised} either if this length is zero or if the leading coefficient is non-zero. We say a polynomial is in \emph{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 \code{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 \code{fmpz *}, \code{fmpz_t}, and \code{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. \input{input/fmpq_poly.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Rational functions % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpz\_poly\_q: Rational functions} \epigraph{Rational functions over $\Q$}{} \section{Introduction} The module \code{fmpz_poly_q} provides functions for performing arithmetic on rational functions in $\mathbf{Q}(t)$, represented as quotients of integer polynomials of type \code{fmpz_poly_t}. These functions start with the prefix \code{fmpz_poly_q_}. Rational functions are stored in objects of type \code{fmpz_poly_q_t}, which is an array of \code{fmpz_poly_q_struct}'s of length one. This permits passing parameters of type \code{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 \code{fmpz_poly_q_numref()} and \code{fmpz_poly_q_denref()}, it is the user's responsibility to canonicalise the rational function using the function \code{fmpz_poly_q_canonicalise()} if necessary. All methods support aliasing of their inputs and outputs \emph{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~\citep{Hen1956}. Differentiation is implemented in a way slightly improving on the algorithm described in~\citep{Hor1972}. \section{Simple example} The following example computes the product of two rational functions and prints the result: \begin{lstlisting}[language=c] #include "fmpz_poly_q.h" ... 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); \end{lstlisting} The output is: \begin{lstlisting}[language=c] (3*t+1)/2 * 3/(7*t+2) = (9*t+3)/(14*t+4) \end{lstlisting} \input{input/fmpz_poly_q.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Multivariate integer polynomials %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpq\_mpoly: Multivariate polynomials over the rationals} \epigraph{Multivariate polynomials over $\Q$}{} \input{input/fmpq_mpoly.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Matrices over integer polynomials % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpz\_poly\_mat: Polynomial matrices over $\Z$} \epigraph{Matrices over $\mathbf{Z}[x]$}{} The \code{fmpz_poly_mat_t} data type represents matrices whose entries are integer polynomials. The \code{fmpz_poly_mat_t} type is defined as an array of \code{fmpz_poly_mat_struct}'s of length one. This permits passing parameters of type \code{fmpz_poly_mat_t} by reference. An integer polynomial matrix internally consists of a single array of \code{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. \section{Simple example} The following example constructs the matrix $\begin{pmatrix} 2x+1 & x \\ 1-x & -1 \end{pmatrix}$ and computes its determinant. \begin{lstlisting}[language=c] #include "fmpz_poly.h" #include "fmpz_poly_mat.h" ... 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); \end{lstlisting} The output is: \begin{lstlisting}[language=c] x^2-3*x-1 \end{lstlisting} \input{input/fmpz_poly_mat.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Vectors over Z / nZ for word-sized moduli % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{nmod\_vec: Vectors over $\Z/n\Z$ (small $n$)} \epigraph{Vectors over $\Z / n \Z$ for word-sized moduli}{} \input{input/nmod_vec.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Polynomials over Z / nZ for word-sized moduli % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{nmod\_poly: Polynomials over $\Z/n\Z$ (small $n$)} \epigraph{Polynomials over $\Z / n \Z$ for word-sized moduli}{} \section{Introduction} The \code{nmod_poly_t} data type represents elements of $\Z/n\Z[x]$ for a fixed modulus $n$. The \code{nmod_poly} module provides routines for memory management, basic arithmetic and some higher level functions such as GCD, etc. Each coefficient of an \code{nmod_poly_t} is of type \code{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. \section{Simple example} The following example computes the square of the polynomial $5x^3 + 6$ in $\Z/7\Z[x]$. \begin{lstlisting}[language=c] #include "nmod_poly.h" ... 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); \end{lstlisting} The output is: \begin{lstlisting} 4 7 6 0 0 5 7 7 1 0 0 4 0 0 4 \end{lstlisting} \section{Definition of the nmod\_poly\_t type} The \code{nmod_poly_t} type is a typedef for an array of length~1 of \code{nmod_poly_struct}'s. This permits passing parameters of type \code{nmod_poly_t} by reference. In reality one never deals directly with the \code{struct} and simply deals with objects of type \code{nmod_poly_t}. For simplicity we will think of an \code{nmod_poly_t} as a \code{struct}, though in practice to access fields of this \code{struct}, one needs to dereference first, e.g.\ to access the \code{length} field of an \code{nmod_poly_t} called \code{poly1} one writes \code{poly1->length}. An \code{nmod_poly_t} is said to be \emph{normalised} if either \code{length} is zero, or if the leading coefficient of the polynomial is non-zero. All \code{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 \code{nmod_poly_t} or its coefficient data directly, but make use of the functions designed for this purpose, detailed below. Functions in \code{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. We now describe the functions available in \code{nmod_poly}. \input{input/nmod_poly.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Factorisation of polynomials over Z / nZ for word-sized moduli % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{nmod\_poly\_factor: Polynomial factorisation over $\Z/n\Z$ (small $n$)} \epigraph{Factorisation of polynomials over $\Z / n \Z$ for word-sized moduli}{} The \code{nmod_poly_factor} module is included automatically with \code{nmod_poly.h}. One should not try to include \code{nmod_poly_factor.h} directly. \input{input/nmod_poly_factor.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Matrices over Z / nZ for word-sized moduli % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{nmod\_mat: Matrices over $\Z/n\Z$ (small $n$)} \epigraph{Matrices over $\Z / n \Z$ for word-sized moduli}{} \section{Introduction} An \code{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 \code{nmod_mat_t} type is defined as an array of \code{nmod_mat_struct}'s of length one. This permits passing parameters of type \code{nmod_mat_t} by reference. An \code{nmod_mat_t} internally consists of a single array of \code{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)$. \input{input/nmod_mat.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Matrices over integer polynomials mod n % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{nmod\_poly\_mat: Polynomial matrices over $\Z/n\Z$ (small $n$)} \epigraph{Matrices over $\Z / n \Z[x]$ for word-sized moduli}{} The \code{nmod_poly_mat_t} data type represents matrices whose entries are polynomials having coefficients in $\Z / n \Z$. We generally assume that $n$ is a prime number. The \code{nmod_poly_mat_t} type is defined as an array of \code{nmod_poly_mat_struct}'s of length one. This permits passing parameters of type \code{nmod_poly_mat_t} by reference. A matrix internally consists of a single array of \code{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. \input{input/nmod_poly_mat.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Polynomials over Z/nZ for general moduli % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpz\_mod\_poly: Polynomials over $\Z/n\Z$} \epigraph{Polynomials over $\Z / n \Z$ for general moduli}{} \section{Introduction} The \code{fmpz_mod_poly_t} data type represents elements of $\Z/n\Z[x]$ for a fixed modulus $n$. The \code{fmpz_mod_poly} module provides routines for memory management, basic arithmetic and some higher level functions such as GCD, etc. Each coefficient of an \code{fmpz_mod_poly_t} is of type \code{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. \section{Simple example} The following example computes the square of the polynomial $5x^3 + 6$ in $\Z/7\Z[x]$. \begin{lstlisting}[language=c] #include "fmpz_mod_poly.h" ... 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); \end{lstlisting} The output is: \begin{lstlisting} 4 7 6 0 0 5 7 7 1 0 0 4 0 0 4 \end{lstlisting} \section{Definition of the fmpz\_mod\_poly\_t type} The \code{fmpz_mod_poly_t} type is a typedef for an array of length~1 of\\ \code{fmpz_mod_poly_struct}'s. This permits passing parameters of type \code{fmpz_mod_poly_t} by reference. In reality one never deals directly with the \code{struct} and simply deals with objects of type \code{fmpz_mod_poly_t}. For simplicity we will think of an \code{fmpz_mod_poly_t} as a \code{struct}, though in practice to access fields of this \code{struct}, one needs to dereference first, e.g.\ to access the \code{length} field of an \code{fmpz_mod_poly_t} called \code{poly1} one writes \code{poly1->length}. An \code{fmpz_mod_poly_t} is said to be \emph{normalised} if either \code{length} is zero, or if the leading coefficient of the polynomial is non-zero. All \code{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$. It is recommended that users do not access the fields of an \code{fmpz_mod_poly_t} or its coefficient data directly, but make use of the functions designed for this purpose, detailed below. Functions in \code{fmpz_mod_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. We now describe the functions available in \code{fmpz_mod_poly}. \input{input/fmpz_mod_poly.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Polynomial factorisation over Z/nZ % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fmpz\_mod\_poly\_factor: Polynomial factorisation over $\Z/n\Z$} \epigraph{Factorisation of polynomials over $\Z/n\Z$ for general moduli}{} The \code{fmpz_mod_poly_factor} module is included automatically when one includes \code{fmpz_mod_poly.h}. One should not try to include \code{fmpz_mod_poly_factor.h} directly. \input{input/fmpz_mod_poly_factor.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Finite Fields (fq) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq: Finite fields} \epigraph{Finite fields of arbitrary 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 \code{fmpz_poly_t}. The default choice for $f(X)$ is the Conway polynomial for the pair $(p,n)$. Frank Luebeck's data base of Conway polynomials is made available in the file \code{qadic/CPimport.txt}. 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)$. \input{input/fq.tex} \input{input/fq_embed.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_vec % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_vec: Vectors over finite fields} \epigraph{Vectors over finite fields of arbitrary characteristic} \input{input/fq_vec.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_mat % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_mat: Matrices over finite fields} \epigraph{Matrices over finite fields of arbitrary characteristic} \input{input/fq_mat.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_poly % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_poly: Polynomials over finite fields} \epigraph{polynomials over finite fields of arbitrary characteristic} We represent a polynomial in $\mathbf{F}_q[X]$ as a \code{struct} which includes an array \code{coeffs} with the coefficients, as well as the length \code{length} and the number \code{alloc} of coefficients for which memory has been allocated. As a data structure, we call this polynomial \emph{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. \input{input/fq_poly.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_poly_factor % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_poly\_factor: Polynomial factorisation over finite fields} \epigraph{Factorisation of polynomials over finite fields of arbitrary characteristic} The \code{fq_poly_factor} module is included automatically when one includes \code{fq_poly.h}. One should not try to include \code{fq_poly_factor.h} directly. \input{input/fq_poly_factor.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_nmod % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_nmod: Finite fields (small representation)} \epigraph{Finite fields of word-sized 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 \code{nmod_poly_t}. The default choice for $f(X)$ is the Conway polynomial for the pair $(p,n)$. Frank Luebeck's data base of Conway polynomials is made available in the file \code{qadic/CPimport.txt}. 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)$. \input{input/fq_nmod.tex} \input{input/fq_nmod_embed.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_nmod_vec % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_nmod\_vec: Vectors over finite fields (small representation)} \epigraph{Vectors over finite fields of word-sized characteristic} \input{input/fq_nmod_vec.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_nmod_mat % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_nmod\_mat: Matrices over finite fields (small representation)} \epigraph{Matrices over finite fields of word-sized characteristic} \input{input/fq_nmod_mat.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_nmod_poly % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_nmod\_poly: Polynomials over finite fields (small representation)} \epigraph{polynomials over finite fields of word-sized characteristic} We represent a polynomial in $\mathbf{F}_q[X]$ as a \code{struct} which includes an array \code{coeffs} with the coefficients, as well as the length \code{length} and the number \code{alloc} of coefficients for which memory has been allocated. As a data structure, we call this polynomial \emph{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. \input{input/fq_nmod_poly.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_nmod_poly_factor % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_nmod\_poly\_factor: Polynomial factorisation over finite fields (small representation)} \epigraph{Factorisation of polynomials over finite fields of word-sized characteristic} The \code{fq_nmod_poly_factor} module is included automatically when one includes \code{fq_nmod_poly.h}. One should not try to include \code{fq_nmod_poly_factor.h} directly. \input{input/fq_nmod_poly_factor.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_zech % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_zech: Finite fields (Zech representation)} \epigraph{Finite fields in 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 \code{mp_limb_t}. The default choice for $f(X)$ is the Conway polynomial for the pair $(p,n)$. Frank Luebeck's data base of Conway polynomials is made available in the file \code{qadic/CPimport.txt}. 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 \code{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. \input{input/fq_zech.tex} \input{input/fq_zech_embed.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_zech_vec % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_zech\_vec: Vectors over finite fields (Zech representation)} \epigraph{Vectors over finite fields in Zech logarithm representation} \input{input/fq_zech_vec.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_zech_mat % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_zech\_mat: Matrices over finite fields (Zech representation)} \epigraph{Matrices over finite fields in Zech logarithm representation} \input{input/fq_zech_mat.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_zech_poly % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_zech\_poly: Polynomials over finite fields (Zech representation)} \epigraph{Polynomials over finite fields in Zech logarithm representation} We represent a polynomial in $\mathbf{F}_q[X]$ as a \code{struct} which includes an array \code{coeffs} with the coefficients, as well as the length \code{length} and the number \code{alloc} of coefficients for which memory has been allocated. As a data structure, we call this polynomial \emph{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. \input{input/fq_zech_poly.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % fq_zech_poly_factor % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fq\_zech\_poly\_factor: Polynomial factorisation over finite fields (Zech representation)} \epigraph{Factorisation of polynomials over finite fields in Zech logarithm representation} The \code{fq_zech_poly_factor} module is included automatically when one includes \code{fq_zech_poly.h}. One should not try to include \code{fq_zech_poly_factor.h} directly. \input{input/fq_zech_poly_factor.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Padic numbers % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{padic: $p$-adic numbers ($\Q_p$)} \epigraph{$p$-Adic numbers in $\mathbf{Q}_p$}{} \section{Introduction} The \code{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 \emph{canonical form} whenever either $p \nmid u$ or $u = v = 0$, and we say it is \emph{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 \code{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. \input{input/padic.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Matrices of padic numbers % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{padic\_mat: Matrices over $\Q_p$} \input{input/padic_mat.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Polynomials of padic numbers % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{padic\_poly: Polynomials over $\Q_p$} \input{input/padic_poly.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Finite unramified extensions of the padic numbers % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{qadic: Unramified extensions of $\Q_p$} \input{input/qadic.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % APRCL primality test % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{aprcl: Primality test for \texttt{fmpz}} \epigraph{APR-CL primality test}{} \section{Introduction} This module provides the APR-CL primality test implementation for \code{fmpz_t} numbers. The APR-CL test uses the Jacobi sums that belong $\mathbb{Z}[\zeta]/(n)$, so we have \code{unity_zp} struct and some useful operations. \code{unity_zp} is just a wrapper over \code{fmpz_mod_poly} with aditional 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 \code{unity_zpq} struct. We now describe the functions available in the \code{aprcl} module. \input{input/aprcl.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Arithmetic functions % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{arith: Arithmetic functions} \epigraph{Arithmetic functions}{} \section{Introduction} This module implements arithmetic functions, number-theoretic and combinatorial special number sequences and polynomials. \input{input/arith.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Unsigned single limb arithmetic % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{ulong\_extras: Arithmetic for single word unsigned integers} \epigraph{Unsigned single limb arithmetic}{} \section{Introduction} 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 \code{mp_limb_t} as defined by MPIR. Functions which take a precomputed inverse either have the suffix \code{preinv} and take an \code{mp_limb_t} precomputed inverse as computed by \code{n_preinvert_limb} or have the suffix \code{_precomp} and accept a \code{double} precomputed inverse as computed by \code{n_precompute_inverse}. Sometimes three functions with similar names are provided for the same task, e.g. \code{n_mod_precomp}, \code{n_mod2_precomp} and \code{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 \code{n_blah2_preinv} variants. Some functions with the \code{n_ll_} or \code{n_lll_} prefix accept parameters of two or three limbs respectively. \section{Simple example} The following example computes $ab \pmod{n}$ using a precomputed inverse, where $a = 12345678, b = 87654321$ and $n = 111111111$. \begin{lstlisting}[language=c] #include #include "ulong_extras.h" ... 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); \end{lstlisting} The output is: \begin{lstlisting}[language=c] 12345678*87654321 mod 111111111 is 23456790 \end{lstlisting} \input{input/ulong_extras.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Signed single limb arithmetic % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{long\_extras: Arithmetic for single word signed integers} \epigraph{Signed single limb arithmetic}{} \input{input/long_extras.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Fast Fourier Transforms % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{fft: Fast Fourier Transform (integer and polynomial multiplication)} \epigraph{Fast Fourier Transforms}{} \input{input/fft.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Quadratic Sieve % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{qsieve: Quadratic sieve for integer factorisation} \epigraph{Quadratic sieve}{} \input{input/qsieve.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Permutations % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{perm: Permutations} \epigraph{Permutations}{} \input{input/perm.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % longlong.h % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{longlong.h: Assembly macros for wide integer arithmetic} \epigraph{$64$-bit arithmetic} \input{input/longlong.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % mpn_extras % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{mpn\_extras: Extra function for the GMP mpn layer} \input{input/mpn_extras.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % C++ wrapper % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{flintxx: C++ wrapper} \epigraph{C++ wrapper library for FLINT} \section{Introduction} FLINT provides fast algorithms for number theoretic computations. For many reasons, it is written in C. Nonetheless, some users prefer object oriented syntax. FLINT ships with a set of wrapper C++ classes, together termed flintxx, which provide such an object oriented syntax. In this chapter, we describe how to \emph{use} flintxx. The FLINT developer wishing to extend the wrapper library should consult appendix~\ref{app:genericxx}. In general, flintxx strives to behave just like the underlying FLINT C interface, except that we use classes and C++ operators to make the client code look more pleasant. The simple example from the section on \code{fmpz} can be transcribed into C++ as follows: \begin{lstlisting}[language=c++] #include "fmpzxx.h" ... using namespace flint; fmpzxx x, y; x = 7u; y = x*x; std::cout << x << "^2 = " << y << std::endl; \end{lstlisting} As can be seen here, and in general, if a FLINT C interface is called \code{foo} and resides in \code{foo.h}, then the C++ version is called \code{fooxx} and resides in \code{fooxx.h}. All flintxx classes live inside \code{namespace flint}. Functions which operate on wrapper classes are usually implemented as overloaded stand-alone functions, with the type prefix dropped. So for example a call to \code{flint::gcd(f1, f2)} yields an expression template evaluating via \code{fmpz_gcd}, provided \code{f1} and \code{f2} are (evaluate to) instances of \code{fmpzxx}. Sometimes we felt that dropping the type prefix would yield incomprehensible names, as for example in \code{fmpq_next_minimal}, or \code{fmpq_reconstruct}. In these cases the type prefix is swapped for the flintxx equivalent, so the flintxx version would be called \code{fmpqxx_reconstruct}. In this situation, usually the same functionality is also exposed as a (possibly static) member function, and this is the preferred way of accessing the functionality. Thus one should write \code{fmpqxx::reconstruct(a, m)} or \code{fmpqxx(0, 1u).next_minimal()}. \section{Overview} \paragraph{Expression templates} The implementation of flintxx tries very hard not to incur any overhead over using the native C interface. For this reason, we use \emph{expression templates} for lazily evaluating expressions. This allows us to avoid creating excessively many temporaries, for example. This means that even if \code{x} and \code{y} are of type \code{fmpzxx} (say), then \code{x + y} will \emph{not} be of type \code{fmpzxx}. Instead it will be an object which for most purposes behaves just like \code{fmpzxx}, but really only expresses the fact that it represents the sum of \code{x} and \code{y}. This distinction almost never matters, since expression templates are evaluated automatically in most cases. Thus \code{cout << x + y} or \code{x + y == 7} will work just as one might expect. There are ways to request explicit evaluation of an expression template, most notably \code{(x + y).evaluate()} and \code{fmpzxx(x + y)}. One caveat of the expression template approach is that compiler error messages can be long and hard to understand. In flintxx we strive to type-check template parameters as early as possible in order to keep error messages short and close to the actual user error. Excessively long error messages are often indicative of a bug in flintxx. %TODO static assert \paragraph{Tuples} Many FLINT functions naturally return two (or more) arguments. A typical example is \code{divrem}. The underlying C function is (for example)\\ \code{void fmpz_poly_divrem(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B)}. Mapping this directly to C++ would yield something like\\ \code{void divrem(fmpz_polyxx& Q, fmpz_polyxx& R, const fmpz_polyxx& A, const fmpz_polyxx& B)}. While functional, this is not particularly nice; the syntax \code{divrem(Q, R, A, B)}, where the first two arguments are modified, is just very reminiscent of C. We would prefer an expression closer to the python analogue \code{(Q, R) = divrem(A, B)}. This is where \emph{ltuples} enter.\footnote{The `l' in \code{ltuple} stands for ``lazy'', i.e. the fact that they can be used in expression templates. The reason for this name is that flintxx internally uses a non-lazy tuple class just called \code{tuple}, on which \code{ltuple} in fact is built.} In fact, the following is a valid flintxx expression:\\ \code{ltupleref(Q, R) = divrem(A, B)}. In generality, the implementation of ltuples is fairly involved template metaprogramming. For the purpose of this documentation, ltuple types are denoted as follows:\\ \code{Ltuple}. So \code{divrem} would return an object of type\\ \code{Ltuple}. The user should never try to construct such types by hand; instead use the function \code{ltupleref} (and perhaps occasionally \code{ltuple}; both documented later). One thing to observe is that ltuples are typed fairly weakly. Thus assignments and equality comparisons can be performed as long as both sides have the same length, and the operation can be performed on all components (whether or not the component types match). Another interesting feature of ltuples is the type \code{flint::detail::IGNORED_TYPE}. In an ltuple assignment, where the left hand side contains a reference to this type, the relevant entry is just discarded. Since the \code{ltuple.h} header automatically creates a static instance \code{_} of this type, in the following listing, the lines marked \code{(1)} and \code{(2)} have the same effect (but the second is potentially more efficient). \begin{lstlisting}[language=c++] #include "fmpz_polyxx.h" ... using namespace flint; fmpz_polyxx f, g; // ... fmpz_polyxx R; ltupleref(_, R) = divrem(f, g); // (1) R = f % g; // (2) \end{lstlisting} Note finally that using \code{ltuple} intermediates often results in more copies than necessary. For example the expression \code{ltupleref(num, _) = divrem(a, b)} assigns the quotient to \code{num}, creating just a temporary \code{fmpzxx} to hold the remainder. In contrast, \code{num = divrem(a, b).get<0>()} creates two temporary instances of \code{fmpzxx}. \paragraph{Reference types} One subtlety in wrapping a C library is that references do not work as easily as one might expect. For example, consider the class \code{fmpqxx}, wrapping \code{fmpq_t}, i.e. rational numbers. As such, an instance of \code{fmpqxx} has a numerator and denominator. In C, these are accessible via macros \code{fmpq_numref} and \code{fmpq_denref}, which yield \code{fmpz*}, which can be used essentially interchangeably with \code{fmpz_t}. In particular, any library function which operates on \code{fmpz_t} can operate on the numerator or denominator of an \code{fmpq_t}. In C++, we would like to have a member function \code{den} (and \code{num}) which returns an object of type \code{fmpzxx&} (i.e. a reference to \code{fmpzxx}). However, this is not possible, since \code{fmpqxx} is \emph{not} implemented as a pair of \code{fmpzxx}, and instead simply contains an \code{fmpq_t}. For this reason, for every C interface \code{foo}, flintxx provides two additional types, called \code{fooxx_ref} and \code{fooxx_srcref}, acting as replacements for \code{fooxx&} and \code{const foox&}, respectively, in situations where no underlying C++ object exists. Instances of \code{fooxx_ref} or \code{fooxx_srcref} behave exactly like instances \code{fooxx}, in fact the user should never notice a difference. Any flintxx operation or expression which works on objects of type \code{foo} also works on objects of type \code{fooxx_ref} and \code{fooxx_srcref}. Moreover, instances of \code{foo} can be converted implicitly to \code{fooxx_ref} or \code{fooxx_srcref}, and \code{fooxx_ref} can be converted implicitly to \code{fooxx_srcref}. It is also possible to explicitly convert reference types \code{fooxx_*ref} to \code{fooxx} (since this entails copying, we provide no implicit conversion). In summary, the class \code{fooxx_ref} behaves like a reference to an object of type \code{fooxx}. As such it can be used both as a right hand side and as a left hand side, just like \code{fooxx}. The class \code{fooxx_srcref} behaves like a reference to a constant object of type \code{fooxx}, and so cannot be used as a left hand side. These objects are created by flintxx automatically, for example upon calling \code{fmpqxx::num()}. \paragraph{Unified coefficient access} Consider again the \code{x.num()} method of \code{fmpqxx}. In various situations, this can have different return types. Namely, if \code{x} is a writable expression, then \code{x.num()} returns an \code{fmpzxx_ref}. In particular the return value behaves just like \code{fmpzxx}, no evaluation is necessary to obtain it, there are no copies, and it is possible to change the return value (and thus change \code{x}). If on the other hand \code{x} is a readonly immediate, then the return value of \code{x.num()} has type \code{fmpzxx_srcref}. This again behaves just like \code{fmpzxx} and no evaluations or copies are necessary, but this time it is not possible to change the return value (and so it is not possible to change \code{x}, either). Finally, if \code{x} is a lazy expression, then the return value is actually a lazy expression template. Thus to obtain the ``actual'' value of \code{x.num()}, evaluations are necessary, and potentially so are copies. Thus in any case the return value behaves just like \code{fmpqxx}, but apart from that the behaviour of \code{x.num()} varies quite drastically in the different situations. We call this ``unified coefficient access'' (the coefficients of a \code{fmpqxx} being \code{num(), den()}), and the same behaviour occurs in many other flintxx types, e.g. in \code{fmpz_polyxx.coeff()}, etc. \paragraph{Type conversion} As a rule, flintxx does not perform automatic type conversions (except when related to the promotion to reference types, c/f earlier discussion). In expression templates, operands can be automatically promoted if the underlying C interface provides this facility. Beyond that, types have to be converted explicitly. There are two ways of doing this. The preferred one is using static constructor functions. Typical examples are \code{fmpz_polyxx::from_ground(fmpzarg)} and\\ \code{nmod_polyxx::reduce(mplimbarg, nmodctxarg)}. The former takes an (expression template evaluating to) \code{fmpzxx} and returns an \code{fmpz_polyxx} representing the constant polynomial with value the \code{fmpzxx}. The latter takes an argument of type \code{mp_limb_t} and one of type \code{nmodxx_ctx_srcref} (essentially a word-sized modulus) and returns an \code{nmod_polyxx} representing the constant polynomial obtained by reducing \code{mplimbarg}. The general format for this is \code{totype::constructorname(arg1, arg2, ...)}. We prefer this because it makes explicit the type that is being converted to, and the way the arguments are to be interpreted. %In comparison, \code{fmpzarg.reduce(ctx)} %does not make it clear if the reduction should be to \code{nmodxx}, %\code{nmod_polyxx} or perhaps \code{fmpz_mod_polyxx}. This format only works if the target type is part of flintxx. In other cases, we use a \code{.to()} syntax, as in \code{fmpzexpr.to()}. \paragraph{Input and output} In C++ it is customary to provide input and output via iostreams, and overloading the operators \code{<<} and \code{>>}. When wrapping a C library which works on the \code{FILE} interface, this is rather hard to accomplish. For this reason, flintxx only provides streaming output (i.e. \code{<<}), and only when there is a \code{to_string} method. Unfortunately this applies to only a small subset of the FLINT types. For output in other cases, and input in all cases, we provide C-like functions. Namely, the functions \code{print}, \code{print_pretty}, \code{read} and \code{read_pretty} can be used similarly to the C \code{flint_printf} and \code{scanf}. For example, \code{print(x)} where \code{x} is an \code{fmpz} has the same effect as \code{std::cout << x}. \paragraph{Extending flintxx} Explanations on the inner workings of the flintxx expression template library and how they pertain to wrapping new C interfaces can be found in appendix~\ref{app:genericxx}. Here we just want to remark that the flintxx classes are not designed for inheritance. If you want to modify behaviour, you should wrap flintxx types into your own classes (extension by aggregation, not inheritance). The header \code{flintxx/forwarding.h} was meant to facilitate this, but has not been finished. \section{Notations and conventions for the C++ interface documentation} As explained above, the flintxx classes and functions perform quite a number of operations which should be invisible to the user. Some template types implement methods which only make sense for some template arguments, etc. For example, every expression template built from \code{fmpq_polyxx} (polynomials with rational coefficients) has a method \code{set_coeff}. However, this method only makes sense for objects of type \code{fmpq_polyxx} or \code{fmpq_polyxx_ref} (calling it on other types will result in a compilation error), and its existence in objects of other types should be considered an implementation detail. In what follows, we document a ``virtual'' set of classes and functions, which explain how the user should expect its objects to behave, and which we guarantee to maintain. Other interfaces should be considered implementation details and subject to change. Consider the interface \code{fmpzxx}, and more concretely an instance \code{a}. As in the above discussion, we see that from \code{a} we can build a lot of different objects: expression templates like \code{a+a}, constant objects like \code{const fmpzxx& b = a;}, reference objects like \code{fmpzxx_ref c(a)}, etc. These by nature behave somewhat differently. For our purposes, we classify types into ``targets'' (things which can be assigned to), ``sources'' (things which contain actual computed data, or references thereto, as opposed to lazy expression templates) and ``expressions'' (sources or expression templates). Note that every target is a source, and every source is an expression. We denote any type which can act as a target for \code{fmpzxx} as \code{Fmpz_target} (note the initial capital letter!), any \code{fmpzxx} source as \code{Fmpz_source} and any \code{fmpzxx} expression as \code{Fmpz_expr}. Such ``made up'' type names (always with initial capital letter) are referred to as ``virtual types'' in the sequel; these are used for all flint classes (e.g. \code{Fmpq_expr} or \code{Fmpz_polyxx_src}). Some examples of virtual types for \code{fmpzxx} are given in table \ref{tab:virtual-type-examples}. \begin{table}[htb] \begin{center} \begin{tabular}{ccc} \code|Fmpz_target| & \code|Fmpz_src| & \code|Fmpz_expr| \\ \hline \code|fmpzxx a;| & \code|const fmpzxx a;| & \code|a + b| \\ \code|fmpzxx& b = a;| & \code|const fmpzxx& b(a);| & \code|a * b| \\ \code|fmpzxx_ref c(a);| & \code|fmpzxx_srcref c(a);| & \code|gcd(a, b)| \\ \end{tabular} \end{center} \caption{Examples of virtual types for \code{fmpzxx}.} \label{tab:virtual-type-examples} \end{table} When using virtual types, we will suppress reference notation. No flintxx types are ever copied automatically, unless the documentation explicitly says so. This is a general philosophy of flintxx: the library does as many things automatically as it can, without introducing additional calls to underlying flint C functions. So for example, it is not possible to implicitly convert \code{int} to \code{fmpzxx} (since doing so requires a C call). Of course explicit conversions (or assignments) work completely fine. It is also often the case that flintxx functions are conditionally enabled templates. A notation such as \code{void foo(T:is_signed_integer)} denotes a template function which is enabled whenever the template parameter \code{T} satisfies the \emph{type trait} \code{is_signed_integer}. These type traits should be self-explanatory, and in any case are documented in TODO. In what follows, we will never document copy constructors, or implicit conversion constructors pertaining to reference types. We will also not document assignment operators for expressions of the same type. (Thus if \code{x} is an \code{fmpzxx} and \code{y} is an \code{fmpqxx}, then \code{x = x} and \code{y = x} are both valid, but only the second assignment operator is documented explicitly.) Most flintxx functions and methods wrap underlying C functions in a way which is evident from the signature of the flintxx function/method. If this is the case, no further documentation is provided. For example, the function \code{double dlog(Fmpz_expr x)} simply wraps \code{double fmpz_dlog(const fmpz_t)}. As is evident from the return type, \code{dlog} immediately evaluates its argument, and then computes the logarithm. In contrast, a function like \code{Fmpz_expr gcd(Fmpz_expr, Fmpz_expr)} returns a lazily evaluated expression template (and wraps \code{void fmpz_gcd(fmpz_t, const fmpz_t, const fmpz_t)}). In case the C function has more than one return value in the form of arguments passed in by reference, the C++ wrapper returns an \code{ltuple}. In this case, the order of the \code{ltuple} arguments is the same as the order of the function arguments; so for example \code{ltupleref(Q, R) = divrem(A, B)} has the same effect as \code{fmpz_poly_divrem(q, r, a, b)}, provided \code{Q, R, A, B} are \code{fmpz_polyxx} and \code{q, r, a, b} are the underlying \code{fmpz_poly_t}. If such a convention is followed, the documentation below may not further explain anything. In all other cases, further explanation is provided (this applies in particular if the C function has return type different from \code{void}). \paragraph{Global functions or member functions?} Often it is not clear if functionality should be exposed as a global function, such as \code{gcd(a, b)}, or as a member function, such as \code{a.gcd(b)}. In flintxx, we strive to make both available when feasible. In the following documentation, the global versions are documented in detail (explaining the allowed types etc), whereas the member function versions are summarised more briefly under e.g. \code{Fmpz_expr::unary operation() const}, \code{Fmpz_expr::binary operation(??) const} etc. \input{input/flintxx.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % profiler % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{profiler} \input{input/profiler.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % interfaces % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{interfaces} \epigraph{Interfaces to other packages}{} \section{Introduction} In this chapter we provide interfaces to various external packages. \input{input/interfaces.tex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % extending the C++ wrapper % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \appendix \chapter{Extending the C++ wrapper} \label{app:genericxx} \section{Introduction} This chapter is geared towards FLINT developers who wish to extend the C++ wrapper, chiefly by adding new functions operating on existing wrapper classes, or by adding altogether new wrapper classes for data types they implemented in C. Part of the design effort of flintxx went into trying to make it possible to do this kind of extension with only cursory knowledge of the syntax of C++, without having to understand in detail things such as partial template specialisation. The easiest way to get started is probably to read \code{examples/fooxx.cpp}. As a matter of fact I hope that most day to day work on the wrapper should be doable by just copying similar code from other data types, so after reading the example you may already know everything you need. \section{Overview of flintxx} The flintxx library is composed of a variety of parts. The main expression template class \code{expression} resides in \code{flintxx/expression.h}. Concrete classes derive from it, and thereby automatically acquire overloaded operators etc. to construct and evaluate expression templates. Of course, this is only possible after telling the flintxx how to do the evaluation, by specialising evaluation rules defined in \code{flintxx/rules.h}. This file also provides convenience macros \code{FLINT_DEFINE_GET} etc., which can be used to simplify defining common rules. Using only these files it would already be possible to interact with flintxx. In many situations one needs to define rules which work with varying argument types, if those types satisfy certain conditions. This can be achieved using the so-called \code{enable_if} idioms together with some meta programming (implemented in \code{flintxx/mp.h}) and type traits (mainly in \code{flintxx/traits.h} and \code{flintxx/expression_traits.h}). These are the files a third party developer should use to interact with flintxx. In writing wrappers for FLINT C types, there are some more common idioms. These are usually expressed as macros \code{FLINTXX_???} and are defined in \code{flintxx/flint_classes.h}. As illustrated in the example, the \code{FLINTXX_???} macros are meant to complement, not supersede, the \code{FLINT_???} macros. The above considerations and examples should explain how to modify any existing class, or write a simple new one, like \code{fmpzxx}. The remaining subsections deal with particular difficulties that require work beyond what has been explained so far. \subsection{Patterns for implementing unified coefficient access} Recall that ``unified coefficient access'' refers to automatically adjusting the return type of coefficient access methods, depending on the argument. Let's focus on the \code{fmpqxx} example, and in particular the \code{num} method. Consider the expression \code{x.num()}. There are three cases: if \code{x} is of type \code{fmpqxx} or \code{fmpqxx_ref}, this should return \code{fmpzxx_ref}. If \code{x} is of type \code{const fmpqxx}, or \code{fmpqxx_srcref}, this should return \code{fmpzxx_srcref}. Otherwise (i.e. if \code{x} is a lazy expression template), this should return a lazy expression template. The way this is implemented is using a traits type. First of all, we need a new lazy function to obtain the numerator: \begin{lstlisting}[language=c++] FLINT_DEFINE_UNOP(fmpqxx_num) \end{lstlisting} We call the function \code{fmpqxx_num} to hide it somewhat, and discourage calling \code{num} as a global function (because this won't have the unified coefficient access properties). Next (even before the expression template definition), we put the generic traits: \begin{lstlisting}[language=c++] template struct fmpq_traits { typedef FLINT_UNOP_BUILD_RETTYPE(fmpqxx_num, fmpzxx, Fmpq) numreturn_t; typedef numreturn_t cnumreturn_t; static numreturn_t num(const Fmpq& f) {return fmpqxx_num(f);} // ... }; \end{lstlisting} This has two typedefs \code{numreturn_t} and \code{cnumreturn_t}, which are the types the \code{num()} method should return on non-constant and constant instances, respectively. As this trait deals with the lazy expression case, we should return a lazy expression in both the constant and non-constant case. Thus we get by with only one static function, which can be called with a constant or non-constant argument, and which creates a new lazy expression involving our new function \code{fmpqxx_num}. The \code{fmpqxx_expression} class can use the traits as follows: \begin{lstlisting}[language=c++] // class fmpqxx_expression typedef detail::fmpq_traits traits_t; typename traits_t::numreturn_t num() {return traits_t::num(*this);} \end{lstlisting} After the definition of the expression template classes, we put the following specialisations: \begin{lstlisting}[language=c++] template<> struct fmpq_traits { typedef fmpzxx_srcref numreturn_t; typedef fmpzxx_srcref cnumreturn_t; template static cnumreturn_t num(T f) {return cnumreturn_t::make(fmpq_numref(f._fmpq()));} }; template<> struct fmpq_traits { typedef fmpzxx_ref numreturn_t; typedef fmpzxx_ref cnumreturn_t; template static cnumreturn_t num(T f) {return cnumreturn_t::make(fmpq_numref(f._fmpq()));} }; template<> struct fmpq_traits { typedef fmpzxx_ref numreturn_t; typedef fmpzxx_srcref cnumreturn_t; template static cnumreturn_t num(const T& f) {return cnumreturn_t::make(fmpq_numref(f._fmpq()));} template static numreturn_t num(T& f) {return numreturn_t::make(fmpq_numref(f._fmpq()));} }; \end{lstlisting} Note how we have to take care of quite a few special cases, and there is not actually any obvious duplication going on here. The way the code is written, calling \code{num()} on a constant instance of \code{fmpqxx_ref} will yield a writable object. This makes sense -- given a constant instance, one can just make a (non-constant) copy, and write through it -- but is not really mandatory. In general, flintxx does not support this kind of writing through constant instances of reference classes. For example, \code{set_zero} will not work on a \code{const fmpqxx_ref}. Thus it would be possible to share some code between the ref and nonref implementations of the traits classes. This is done for example in \code{padicxx}. Finally, in the \code{rules} namespace, we have to place an implementation of \code{fmpqxx_num}: \begin{lstlisting}[language=c++] FLINT_DEFINE_UNARY_EXPR_COND(fmpqxx_num_op, fmpzxx, FMPQXX_COND_S, fmpz_set(to._fmpz(), fmpq_numref(from._fmpq()))) \end{lstlisting} The example of traits usage we see here illustrates how careful one has to be to avoid circular class dependencies. In particular, the traits can only be specialised after the expression template class has been defined and the special immediate cases have been \code{typedef}d. However, they have to be specialised before any of the related templates is instantiated. Note also how the \code{fmpq_traits} functions take their argument by value, thus automatically obtaining non-constant versions, while declaring the argument type via a template. This again delays instantiation, and breaks circular dependencies. \subsection{Nmod classes} Another common complication is when the underlying C objects are not ``default constructible''. For example, the \code{nmod_*} interfaces (\code{nmod_poly}, \code{nmod_mat}, etc.) always require a modulus for initialisation. This is mainly problematic when evaluating compound expressions which require temporary objects. In principle flintxx has an easy workaround for this: the expression template class can define a \code{create_temporary()} method which is used to instantiate a temporary object of the same type as the return type of the current expression. However, this only really shifts the problem: now the expression template class has to figure out its own modulus. To complicate matters further, the moduli are not stored in a single type. The structures \code{nmod_mat_t}, \code{nmod_poly_t}, \code{nmod_poly_mat_t} all store a modulus. Even an expression built out of (say) \code{nmod_poly_mat} can return a (say) \code{nmod_poly} (e.g. the determinant), and so the \code{nmod_polyxx} class must be able to instantiate a temporary for an expression which does not contain any immediate polynomials! As a final complication, the C objects do not actually only store the modulus $n$, but also extra information computed from $n$. This extra information is conveniently wrapped up in \code{nmod_t}, although most of the C interfaces do not expose this data structure directly. These problems are overcome as follows. First of all, we do not allow any mixing of moduli in compound expressions. Thus the only task of the \code{create_temporary} method is to locate \emph{any} modulus inside a subexpression. Next, we require objects with a modulus to be recognisable by type.\footnote{This is why we disallow empty matrices over $\mathbf{Z}/n\mathbf{Z}[X]$. The \code{nmod_poly_mat_t} does not store a modulus, so we have to look at an entry.} With these conventions in place, it is a matter of bookkeeping (and searching the subexpression tree) to locate a modulus. Additionally, we have a class \code{nmodxx_ctx_srcref} (which is not an expression template) which stores a reference to an \code{nmod_t}. All classes which want to provide moduli must implement a \code{_ctx()} method which returns such an \code{nmodxx_ctx_srcref} object. In practice, there is a type trait \code{traits::has_nmodxx_ctx} which should be specialised for all (immediate) classes wishing to participate in the modulus determination. For example, the following lines enable looking up moduli in \code{nmod_poly}: \begin{lstlisting}[language=c++] namespace traits { template<> struct has_nmodxx_ctx : mp::true_ { }; template<> struct has_nmodxx_ctx : mp::true_ { }; template<> struct has_nmodxx_ctx : mp::true_ { }; } // traits \end{lstlisting} In addition to this, as mentioned above, the \code{create_temporary} method has to be overridden: \begin{lstlisting}[language=c++] // class nmod_polyxx nmodxx_ctx_srcref estimate_ctx() const { return tools::find_nmodxx_ctx(*this); } evaluated_t create_temporary() const { return evaluated_t(estimate_ctx()); } \end{lstlisting} The function \code{tools::find_nmodxx_ctx} is implemented in \code{nmod_vec.h} and traverses the subexpression tree, searching for objects containing moduli, and returning the modulus of the first such object found. %There is one final complication, which is what to do if there are no %immediate subexpressions containing moduli. % TODO this is probably not worth explaining here \subsection{Matrix classes} A related but subtly different problem is posed by matrix classes. Again, these are not default instantiable, but one instead needs to specify their dimension (numbers of rows and columns). Two new problems arise. First, it is very common to mix matrices of differing dimensions in one expression (consider transposing a non-square matrix). Second, FLINT does no resizing of matrices. The latter is problematic, because flintxx uses a technique we call ``temporary merging'' where temporary objects needed in a calculation are only identified by type, and allowed to be reused. This reduces memory allocation and deallocation. In the current design, temporary merging cannot be used with matrix classes. The type trait \code{traits::use_temporary_merging} must be used to disable it. After that, we can override \code{create_temporary} in the usual way, except that the method will now be called more often.\footnote{Actually, additional care has to be taken with regard to ltuples. We ignore this here for simplicity.} However, the \code{create_temporary} method still has to figure out the dimensions of the resulting matrix. For this, we use the type trait \code{outsize}. There are static functions \code{outsize::rows(m)} and \code{outsize::cols(m)} which yield the dimensions. Of course, the \code{outsize} trait has to be specialised appropriately. All in all, this is quite a lot of work, much of which is independent of the actual coefficient ring. For this reason, we have the helper file \code{flintxx/matrix.h}. It contains the following: \begin{enumerate} \item The \code{matrix_traits} template. \item Definition of operations for common matrix functions (e.g. transpose). \item The \code{matrices::outsize} and \code{matrices::outsize_generic} templates, and appropriate specialisations for common functions (e.g. transpose, multiplication). \item The templates \code{generic_traits_ref}, \code{generic_traits_srcref} and \code{generic_traits_nonref} to simplify unified coefficient access. \item Some convenience macros. \end{enumerate} To see how these things are used, consider the example of \code{fmpz_matxx}. We begin with the generic traits type for unified coefficient access: \begin{lstlisting}[language=c++] namespace detail { template struct fmpz_matxx_traits : matrices::generic_traits { }; } // detail \end{lstlisting} This defines a traits type, which will be used to implement the \code{at(i, j)} method with unified access. The implementation defined above is the generic one, which is implemented via a call to the lazy operation \code{mat_at}. Next, inside the \code{fmpz_matxx_expression} class, the trait is used as follows: \begin{lstlisting}[language=c++] // class fmpz_matxx_expression typedef detail::fmpz_matxx_traits traits_t; template static evaluated_t create_temporary_rowscols( const Expr&, slong rows, slong cols) { return evaluated_t(rows, cols); } FLINTXX_DEFINE_MATRIX_METHODS(traits_t) \end{lstlisting} The macro \code{FLINTXX_DEFINE_MATRIX_METHODS} adds methods \code{at}, \code{rows}, \code{cols} and \code{create_temporary} for us (the function \code{create_temporary_rowscols} is used by the implementation of \code{create_temporary}). However, these methods cannot work unless we provide more information to the matrix helpers. The main thing we have to do is to specialise the \code{matrix_traits} trait: \begin{lstlisting}[language=c++] template<> struct matrix_traits { template static slong rows(const M& m) { return fmpz_mat_nrows(m._mat()); } template static slong cols(const M& m) { return fmpz_mat_ncols(m._mat()); } template static fmpzxx_srcref at(const M& m, slong i, slong j) { return fmpzxx_srcref::make(fmpz_mat_entry(m._mat(), i, j)); } template static fmpzxx_ref at(M& m, slong i, slong j) { return fmpzxx_ref::make(fmpz_mat_entry(m._mat(), i, j)); } }; \end{lstlisting} This trait means that the class \code{fmpz_matxx} (and all the classes built from it, like reference types and lazy expressions) wants to use the matrix helpers framework. It also specifies how to determine the dimension of immediate objects, and how to access their coefficients. (The framework will never call these trait functions with non-immediates, but we use a template nonetheless so the functions also work on reference types.) Furthermore, we have to specialise some more type traits to disable temporary merging. This is done using the following convenience macro: \begin{lstlisting}[language=c++] // temporary instantiation stuff FLINTXX_DEFINE_TEMPORARY_RULES(fmpz_matxx) \end{lstlisting} The matrix class is now almost operational. In standard expressions (involving transpose, matrix multiplication etc.) temporary objects of the correct dimensions will be allocated automatically. What remains to be done is to implement the rest of the unified coefficient access, and matrix dimension rules for more esoteric functions. The unified coefficient access implementation can in principle be done precisely as described in a previous subsection. However, it is essentially the same in all matrix classes, which is why we provide default implementations: \begin{lstlisting}[language=c++] template<> struct fmpz_matxx_traits : matrices::generic_traits_srcref { }; template<> struct fmpz_matxx_traits : matrices::generic_traits_ref { }; template<> struct fmpz_matxx_traits : matrices::generic_traits_nonref { }; \end{lstlisting} We still have to provide a \code{mat_at} rule: \begin{lstlisting}[language=c++] FLINT_DEFINE_THREEARY_EXPR_COND3(mat_at_op, fmpzxx, FMPZ_MATXX_COND_S, traits::fits_into_slong, traits::fits_into_slong, fmpz_set(to._fmpz(), fmpz_mat_entry(e1._mat(), e2, e3))) \end{lstlisting} Now all that remains to be done is to inform the matrices framework of dimension calculations for functions it is not aware of. For \code{fmpz_matxx}, one example is a particular multiplication algorithm. Of course, the rule is just the same as for ordinary multiplication, so the specialisation is very simple: \begin{lstlisting}[language=c++] namespace matrices { template<> struct outsize : outsize { }; } // matrices \end{lstlisting} In general, if there is no rule, a default case will be used. If the number of arguments is not two, this assumes that the first argument is a matrix, and that the dimensions of the output will match the dimensions of this first argument. If there are two arguments, at least one of which is a matrix, then the dimension of one of those is returned (with no guarantee which if there are two matrices). This default rule works for matrix addition, matrix-scalar multiplication (on either side), and ``elementwise'' operations. \subsection{Padic classes} The classes representing padic numbers (\code{padicxx}, \code{padic_polyxx}, \code{padic_matxx} and \code{qadic}) come with their own difficulties. These are twofold. First of all, padic number data is split into two data structures: the actual number data (e.g. \code{padic_t}), and a \emph{context} (\code{padic_ctx_t}) containing meta data. Any operation on padic numbers needs to be passed both the number data and a context. In order to facilitate this, all C++ wrappers for padics store a reference to a context. We can then use a lookup scheme similar to the \code{nmod_*} case to find a context suitable for a whole expression. One difference is that the context reference has to be stored with every immediate object (e.g. in \code{padic_data}). This also includes the reference types, and hence requires specialising \code{flint_classes::ref_data} and \code{flint_classes::srcref_data}. Secondly, all padic computations are necessarily just approximations. That is to say, like real numbers, padic numbers cannot in general be stored exactly. Thus every padic number also stores its own precision. When the C library is asked to perform an operations, such as \code{a = b + c}, it will treat \code{b} and \code{c} as exact padic numbers (similarly to how we can treat a decimal approximation to a real number, such as $3.14$, as the exact real number $3.140000\dots$). Then it implements an algorithm which is equivalent to performing the computation \code{b + c} exactly and truncating to the precision of \code{c} in the end. This gives very well-defined semantics, and very fine control over the behaviour, but is unfortunately not very well-suited to implementing automatic evaluation of compound expressions. In flintxx, we have decided to (notionally) assign a precision to every compound expression. All temporaries used will be instantiated with this precision. The precision of a compound expression is computed as the maximum of the precision of all of its (immediate) subexpressions. In order to still be able to change this precision, all immediates have a \code{.toN(n)} method which (notionally) raises or lowers their precision. This is implemented by extending the functionality of the \code{padicxx_srcref} type. Namely, in \code{padicxx_srcref}, in addition to a \code{const padic_struct*} and \code{padicxx_ctx_srcref}, we also store an additional \code{slong N} representing the notional precision. The usual constructors of \code{padicxx_srcref} just initialise \code{N} from the underlying \code{padic_struct}. But we provide additional constructors which allow setting this parameter explicitly. The \code{toN} method makes use of these constructors. We thus see that quite a bit of infrastructure is needed to build a new padic class. To facilitate this, \code{padicxx.h} defines some convenience macros. In summary, the following steps are necessary: \begin{enumerate} \item Implement a traits type for computing \code{prec()} and \code{val()}. In the general case, \code{prec()} should return \code{tools::padic_output_prec}. \item In the expression class, typedef \code{traits_t} and invoke the macro \code{PADICXX_DEFINE_STD}.\footnote{This adds context estimation, \code{toN}, \code{prec} and \code{val} methods. Alternatively invoke a subset of \code{PADICXX_DEFINE_CTX}, \code{PADICXX_DEFINE_ESTIMATE_CTX}, \code{PADICXX_DEFINE_TON}, \code{PADICXX_DEFINE_PREC}, \code{PADICXX_DEFINE_VAL}.} \item Enable the trait \code{has_padicxx_ctx} for your immediate classes. \item Specialise the traits type. For reference and non-reference immediates, it should return the precision stored with the objects. For srcref, it should return the N field in \code{_data()}.\footnote{\code{val()} can be an ordinary unified access implementation.} \item Invoke the macro \code{PADICXX_DEFINE_REF_STRUCTS(classname, structname, precname)}. Here \code{classname} is the name of the non-reference immediate (e.g. \code{padicxx}), \code{structname} is the name of the underlying C struct (e.g. \code{padic_struct}) and \code{precname} is the name of the function for accessing the precision (e.g. \code{padic_prec}). This specialises the \code{flint_classes::ref_data} and \code{flint_classes::srcref_data} templates, adding a context reference and \code{toN} support. \end{enumerate} The implementation of \code{qadicxx} is slightly different since it uses a larger context. But this contains \code{padic_ctx} as a substruct, and hence it is not difficult to incorporate \code{qadicxx} into the context lookup infrastructure. See the source for more details. \subsection{Vector classes} Vectors do not have very good representation in FLINT. Usually, but not universally, a vector of type \code{foo_t} is represented as \code{foo_struct*}, with size passed in explicitly. Some vector types have support functions in FLINT, typically all underscored. In flintxx we implement some first class vectors, but the interfaces are not very well developed and relatively ad-hoc. \section{Some tidbits and caveats} One C++ idiom which may initially look staggering is \code{enable_if}. A typical usage is as follows: \begin{lstlisting}[language=c++] template void foo(T, typename enable_if >::type* = 0) { cout << 'a'; } template void foo(T, typename enable_if >::type* = 0) { cout << 'b'; } ... foo(4); // a foo(4u); // b foo("x"); // error \end{lstlisting} What happens syntactically here is that we define two functions called \code{foo}. In C++ this is allowed, such a function is called \emph{overloaded}, and depending on the arguments it is called with, the so-called overloading algorithm decides which instance to call. Additionally, both functions we define are actually \emph{function templates}. Normally, a function template like \code{template void foo(T)} can be called with arbitrary arguments, and so overloading makes little sense.\footnote{One may still overload e.g. \code{foo(T&)} and \code{foo(const T&)}, and say \code{foo(int)}; the overloading algorithm determines a ``best match'', and so this overloading can still be useful. However the details of what constitutes a best match are complicated, and if there are several equally-good matches (none of which is ``best'') then an error will be issued.} But of course the point to observe is that our overloaded functions have an additional argument, which depends on \code{T}. Syntactically, there is an un-named pointer argument, which defaults to zero.\footnote{It is not terribly important that this is a pointer type, it could be say int, but \code{enable_if<...>::type} is defined to be void, and so converting to a pointer is the easiest way to turn this into a function argument.} What happens now is that depending on \code{T}, the function signature may be syntactically invalid! Indeed, the template \code{enable_if} has a member \code{type} only if \code{cond} is true. Otherwise \code{enable_if} is just completely empty, and the function signature makes no sense. But this is fine, according to the SFINAE\footnote{``Substitution Failure Is Not An Error''} rule of C++, if something like this happens during overload resolution, the algorithm just discards this possibility. So in general, what the overload algorithm does it looks for all function templates (and functions) which the overloaded call could possibly match (this by itself is a complicated procedure, because of so-called argument-dependent lookup ...), then tries to instantiate all the function templates, discards all which have substitution failures, and then tries to find the best match in the remaining list. Similar rules also apply in resolving partially specialised template types. In this case, the pattern usually looks like this: \begin{lstlisting}[language=c++] template struct foo { static const int a = 0; }; template struct foo >::type> { static const int a = 1; }; template struct foo >::type> { static const int a = 2; }; ... foo::a; // 0 foo::a; // 2 foo::a; // 1 \end{lstlisting} It may seem tempting to enable member functions conditionally on class template arguments, like this: \begin{lstlisting} template struct foo { void bar(typename enable_if >::type* = 0) {...} }; \end{lstlisting} But this is not possible. The problem is, more or less, that when instantiating \code{foo}, after replacing \code{T} by \code{int}, the entire class signature has to be well-formed, which it just is not. Nonetheless it is typically straightforward to workaround this. You just have to ensure that the signature of your member function is well-formed for any template argument \code{T}. Then in the function body, which is instantiated only when the function is actually called, you can add a \code{STATIC_ASSERT} to make it plain that this function should only be called with integers, etc. Another thing to keep in mind is that in C++98, the expressions \code{> >} and \code{>>} are very different. The latter is a shift operator, and cannot be used to close template argument lists. Thus expressions like \code{not_>} are invalid in C++98, one has to write \code{not_ >} instead. On a similar note, the meaning of an expression involving template arguments can in some situations depend on the template parameter, and sometimes this has to be made explicit. A typical situation is \code{T::something}, which may refer to either a static member value, or a member type of T. If the latter is desired, in most situations one needs to write \code{typename T::something}. Similarly if \code{T} has a member template (function, say), then one cannot write \code{T::something()}, but instead has to write \code{T::template something()}. Most modern compilers will suggest the alternative syntax when such an error is encountered. \input{input/genericxx.tex} \chapter{License} \lstinputlisting[language={},breaklines=false,basicstyle=\scriptsize]{../../LICENSE} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % BACKMATTER % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \backmatter \phantomsection \addcontentsline{toc}{chapter}{References} \bibliographystyle{amsplain} \bibliography{flint-manual} \end{document} flint2-2.8.4/doc/latex/input/000077500000000000000000000000001414523752600157555ustar00rootroot00000000000000flint2-2.8.4/doc/latex/input/title.tex000066400000000000000000000014201414523752600176150ustar00rootroot00000000000000\thispagestyle{plain} \vfill \hbox{% \rule{1pt}{1.0\textheight} \hspace*{0.05\textwidth}% \parbox[b]{0.95\textwidth}{ \vbox{% \vspace{0.1\textwidth} {\noindent\Huge\bfseries FLINT}\\[2\baselineskip] {\Large\itshape Fast Library for Number Theory} \vspace{0.5\textheight} {\large Version~2.5.2}\\[1.2\baselineskip] {\large 13 Aug 2015}\\[1.2\baselineskip] {\large William Hart${}^*$, Fredrik Johansson${}^\dag$, Sebastian Pancratz${}^\ddag$}\\[1.2\baselineskip] {\large ${}^*$ EPSRC Grant EP/G004870/1, DFG Priority Program SPP1489}\\ {\large ${}^\dag$ Supported by Austrian Science Foundation (FWF) Grant Y464-N18}\\ {\large ${}^\ddag$ Supported by European Research Council Grant 204083}\\[1.2\baselineskip] }% end of vbox }% end of parbox }% end of hbox \vfill flint2-2.8.4/doc/profiler.txt000066400000000000000000000121041414523752600160620ustar00rootroot00000000000000******************************************************************************* 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. flint2-2.8.4/doc/source/000077500000000000000000000000001414523752600150015ustar00rootroot00000000000000flint2-2.8.4/doc/source/_static/000077500000000000000000000000001414523752600164275ustar00rootroot00000000000000flint2-2.8.4/doc/source/_static/default.css000066400000000000000000000004651414523752600205720ustar00rootroot00000000000000@import url("classic.css"); 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%; } flint2-2.8.4/doc/source/aprcl.rst000066400000000000000000000347321414523752600166450ustar00rootroot00000000000000.. _aprcl: **aprcl.h** -- APRCL primality testing ======================================================================================== This module implements the rigorous APRCL primality test, suitable for integers up to a few thousand digits. 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` 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:: void 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 | 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|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 integer `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(const unity_zp f) If `f = \zeta^h` returns h; otherwise returns -1. .. function:: int unity_zp_equal(const unity_zp f, const unity_zp g) Returns nonzero if `f = g` reduced by the `p^{exp}`-th cyclotomic polynomial. Output ................................................................................ .. function:: void unity_zp_print(const unity_zp f) Prints the contents of the `f`. 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_fmpz(unity_zp f, const unity_zp g, const fmpz_t s) Sets `f` to `s \cdot g`. `f` and `g` must be initialized with same `p`, `exp` and `n`. .. 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 untiy_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, 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, 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, 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:: ulong unity_zpq_p_unity(const unity_zpq f) If `f = \zeta_p^x` returns `x in [0, p - 1]`; otherwise returns `p`. .. function:: int unity_zpq_is_p_unity(const unity_zpq f) Returns nonzero if `f = \zeta_p^x`. .. function:: int unity_zpq_is_p_unity_generator(const unity_zpq f) Returns nonzero if `f` is a generator of the cyclic group `<\zeta_p>`. .. function:: void unity_zpq_coeff_set_fmpz(unity_zpq f, ulong i, ulong 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, ulong i, ulong 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, ulong i, ulong 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, ulong k) Sets `f` to `g \cdot \zeta_p^k`. .. function:: void unity_zpq_pow(unity_zpq f, 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, 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})`. flint2-2.8.4/doc/source/arith.rst000066400000000000000000000632371414523752600166550ustar00rootroot00000000000000.. _arith: **arith.h** -- arithmetic and special functions ================================================================================ 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, slong n, slong k) .. function:: void arith_stirling_number_1(fmpz_t s, slong n, slong k) .. function:: void arith_stirling_number_2(fmpz_t s, slong n, slong 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, slong n, slong klen) .. function:: void arith_stirling_number_1_vec(fmpz * row, slong n, slong klen) .. function:: void arith_stirling_number_2_vec(fmpz * row, slong 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, fmpz * prev, slong n, slong klen) .. function:: void arith_stirling_number_1_vec_next(fmpz * row, fmpz * prev, slong n, slong klen) .. function:: void arith_stirling_number_2_vec_next(fmpz * row, 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) 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. This function automatically selects between table lookup, binary splitting, and the multimodular algorithm. .. function:: void arith_bell_number_bsplit(fmpz_t res, ulong n) Computes the Bell number `B_n` by evaluating a precise truncation of the series `B_n = e^{-1} \sum_{k=0}^{\infty} \frac{k^n}{k!}` using binary splitting. .. function:: void arith_bell_number_multi_mod(fmpz_t res, ulong n) Computes the Bell number `B_n` using a multimodular algorithm. This function evaluates the Bell number modulo several limb-size primes using\\ ``arith_bell_number_nmod`` 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) Sets `b` to the vector of Bell numbers `B_0, B_1, \ldots, B_{n-1}` inclusive. Automatically switches between the ``recursive`` and ``multi_mod`` algorithms depending on the size of `n`. .. function:: void arith_bell_number_vec_recursive(fmpz * b, slong n) Sets `b` to the vector of Bell numbers `B_0, B_1, \ldots, B_{n-1}` inclusive. This function uses table lookup if `B_{n-1}` fits in a single word, and a standard triangular recurrence otherwise. .. function:: 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. This function evaluates the Bell numbers modulo several limb-size primes using\\ ``arith_bell_number_nmod_vec`` and reconstructs the integer values using the fast Chinese remainder algorithm. A bound for the number of needed primes is computed using ``arith_bell_number_size``. .. function:: mp_limb_t arith_bell_number_nmod(ulong n, nmod_t mod) Computes the Bell number `B_n` modulo a prime `p` 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. The divisions by factorials require `n > p`, so we fall back to calling\\ ``bell_number_nmod_vec_recursive`` and reading off the last entry when `p \le n`. .. function:: void arith_bell_number_nmod_vec(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 a prime `p` given by ``mod``. Automatically switches between the ``recursive`` and ``series`` algorithms depending on the size of `n` and whether `p` is large enough for the series algorithm to work. .. function:: void arith_bell_number_nmod_vec_recursive(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 a prime `p` given by ``mod``. This function uses table lookup if `B_{n-1}` fits in a single word, and a standard triangular recurrence otherwise. .. function:: void 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 a prime `p` given by ``mod``. This function expands the exponential generating function ``\sum_{k=0}^{\infty} \frac{B_n}{n!} x^n = \exp(e^x-1).`` We require that `p \ge n`. .. function:: double arith_bell_number_size(ulong n) Returns `b` such that `B_n < 2^{\lfloor b \rfloor}`, using the inequality ``B_n < \left(\frac{0.792n}{\log(n+1)}\right)^n`` which is given in [BerTas2010]_. 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. As presently implemented, this function simply calls\\ ``_arith_bernoulli_number_zeta``. .. 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. Warning: this function does not use proven precision bounds, and could return the wrong results for very large `n`. It is recommended to use the Bernoulli number functions in Arb instead. .. 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_zeta(fmpz_t num, fmpz_t den, ulong n) Sets ``(num, den)`` to the reduced numerator and denominator of the `n`-th Bernoulli number. This function first computes the exact denominator and a bound for the size of the numerator. It then computes an approximation of `|B_n| = 2n! \zeta(n) / (2 \pi)^n` as a floating-point number and multiplies by the denominator to to obtain a real number that rounds to the exact numerator. For tiny `n`, the numerator is looked up from a table to avoid unnecessary overhead. Warning: this function does not use proven precision bounds, and could return the wrong results for very large `n`. It is recommended to use the Bernoulli number functions in Arb instead. .. 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_zeta(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 repeated direct calls to\\ ``_arith_bernoulli_number_zeta``. .. 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`. Currently calls ``_arith_euler_number_zeta``. Warning: this function does not use proven precision bounds, and could return the wrong results for very large `n`. It is recommended to use the Euler number functions in Arb instead. .. 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. .. function:: void _arith_euler_number_zeta(fmpz_t res, ulong n) Sets ``res`` to the Euler number `E_n`. For even `n`, this function uses the relation ``|E_n| = \frac{2^{n+2} n!}{\pi^{n+1}} L(n+1)`` where `L(n+1)` denotes the Dirichlet `L`-function with character `\chi = \{ 0, 1, 0, -1 \}`. Warning: this function does not use proven precision bounds, and could return the wrong results for very large `n`. It is recommended to use the Euler number functions in Arb instead. 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, const fmpz_t n, ulong k) 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. Cyclotomic polynomials -------------------------------------------------------------------------------- .. function:: void _arith_cos_minpoly(fmpz * coeffs, slong d, ulong n) For `n \ge 1`, sets ``(coeffs, d+1)`` to the minimal polynomial `\Psi_n(x)` of `\cos(2 \pi / n)`, scaled to have integer coefficients by multiplying by `2^d` (`2^{d-1}` when `n` is a power of two). The polynomial `\Psi_n(x)` is described in [WaktinsZeitlin1993]_. As proved in that paper, the roots of `\Psi_n(x)` for `n \ge 3` are `\cos(2 \pi k / n)` where `0 \le k < d` and where `\gcd(k, n) = 1`. To calculate `\Psi_n(x)`, we compute the roots numerically with MPFR and use a balanced product tree to form a polynomial with fixed-point coefficients, i.e. an approximation of `2^p 2^d \Psi_n(x)`. To determine the precision `p`, we note that the coefficients in `\prod_{i=1}^d (x - \alpha)` can be bounded by the central coefficient in the binomial expansion of `(x+1)^d`. When `n` is an odd prime, we use a direct formula for the coefficients (https://mathworld.wolfram.com/TrigonometryAngles.html ). .. function:: void arith_cos_minpoly(fmpz_poly_t poly, ulong n) Sets ``poly`` to the minimal polynomial `\Psi_n(x)` of `\cos(2 \pi / n)`, scaled to have integer coefficients. This polynomial has degree 1 if `n = 1` or `n = 2`, and degree `\phi(n) / 2` otherwise. We allow `n = 0` and define `\Psi_0 = 1`. 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 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. flint2-2.8.4/doc/source/bug_reporting.rst000066400000000000000000000015151414523752600204030ustar00rootroot00000000000000.. _bug_reporting: **Bug reporting** =============================================================================== Reporting bugs ------------------------------------------------------------------------------- The maintainer wishes to be made aware of any and all bugs. Please 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, the version of GCC, the versions of GMP/MPIR and MPFR as well as precise details of how to replicate the bug. Note that FLINT needs to be linked against version 2.6.0 or later of MPIR (or version 5.1.1 or later of GMP), version 3.0.0 or later of MPFR and must be compiled with gcc version 2.96 or later. Version 4.8 or later of GCC is recommended for parallel builds and use of the ``C++`` interface. flint2-2.8.4/doc/source/building.rst000066400000000000000000000264401414523752600173360ustar00rootroot00000000000000.. _building: **Configuring and building** =============================================================================== Configuring Flint ------------------------------------------------------------------------------- There are three ways to build Flint. One way is through a standard set of CMake files provided in the distribution. A second way is with a custom build system based on a configuration script and Makefiles also provided in the distribution. A third way using MSVC solution files is documented in a section further down. The easiest way to use FLINT is to build a shared library. Simply download the FLINT tarball and untar it on your system. FLINT requires either MPIR (version 2.6.0 or later) or GMP (version 5.1.1 or later). If MPIR is used, MPIR must be built with the ``--enable-gmpcompat`` option. FLINT also requires MPFR 3.0.0 or later and a pthread implementation. Some of the input/output tests require ``fork`` and ``pipe``, however these are disabled on Windows when a posix implementation is not provided. If it happens that GMP/MPIR and MPFR are not in a standard location on your system (e.g. not in ``/usr/include/`` and ``/usr/lib/``), you need to tell the configure script where they are with the options ``--with-gmp=/path/to/gmp`` or ``--with-mpir=/path/to/mpir`` and ``--with-mpfr=/path/to/mpfr``, e.g. .. code-block:: bash ./configure --with-gmp=/home/user1/local --with-mpfr=/home/user1/local FLINT can also build against a source build of GMP/MPIR and MPFR. Though programs using FLINT may require GMP/MPIR and MPFR to be installed (via ``make install`` if built from sources). Note that 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. 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. 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 ``--single`` option to configure, though note that this is the default. The reentrant mode is selected by passing the option ``--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 passing ``--build=cpu-os`` to configure. The available choices for CPU include ``x86_64``, ``x86``, ``ia64``, ``sparc``, ``sparc64``, ``ppc``, ``ppc64``. Other CPU types are unrecognised and FLINT will build with generic code on those machines. The choices for OS include ``Linux``, ``MINGW32``, ``MINGW64``, ``CYGWIN32``, ``CYGWIN64``, ``Darwin``, ``FreeBSD``, ``SunOS`` and numerous other operating systems. 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. C++ wrapper ------------------------------------------------------------------------------- If you wish to enable the test functions for the FLINT ``C++`` wrapper ``flintxx`` you must pass ``--enable-cxx`` to configure. The ``C++`` wrapper is always available, but tests will only run if this option is selected. It is disabled by default (``--disable-cxx``) because some ``C++`` compilers internally segfault when compiling the tests, or exhaust memory due to the complexity of the ``C++`` code. Building, testing, installing and using FLINT ------------------------------------------------------------------------------- Once FLINT is configured, in the main directory of the FLINT directory tree simply type: .. code-block:: bash make make check GNU make or CMake is required to build FLINT. For GNU make, this is simply ``make`` on Linux, Darwin, MinGW and Cygwin systems. However, on some unixes the command is ``gmake``. For CMake, this is ``cmake``, which which may need to be installed with your package manager. If you wish to install FLINT with GNU make, simply type: .. code-block:: bash make install If you wish to install FLINT with CMake, simply type: .. code-block:: bash mkdir build && cd build cmake .. -DBUILD_SHARED_LIBS=ON cmake --build . --target install 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/MPIR, MPFR and pthreads with the options ``-lflint -lmpfr -lgmp -lpthread``. To uninstall FLINT with GNU make, type: .. code-block:: bash make uninstall Note that you may have to set ``LD_LIBRARY_PATH`` or equivalent for your system to let the linker know where to find these libraries. Please refer to your system documentation for how to do this. If you have any difficulties with conflicts with system headers on your machine, you can do the following in your code: .. code-block:: C #undef ulong #define ulong ulongxx #include // other system headers #undef ulong #define ulong mp_limb_t This prevents FLINT's definition of ``ulong`` interfering with your system headers. The FLINT custom make system responds to the standard commands .. code-block:: bash make make library make check make clean make distclean make install If your system supports parallel builds, FLINT will build in parallel, e.g: .. code-block:: bash make -j4 check On some systems, parallel builds appear to be available but buggy. Testing a single module or file ------------------------------------------------------------------------------- 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 in inverted commas, e.g: .. code-block:: bash make check MOD=ulong_extras make check MOD="fft fmpz_mat" To specify an individual test(s) for any module you can add it (or comma separated test list) after chosen module name followed by the colon, e.g.: .. code-block:: bash make check MOD=ulong_extras:clog,factor,is_prime make check MOD="fft fmpz_mat:add_sub,charpoly fq_vec:add" 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. Exceptions ------------------------------------------------------------------------------- When FLINT encounters a problem, mostly illegal input, it currently aborts. There is an experimental interface for generating proper exceptions ``flint_throw``, but this is currently rarely used and experimental - you should expect this to change. At the end, all of FLINT's exceptions call ``abort()`` to terminate the program. Using ``flint_set_abort(void (*abort_func)(void))``, the user can install a function that will be called instead. Similar to the exceptions, this should be regarded as experimental. Building FLINT2 with Microsoft Visual Studio using solution files ------------------------------------------------------------------------------- Brian Gladman has kindly provided the build scripts for building Flint with Microsoft Visual Studio. Building FLINT2 with Microsoft Visual Studio requires Visual Studio 2015 Community (or higher version) and: - an installed version of Python 3 - an installed version of Python Tools for Visual Studio Obtain FLINT2 by cloning it using GIT from Brian Gladman's repository: ``git@github.com:BrianGladman/flint.git`` FLINT2 depends on the MPIR, MPFR and PTHREADS libraries that have to be installed and built using Visual Studio before FLINT2 can be built. The application directories are assumed to be in the same root directory with the names and layouts: .. code :: mpir lib dll mpfr lib dll pthreads lib dll flint build.vc lib dll Here the ``lib`` and ``dll`` sub-directories for each application hold the static and dynamic link library outputs which will be used when Flint is built. They each contain up to four sub-directories for the normal configurations for building on Windows: ``Win32\Release`` ``Win32\Debug`` ``x64\Release`` ``x642\Debug`` To build FLINT2 for a particular configuration requires that each of the three libraries on which FLINT2 depends must have been previously built for the same configuration. Opening the solution file ``flint\build.vc\flint.sln`` provides the following build projects: ``flint_config`` - a Python program for creating the Visual Studio build files ``build_tests`` - a Python program for building the FLINT2 tests (after they have been created) ``run_tests`` - a Python program for running the FLINT2 tests (after they have been built) The first step in building FLINT2 is to generate the Visual Studio build files for the version of Visual Studio being used. This is done by running the Python application ``flint_config.py``, either from within Visual Studio or on the command line. It is run with a single input parameter which is the last two digits of the Visual Studio version selected for building FLINT2 (the default is 19 if no input is given). This creates a build directory in the Flint root directory, for example: ``flint\build.vs19`` that contains the file ``flint.sln`` which can now be loaded into Visual Studio and used to build the FLINT2 library. Once the FLINT2 library has been built, the FLINT2 tests can now be built and run by returning to the Visual Studio solution: ``flint\build.vc\flint.sln`` and running the ``build_tests`` and ``run_tests`` Python applications. After building FLINT2, the libraries and the header files that you need to use FLINT2 are placed in the directories: - ``lib\\`` - ``dll\\`` depending on the version(s) that have been built. flint2-2.8.4/doc/source/conf.py000066400000000000000000000130301414523752600162750ustar00rootroot00000000000000# -*- 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: # http://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('.')) # -- Project information ----------------------------------------------------- project = u'Flint' copyright = u'2018, The Flint development team' author = u'The Flint development team' # The short X.Y version version = u'' for _line in open("../../flint.h").readlines(): if _line.startswith("#define FLINT_VERSION"): _i1 = _line.find('"') _i2 = _line.find('"', _i1 + 1) version = _line[_i1+1:_i2] release = version # The full version, including alpha/beta/rc tags release = version # -- 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', ] # 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 = None # 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' : 280, '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', # 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}', # 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 ------------------------------------------------- flint2-2.8.4/doc/source/contributors.rst000066400000000000000000000011411414523752600202650ustar00rootroot00000000000000.. _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: http://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. flint2-2.8.4/doc/source/d_mat.rst000066400000000000000000000125571414523752600166310ustar00rootroot00000000000000.. _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(d_mat_t mat1, d_mat_t mat2) Swaps two matrices. The dimensions of ``mat1`` and ``mat2`` are allowed to be different. .. 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. .. function:: void d_mat_one(d_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. 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_zero(const d_mat_t mat) Returns a non-zero value if all entries ``mat`` are zero, and otherwise returns zero. .. function:: int d_mat_is_approx_zero(const d_mat_t mat, double eps) Returns a non-zero value if all entries ``mat`` are zero to within ``eps`` and otherwise returns zero. .. function:: int d_mat_is_empty(const d_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 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. Gram-Schmidt Orthogonalisation and QR Decomposition -------------------------------------------------------------------------------- .. function:: void d_mat_gso(d_mat_t B, const d_mat_t A) Takes a subset of `R^m` `S = {a_1, a_2, \ldots, a_n}` (as the columns of a `m x n` matrix ``A``) and generates an orthonormal set `S' = {b_1, b_2, \ldots, b_n}` (as the columns of the `m x n` matrix ``B``) that spans the same subspace of `R^m` as `S`. This uses an algorithm of Schwarz-Rutishauser. See pp. 9 of https://people.inf.ethz.ch/gander/papers/qrneu.pdf .. function:: void d_mat_qr(d_mat_t Q, d_mat_t R, const d_mat_t A) Computes the `QR` decomposition of a matrix ``A`` using the Gram-Schmidt process. (Sets ``Q`` and ``R`` such that `A = QR` where ``R`` is an upper triangular matrix and ``Q`` is an orthogonal matrix.) This uses an algorithm of Schwarz-Rutishauser. See pp. 9 of https://people.inf.ethz.ch/gander/papers/qrneu.pdf flint2-2.8.4/doc/source/d_vec.rst000066400000000000000000000073421414523752600166210ustar00rootroot00000000000000.. _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`. Addition and subtraction -------------------------------------------------------------------------------- .. 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)``. 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 \url{http://www.ti3.tuhh.de/paper/rump/OgRuOi05.pdf}. flint2-2.8.4/doc/source/double_extras.rst000066400000000000000000000044401414523752600203750ustar00rootroot00000000000000.. _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 the polynomial defined by the given ``len`` coefficients. Requires that ``len`` is nonzero. 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. flint2-2.8.4/doc/source/examples.rst000066400000000000000000000043651414523752600173610ustar00rootroot00000000000000.. _examples: **Examples** =============================================================================== Example programs ------------------------------------------------------------------------------- FLINT comes with example programs to demonstrate current and future FLINT features. To build the example programs, type: .. code-block:: bash make examples The example programs are built in the ``build/examples`` directory. You must set your ``LD_LIBRARY_PATH`` or equivalent for the FLINT, MPIR and MPFR libraries. See your operating system documentation to see how to set this. The current example programs are: - ``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 polynomials 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. - ``fmpz_poly`` Gives a very simple example of the ``fmpz_poly`` module. - ``fmpq_poly`` Gives a very simple example of the ``fmpq_poly`` module. Some of the example programs have associated ``C++`` versions. flint2-2.8.4/doc/source/fft.rst000066400000000000000000000704711414523752600163230ustar00rootroot00000000000000.. _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_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 twos 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 twos 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 twos 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*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*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 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 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``. flint2-2.8.4/doc/source/flint.rst000066400000000000000000000116351414523752600166550ustar00rootroot00000000000000.. _flint: **flint.h** -- global definitions =============================================================================== 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() 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:: void flint_get_num_threads() 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 counts the workers in the thread pool plus one more 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. .. 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 * str, ...) int flint_vprintf(const char * str, va_list ap) int flint_fprintf(FILE * f, const char * str, ...) int flint_sprintf(char * s, const char * str, ...) These are equivalent to the standard library functions ``printf``, ``vprintf``, ``fprintf``, and ``sprintf`` with an additional length modifier "w" for use with an :type:`mp_limb_t` type. This modifier can be used with format specifiers "d", "x", or "u", thereby outputting the limb as a signed decimal, hexadecimal, or unsigned decimal integer. .. 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. flint2-2.8.4/doc/source/flintxx.rst000066400000000000000000000410321414523752600172270ustar00rootroot00000000000000.. _flintxx: **flintxx** -- C++ Wrapper =============================================================================== Introduction ------------------------------------------------------------------------------- Flint provides a C++ wrapper which makes extensive use of metaprogramming. It is currently not maintained for the whole of Flint due to lack of a C++ developer willing to step up and maintain it. Therefore it is provided as-is, though we do try to do sufficient maintenance to keep the `currently wrapped functions `_ compiling. In this section we describe how to use ``flintxx`` the Flint C++ wrapper. We begin with a simple example: .. code-block:: C #include "fmpzxx.h" using namespace flint; fmpzxx x, y; x = 7u; y = x*x; std::cout << x << "^2 = " << y << std::endl; As can be seen, if a FLINT C interface is called ``foo``and resides in ``foo.h``, then the C++ version is called ``fooxx`` and resides in ``fooxx.h``. All flintxx classes live inside ``namespace flint``. Functions which operate on wrapper classes are usually implemented as overloaded stand-alone functions, with the type prefix dropped. For example, a call to ``flint::gcd(f1, f2)`` yields an expression template evaluating via ``fmpz_gcd``, provided ``f1`` and ``f2`` evaluate to instances of ``fmpzxx``. Sometimes we felt that dropping the type prefix would yield incomprehensible names, as for example in ``fmpq_next_minimal``, or ``fmpq_reconstruct``. In these cases the type prefix is swapped for the flintxx equivalent, so the flintxx version would be called ``fmpqxx_reconstruct``. In this situation, usually the same functionality is also exposed as a (possibly static) member function, and this is the preferred way of accessing the functionality. Thus one should write ``fmpqxx::reconstruct(a, m)`` or ``fmpqxx(0, 1u).next_minimal()``. Expression templates ------------------------------------------------------------------------------- The implementation of flintxx tries very hard not to incur any overhead over using the native C interface. For this reason, we use ``expression templates`` for lazily evaluating expressions. This allows us to avoid creating excessively many temporaries, for example. This means that even if ``x`` and ``y`` are of type ``fmpzxx``, then ``x + y`` will not be of type ``fmpzxx``. Instead it will be an object which for most purposes behaves just like ``fmpzxx``, but really only expresses the fact that it represents the sum of ``x`` and ``y``. This distinction almost never matters, since expression templates are evaluated automatically in most cases. Thus ``cout << x + y`` or ``x + y == 7`` will work just as one might expect. There are ways to request explicit evaluation of an expression template, most notably ``(x + y).evaluate()`` and ``fmpzxx(x + y)``. One caveat of the expression template approach is that compiler error messages can be long and hard to understand. In flintxx we strive to type-check template parameters as early as possible in order to keep error messages short and close to the actual user error. Excessively long error messages are often indicative of a bug in flintxx. Tuples ------------------------------------------------------------------------------- Many FLINT functions naturally return two or more arguments. A typical example is ``divrem``. The underlying C function is ``void fmpz_poly_divrem(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B)``. Mapping this directly to C++ would yield something like ``void divrem(fmpz_polyxx& Q, fmpz_polyxx& R, const fmpz_polyxx& A, const fmpz_polyxx& B)}``. While functional, this is not particularly nice; the syntax ``divrem(Q, R, A, B)``, where the first two arguments are modified, is just very reminiscent of C. We prefer an expression closer to the python analogue ``(Q, R) = divrem(A, B)``. For this purpose, flintxx uses lazy tuples and the following is a valid flintxx expression: ``ltupleref(Q, R) = divrem(A, B)``. For the purpose of this documentation, ltuple types are denoted as follows: ``Ltuple``. Thus, ``divrem`` would return an object of type ``Ltuple``. The user should never try to construct such types by hand; instead use the function ``ltupleref`` (and perhaps occasionally ``ltuple``; both documented later). One thing to observe is that ltuples are typed fairly weakly. Thus assignments and equality comparisons can be performed as long as both sides have the same length, and the operation can be performed on all components (whether or not the component types match). Another interesting feature of ltuples is the type ``flint::detail::IGNORED_TYPE``. In an ltuple assignment, where the left hand side contains a reference to this type, the relevant entry is just discarded. Since the ``ltuple.h`` header automatically creates a static instance ``_`` of this type, in the following listing, the lines marked (1) and (2) have the same effect (but the second is potentially more efficient). .. code-block:: C #include "fmpz_polyxx.h" using namespace flint; fmpz_polyxx f, g; fmpz_polyxx R; ltupleref(_, R) = divrem(f, g); // (1) R = f % g; // (2) Note finally that using ``ltuple`` intermediates often results in more copies than necessary. For example the expression ``ltupleref(num, _) = divrem(a, b)`` assigns the quotient to ``num``, creating just a temporary ``fmpzxx`` to hold the remainder. In contrast, ``num = divrem(a, b).get<0>()`` creates two temporary instances of ``fmpzxx``. Reference types ------------------------------------------------------------------------------- One subtlety in wrapping a C library is that references do not work as easily as one might expect. For example, consider the class ``fmpqxx``, wrapping ``fmpq_t``, i.e. rational numbers. As such, an instance of ``fmpqxx`` has a numerator and denominator. In C, these are accessible via macros ``fmpq_numref`` and ``fmpq_denref``, which yield ``fmpz*``, which can be used essentially interchangeably with ``fmpz_t``. In particular, any library function which operates on ``fmpz_t`` can operate on the numerator or denominator of an ``fmpq_t``. In C++, we would like to have a member functions ``den` and ``num`` which return an object of type ``fmpzxx&`` (i.e. a reference to ``fmpzxx``). However, this is not possible, since ``fmpqxx`` is not implemented as a pair of ``fmpzxx``, and instead simply contains an ``fmpq_t``. For this reason, for every C interface ``foo``, flintxx provides two additional types, called ``fooxx_ref`` and ``fooxx_srcref``, acting as replacements for ``fooxx&`` and ``const foox&``, respectively, in situations where no underlying C++ object exists. Instances of ``fooxx_ref`` or ``fooxx_srcref`` behave exactly like instances of ``fooxx``. In fact, the user should never notice a difference. Any flintxx operation or expression which works on objects of type ``foo`` also works on objects of type ``fooxx_ref`` and ``fooxx_srcref``. Moreover, instances of ``foo`` can be converted implicitly to ``fooxx_ref`` or ``fooxx_srcref``, and ``fooxx_ref`` can be converted implicitly to ``fooxx_srcref``. It is also possible to explicitly convert reference types ``fooxx_*ref`` to ``fooxx`` (since this entails copying, we provide no implicit conversion). In summary, the class ``fooxx_ref`` behaves like a reference to an object of type ``fooxx``. As such it can be used both as a right hand side and as a left hand side, just like ``fooxx``. The class ``fooxx_srcref`` behaves like a reference to a constant object of type ``fooxx``, and so cannot be used as a left hand side. These objects are created by flintxx automatically,`for example upon calling ``fmpqxx::num()``. Unified coefficient access ------------------------------------------------------------------------------- Consider again the ``x.num()`` method of ``fmpqxx``. In various situations, this can have different return types. Namely, if ``x`` is a writable expression, then ``x.num()`` returns an ``fmpzxx_ref``. In particular the return value behaves just like ``fmpzxx``, no evaluation is necessary to obtain it, there are no copies, and it is possible to change the return value (and thus change ``x``). If on the other hand ``x`` is a readonly immediate, then the return value of ``x.num()`` has type ``fmpzxx_srcref``. This again behaves just like ``fmpzxx`` and no evaluations or copies are necessary, but this time it is not possible to change the return value (and so it is not possible to change ``x``, either). Finally, if ``x`` is a lazy expression, then the return value is actually a lazy expression template. Thus to obtain the "actual" value of ``x.num()``, evaluations are necessary, and potentially so are copies. Thus in any case the return value behaves just like ``fmpqxx``, but apart from that the behaviour of ``x.num()`` varies quite drastically in the different situations. We call this "unified coefficient access" (the coefficients of a ``fmpqxx`` being ``num(), den()``), and the same behaviour occurs in many other flintxx types, e.g. in ``fmpz_polyxx.coeff()``, etc. Type conversion ------------------------------------------------------------------------------- As a rule, flintxx does not perform automatic type conversions (except when related to the promotion to reference types, c/f earlier discussion). In expression templates, operands can be automatically promoted if the underlying C interface provides this facility. Beyond that, types have to be converted explicitly. There are two ways of doing this. The preferred one is using static constructor functions. Typical examples are ``fmpz_polyxx::from_ground(fmpzarg)`` and ``nmod_polyxx::reduce(mplimbarg, nmodctxarg)``. The former takes an (expression template evaluating to) ``fmpzxx`` and returns an ``fmpz_polyxx`` representing the constant polynomial with value the ``fmpzxx``. The latter takes an argument of type ``mp_limb_t`` and one of type ``nmodxx_ctx_srcref`` (essentially a word-sized modulus) and returns an ``nmod_polyxx`` representing the constant polynomial obtained by reducing ``mplimbarg``. The general format for this is ``totype::constructorname(arg1, arg2, ...)``. We prefer this because it makes explicit the type that is being converted to, and the way the arguments are to be interpreted. This format only works if the target type is part of flintxx. In other cases, we use a ``.to()`` syntax, as in ``fmpzexpr.to()``. Input and output ------------------------------------------------------------------------------- In C++ it is customary to provide input and output via iostreams, and overloading the operators ``<<`` and ``>>``. When wrapping a C library which works on the ``FILE`` interface, this is rather hard to accomplish. For this reason, flintxx only provides streaming output (i.e. ``<<``), and only when there is a ``to_string`` method. Unfortunately this applies to only a small subset of the FLINT types. For output in other cases, and input in all cases, we provide C-like functions. Namely, the functions ``print``, ``print_pretty``, ``read`` and ``read_pretty`` can be used similarly to the C ``flint_printf`` and ``scanf``. For example, ``print(x)`` where ``x`` is an ``fmpz`` has the same effect as ``std::cout << x``. Inheritance and flintxx ------------------------------------------------------------------------------- The flintxx classes are not designed for inheritance. If you want to modify behaviour, you should wrap flintxx types into your own classes (extension by aggregation, not inheritance). Notation and conventions in flintxx documentation ------------------------------------------------------------------------------- As explained above, the flintxx classes and functions perform quite a number of operations which should be invisible to the user. Some template types implement methods which only make sense for some template arguments, etc. For example, every expression template built from ``fmpq_polyxx`` (polynomials with rational coefficients) has a method ``set_coeff``. However, this method only makes sense for objects of type ``fmpq_polyxx`` or ``fmpq_polyxx_ref`` (calling it on other types will result in a compilation error), and its existence in objects of other types should be considered an implementation detail. In what follows, we document a "virtual" set of classes and functions, which explain how the user should expect its objects to behave, and which we guarantee to maintain. Other interfaces should be considered implementation details and subject to change. Consider the interface ``fmpzxx``, and more concretely an instance ``a``. As in the above discussion, we see that from ``a`` we can build a lot of different objects: expression templates like ``a+a``, constant objects like ``const fmpzxx& b = a;``, reference objects like ``fmpzxx_ref c(a)``, etc. These by nature behave somewhat differently. For our purposes, we classify types into "targets" (things which can be assigned to), "sources" (things which contain actual computed data, or references thereto, as opposed to lazy expression templates) and "expressions" (sources or expression templates). Note that every target is a source, and every source is an expression. We denote any type which can act as a target for ``fmpzxx`` as ``Fmpz_target`` (note the initial capital letter!), any ``fmpzxx`` source as ``Fmpz_source`` and any ``fmpzxx`` expression as ``Fmpz_expr``. Such made up type names (always with initial capital letter) are referred to as "virtual types" in the documentation. These are used for all flint classes (e.g. ``Fmpq_expr`` or ``Fmpz_polyxx_src``). When using virtual types, we will suppress reference notation. No flintxx types are ever copied automatically, unless the documentation explicitly says so. This is a general philosophy of flintxx: the library does as many things automatically as it can, without introducing additional calls to underlying Flint C functions. So for example, it is not possible to implicitly convert ``int`` to ``fmpzxx`` (since doing so requires a C call). Of course explicit conversions (or assignments) work completely fine. It is also often the case that flintxx functions are conditionally enabled templates. A notation such as ``void foo(T:is_signed_integer)`` denotes a template function which is enabled whenever the template parameter ``T`` satisfies the type trait ``is_signed_integer``. These type traits should be self-explanatory. In what follows, we will never document copy constructors, or implicit conversion constructors pertaining to reference types. We will also not document assignment operators for expressions of the same type. Thus if ``x`` is an ``fmpzxx`` and ``y`` is an ``fmpqxx``, then ``x = x`` and ``y = x`` are both valid, but only the second assignment operator is documented explicitly. Most flintxx functions and methods wrap underlying C functions in a way which is evident from the signature of the flintxx function/method. If this is the case, no further documentation is provided. For example, the function ``double dlog(Fmpz_expr x)`` simply wraps ``double fmpz_dlog(const fmpz_t)``. As is evident from the return type, ``dlog`` immediately evaluates its argument, and then computes the logarithm. In contrast, a function like ``Fmpz_expr gcd(Fmpz_expr, Fmpz_expr)`` returns a lazily evaluated expression template and wraps ``void fmpz_gcd(fmpz_t, const fmpz_t, const fmpz_t)``. In case a Flint C function has more than one return value in the form of arguments passed in by reference, the C++ wrapper returns an ``ltuple``. In this case, the order of the ``ltuple`` arguments is the same as the order of the function arguments; so for example ``ltupleref(Q, R) = divrem(A, B)`` has the same effect as ``fmpz_poly_divrem(q, r, a, b)``, provided ``Q, R, A, B`` are ``fmpz_polyxx`` and ``q, r, a, b`` are the underlying ``fmpz_poly_t``. If such a convention is followed, the documentation below may not further explain anything. In all other cases, further explanation is provided (this applies in particular if the C function has return type different from ``void``). Global functions or member functions? ------------------------------------------------------------------------------- Often it is not clear if functionality is exposed as a global function, such as ``gcd(a, b)``, or as a member function, such as ``a.gcd(b)``. In flintxx, we strive to make both available when feasible. In the documentation, the global versions are documented in detail (explaining the allowed types etc), whereas the member function versions are summarised more briefly under e.g. ``Fmpz_expr::unary operation() const``, ``Fmpz_expr::binary operation(??) const`` etc. flint2-2.8.4/doc/source/flintxx_functions.txt000066400000000000000000005276621414523752600213500ustar00rootroot00000000000000.. _flintxx_functions: **flint.. cpp:functions** -- C++ Wrapper =============================================================================== Flint exception type =============================================================================== flint\_exception This is the main exception type used by the flintxx library. It derives from ``std::domain_error``. As such its main method is ``what()``, yielding an English language description of the problem encountered. Rand.. cpp:functions =============================================================================== .. type:: frandxx The type ``frandxx`` wraps ``flint_rand_t`` and takes care of initialising and clearing random states. It is defined in ``flintxx/frandxx.h``. Note that this type is not copyable. .. cpp:function:: frandxx::frandxx() Initialize random state. .. cpp:function:: flint_rand_t& frandxx::_data() .. cpp:function:: const flint_rand_t& frandxx::_data() const Obtain a reference to the underlying C random state. Tuples =============================================================================== .. type:: ltuple Lazy tuples are implemented in ``flintxx/ltuple.h``. They are used throughout flintxx to emula.. cpp:functions with several return values. This header automatically creates a static instance of ``flint::detail::IGNORED_TYPE``. It is accessible in namespace flint, under the name ``FLINT_LTUPLE_PLACEHOLDER_NAME``, which defaults to ``_``. See ``ltupleref`` documentation for how to use this. Construct an ltuple of references, binding to the arguments ``t1``, \dots, ``tn``. Instances of ``flint::detail::IGNORED_TYPE`` can be used as placeholders. Currently $n \le 4$. .. cpp:function:: Ltuple ltuple(const T1& t1, ..., const Tn& tn) Construct an ltuple containing copies of ``t1``, \dots, ``tn``. Currently \code{n \le 4}. .. cpp:function:: Tk_expr Ltuple_expr::get() const If ``Tk`` is an expression template type, then the ``get()`` method returns a lazy expression evaluating to the kth element of the (potentially lazy) ltuple. If ``Tk`` is not an expression template type, this method evaluates the ltuple, and returns the kth entry. On ltuple immediates, reference versions are also available, which can be used to manipulate the entries. Permutations =============================================================================== .. type:: permxx Permutations are mostly used by row reduction algorithms. Even though we support limited arithmetic on them (e.g. composition), permutations are not implemented as expression templates. ``permxx`` wraps the C interface ``perm`` operating on ``slong*``. .. cpp:function:: permxx::permxx(slong n) .. cpp:function:: static permxx permxx::one(slong n) Initialize an identity permutation on the set $[n] = \{0, 1, \dots, n-1\}$. .. cpp:function:: static permxx permxx::randtest(slong n) Generate a random permutation on $[n]$. See ``_perm_randtest``. .. cpp:function:: bool permxx::operator==(const permxx&) .. cpp:function:: bool permxx::operator!=(const permxx&) .. cpp:function:: slong permxx::size() const Return the size of the set being permuted ($n$ in the constructors). .. cpp:function:: slong& operator[](slong i) .. cpp:function:: slong operator[](slong i) const Return the image of $i$ under the permutation. .. cpp:function:: permxx permxx::operator*(const permxx&) .. cpp:function:: permxx compose(const permxx& p1, const permxx& p2) Compute the composition of two permutations. See ``_perm_compose``. .. cpp:function:: void permxx::set_inv(const permxx& o) Set self to the inverse permutation of ``o``. .. cpp:function:: permxx permxx::inv() const .. cpp:function:: permxx inv(const permxx&) Return the inverse permutation. .. cpp:function:: int print(const permxx&) Integers (``fmpz``) =============================================================================== .. type:: fmpzxx C++ particulars ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``sqrt``, ``abs``. .. cpp:function:: Fmpz_expr::binary operation(??) const The following bina.. cpp:functions are made available as member functions: ``cdiv_q``, ``divexact``, ``fdiv_qr``, ``fdiv_r``, ``fdiv_r_2exp``, ``gcd``, ``gcdinv``, ``invmod``, ``lcm``, ``negmod``, ``pow``, ``rfac``, ``root``, ``sqrtmod``, ``tdiv_q``, ``tdiv_q_2exp``, ``tdiv_qr``, ``xgcd``. .. cpp:function:: Fmpz_expr::ternary operation(??, ??) const The following terna.. cpp:functions are made available as member functions: ``divexact2``, ``mul2``, ``mul_tdiv_q_2exp``, ``powm``. Memory management ------------------------------------------------------------------------------- .. cpp:function:: fmpzxx::fmpzxx() Initialize to zero. .. cpp:function:: fmpzxx::fmpzxx(const char*) .. cpp:function:: fmpzxx::fmpzxx(T:is_integer) Initialize from a primitive data type. See ``fmpz_set_str``, ``fmpz_set_si`` and ``fmpz_set_ui``. Random generation ------------------------------------------------------------------------------- .. cpp:function:: static fmpzxx fmpzxx::randbits(frandxx& state) .. cpp:function:: static fmpzxx fmpzxx::randtest(frandxx& state) .. cpp:function:: static fmpzxx fmpzxx::randtest_unsigned(frandxx& state) .. cpp:function:: static fmpzxx fmpzxx::randtest_not_zero(frandxx& state) .. cpp:function:: static fmpzxx fmpzxx::randm(frandxx& state, Fmpz_expr m) .. cpp:function:: static fmpzxx fmpzxx::randtest_mod(frandxx& state, Fmpz_expr m) .. cpp:function:: static fmpzxx fmpzxx::randtest_mod_signed(frandxx& state, Fmpz_expr m) Conversion ------------------------------------------------------------------------------- .. cpp:function:: std::string Fmpz_expr::to_string(int base = 10) const Convert self into a ``string``. See ``fmpz_get_str``. .. cpp:function:: slong Fmpz_expr::to() const Convert self to ``slong``. See ``fmpz_get_si``. .. cpp:function:: ulong Fmpz_expr::to() const Convert self to ``ulong``. See ``fmpz_get_ui``. .. cpp:function:: double Fmpz_expr::to() const Convert self to ``double``. See ``fmpz_get_d``. .. cpp:function:: double Fmpz_expr::get_d_2exp(long& exp) const .. cpp:function:: Fmpz_target Fmpz_target::operator=(const char*) .. cpp:function:: Fmpz_target Fmpz_target::operator=(T:is_integer) See ``fmpz_set_str``, ``fmpz_set_ui`` and ``fmpz_set_si``. .. cpp:function:: void Fmpz_target::set_ui_smod(mp_limb_t x, mv_limb_t m) .. cpp:function:: void Fmpz_target::set_uiui(mp_limb_t x, mv_limb_t m) .. cpp:function:: void Fmpz_target::neg_uiui(mp_limb_t x, mv_limb_t m) Input and output ------------------------------------------------------------------------------- .. cpp:function:: int print(Fmpz_expr) .. cpp:function:: int print(FILE*, Fmpz_expr) .. cpp:function:: int read(Fmpz_target) .. cpp:function:: int read(FILE*, Fmpz_target) Basic properties and manipulation ------------------------------------------------------------------------------- .. cpp:function:: size_t Fmpz_expr::sizeinbase(int) const .. cpp:function:: size_t sizeinbase(Fmpz_expr, int) .. cpp:function:: mp_bitcnt_t Fmpz_expr::bits() const .. cpp:function:: mp_bitcnt_t bits(Fmpz_expr) .. cpp:function:: mp_bitcnt_t Fmpz_expr::size() const .. cpp:function:: mp_bitcnt_t size(Fmpz_expr) .. cpp:function:: mp_bitcnt_t Fmpz_expr::val2() const .. cpp:function:: mp_bitcnt_t val2(Fmpz_expr) .. cpp:function:: int Fmpz_expr::sign() const .. cpp:function:: int sign(Fmpz_expr) .. cpp:function:: void Fmpz_target::set_zero() .. cpp:function:: void Fmpz_target::set_one() .. cpp:function:: bool Fmpz_expr::abs_fits_ui() const .. cpp:function:: bool Fmpz_expr::fits_si() const .. cpp:function:: void Fmpz_target::setbit(ulong) .. cpp:function:: bool Fmpz_expr::tstbit(ulong) const Comparison ------------------------------------------------------------------------------- Relational operators ``<=``, ``>`` etc. are overloaded, where ``e1`` and ``e2`` can be any combination of ``Fmpz_expr`` and ``T:is_integer``. See ``fmpz_cmp``, ``fmpz_cmp_si`` and ``fmpz_cmp_ui``. .. cpp:function:: bool Fmpz_expr::is_zero() const Return if this expression evaluates to zero. .. cpp:function:: bool Fmpz_expr::is_one() const Return if this expression evaluates to one. .. cpp:function:: bool Fmpz_expr::is_pm1() const Return if this expression evaluates to $\pm 1$. .. cpp:function:: bool Fmpz_expr::is_even() const Return if this expression evaluates to an even integer. .. cpp:function:: bool Fmpz_expr::is_odd() const Return if the expression evaluates to an odd integer. Basic arithmetic ------------------------------------------------------------------------------- Arithmetic operators ``+``, ``-``, ``*``, ``/``, ``%``, ``<<`` and ``>>`` are overloaded. See the ``fmpz`` documentation for which argument types are allowed. Symmetric operators with asymmetric type arguments can be used in either order, even if this is not exposed in the C interface. The shift operators wrap ``fmpz_fdiv_q_2exp`` and ``fmpz_mul_2exp``. The division operators use ``fmpz_fdiv``. .. cpp:function:: Fmpz_expr abs(Fmpz_expr) .. cpp:function:: Fmpz_expr mul2_uiui(Fmpz_expr g, ulong x, ulong y) .. cpp:function:: Fmpz_expr cdiv_q(Fmpz_expr, Fmpz_expr) .. cpp:function:: Fmpz_expr cdiv_q(Fmpz_expr, T:is_integer) .. cpp:function:: Fmpz_expr tdiv_q(Fmpz_expr, Fmpz_expr) .. cpp:function:: Fmpz_expr tdiv_q(Fmpz_expr, T:is_integer) .. cpp:function:: Fmpz_expr divexact(Fmpz_expr, Fmpz_expr) .. cpp:function:: Fmpz_expr divexact(Fmpz_expr, T:is_integer) .. cpp:function:: Fmpz_expr fdiv_r(Fmpz_expr, Fmpz_expr) .. cpp:function:: Fmpz_expr tdiv_q_2exp(Fmpz_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_expr fdiv_r_2exp(Fmpz_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_expr divexact2(Fmpz_expr g, ulong x, ulong y) .. cpp:function:: Fmpz_expr mul_tdiv_q_2exp(Fmpz_expr g, Fmpz_expr x, ulong exp) .. cpp:function:: Fmpz_expr mul_tdiv_q_2exp(Fmpz_expr g, long x, ulong exp) .. cpp:function:: Ltuple_expr fdiv_qr(Fmpz_expr g, Fmpz_expr h) .. cpp:function:: Ltuple_expr tdiv_qr(Fmpz_expr g, Fmpz_expr h) .. cpp:function:: bool Fmpz_expr::divisible(Fmpz_expr) const .. cpp:function:: bool Fmpz_expr::divisible(T:fits_into_slong) const .. cpp:function:: bool divisible(Fmpz_expr n, Fmpz_expr d) .. cpp:function:: bool divisible(Fmpz_expr n, T:fits_into_slong d) Return if $d$ divides $n$. See ``fmpz_divisible``. .. cpp:function:: Fmpz_expr powm(Fmpz_expr g, ulong e, Fmpz_expr m) .. cpp:function:: Fmpz_expr powm(Fmpz_expr g, Fmpz_expr e, Fmpz_expr m) .. cpp:function:: Fmpz_expr pow(Fmpz_expr, T:is_unsigned_integer) .. cpp:function:: long clog(Fmpz_expr x, Fmpz_expr b) .. cpp:function:: long clog(Fmpz_expr x, ulong b) .. cpp:function:: long flog(Fmpz_expr x, Fmpz_expr b) .. cpp:function:: long flog(Fmpz_expr x, ulong b) .. cpp:function:: double dlog(Fmpz_expr x) .. cpp:function:: long Fmpz_expr::clog(Fmpz_expr) const .. cpp:function:: long Fmpz_expr::clog(T:is_unsigned_integer) const .. cpp:function:: long Fmpz_expr::flog(Fmpz_expr) const .. cpp:function:: long Fmpz_expr::flog(T:is_unsigned_integer) const .. cpp:function:: double Fmpz_expr::dlog() const .. cpp:function:: Ltuple_expr sqrtmod(Fmpz_expr a, Fmpz_expr b) ``ltupleref(b, N) = sqrtmod(A, B)`` has the same effect as ``b = fmpz_sqrtmod(n, a, b)``, where ``n, a, b`` are the underlying ``fmpz_t`` of ``N, A, B``. .. cpp:function:: Ltuple_expr sqrtrem(Fmpz_expr g) .. cpp:function:: Fmpz_expr sqrt(Fmpz_expr) .. cpp:function:: bool Fmpz_expr::is_square() const Return if this expression evaluates to a square integer. .. cpp:function:: Fmpz_expr root(Fmpz_expr, T:fits_into_slong) .. cpp:function:: Fmpz_expr rfac(Fmpz_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_expr fac(T:is_unsigned_integer) .. cpp:function:: Fmpz_expr fib(T:is_unsigned_integer) .. cpp:function:: Fmpz_expr bin(T:is_unsigned_integer, U:is_unsigned_integer) Greatest common divisor ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr gcdinv(Fmpz_expr f, Fmpz_expr g) .. cpp:function:: Ltuple_expr xgcd(Fmpz_expr f, Fmpz_expr g) .. cpp:function:: Fmpz_expr gcd(Fmpz_expr, Fmpz_expr) .. cpp:function:: Fmpz_expr lcm(Fmpz_expr, Fmpz_expr) Modular arithmetic ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr remove(Fmpzxx a, Fmpzxx b) .. cpp:function:: int jacobi(Fmpz_expr a, Fmpz_expr p) .. cpp:function:: int Fmpz_expr::jacobi(Fmpz_expr) const .. cpp:function:: Fmpz_expr invmod(Fmpz_expr, Fmpz_expr) .. cpp:function:: Fmpz_expr negmod(Fmpz_expr, Fmpz_expr) Bit packing and unpacking ------------------------------------------------------------------------------- Beware that argument orders are different relative to the C interface, to facilitate default arguments. .. cpp:function:: static Fmpz_expr fmpzxx::bit_unpack(const vector& v, mp_bitcnt_t bits, mp_bitcnt_t shift = 0, int negate = 0, bool borrow = false) .. cpp:function:: static Fmpz_expr fmpzxx::bit_unpack_unsigned(const vector& v, mp_bitcnt_t bits, mp_bitcnt_t shift = 0) Unpack an ``fmpzxx`` from ``v``. .. cpp:function:: bool bit_pack(std::vector& v, mp_bitcnt_t bits, Fmpz_expr, mp_bitcnt_t shift = 0, int negate = 0, bool borrow = false) Pack an ``fmpzxx`` to ``v``. The vector ``v`` is required to be of sufficient size. Logic operations ------------------------------------------------------------------------------- Binary logic operators ``& | ^`` (and, or, xor) are also overloaded (implemented when both arguments are ``Fmpz_expr``). .. cpp:function:: void Fmpz_target::clrbit(ulong i) .. cpp:function:: void Fmpz_target::combit(ulong i) .. cpp:function:: int Fmpz_expr::popcnt() const Chinese remaindering ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr Fmpz_expr::CRT(Fmpz_expr, T:is_unsigned_integer, T:is_unsigned_integer, bool) const .. cpp:function:: Fmpz_expr CRT(Fmpz_expr, Fmpz_expr, T:is_unsigned_integer, T:is_unsigned_integer, bool) See ``fmpz_CRT_ui``. .. cpp:function:: fmpz_combxx::fmpz_combxx(const std::vector& primes) The class ``fmpz_combxx`` wraps both ``fmpz_comb_t`` and ``fmpz_comb_temp_t``. The argument ``primes`` is the vector of moduli to use, and must not be deallocated before the newly constructed ``fmpz_combxx``. Note that the internal ``fmpz_comb_temp_t`` structure may be modified even on constant instances of ``fmpz_combxx``. .. cpp:function:: void multi_mod(std::vector& out, Fmpz_expr in, const fmpz_combxx& comb) Reduce ``in`` modulo the primes stored in ``comb``, and store the results in ``out``. The vector ``out`` must have sufficient size, and its size will not be changed. .. cpp:function:: Fmpz_expr multi_CRT(const std::vector& residues, const fmpz_combxx comb, bool sign) Reconstruct an integer from its residues. See ``fmpz_multi_CRT_ui``. Primality testing ------------------------------------------------------------------------------- .. cpp:function:: bool Fmpz_expr::is_probabprime() const .. cpp:function:: bool Fmpz_expr::is_prime_pseudosquare() const Integer factoring (``fmpz_factor``) =============================================================================== .. cpp:function:: fmpz_factorxx::fmpz_factorxx() Initialise an empty factorisation. .. cpp:function:: fmpz_factorxx::fmpz_factorxx(const fmpz_factorxx& o) Copy a factorisation. .. cpp:function:: bool fmpz_factorxx::operator==(const fmpz_factorxx&) Compare two factorisations. .. cpp:function:: ulong fmpz_factorxx::size() const Return the number of stored factors. .. cpp:function:: ulong fmpz_factorxx::exp(slong i) const .. cpp:function:: ulong& fmpz_factorxx::exp(slong i) Obtain the exponent of the ith factor. .. cpp:function:: fmpzxx_srcref fmpz_factorxx::p(slong i) const .. cpp:function:: fmpzxx_ref fmpz_factorxx::p(slong i) Obtain the ith factor. .. cpp:function:: int fmpz_factorxx::sign() const .. cpp:function:: int& fmpz_factorxx::sign() Obtain the sign of the factored expression. .. cpp:function:: void fmpz_factorxx::set_factor(Fmpz_expr) .. cpp:function:: void fmpz_factorxx::set_factor(T:fits_into_slong) .. cpp:function:: bool fmpz_factorxx::set_factor_trial_range(Fmpz_expr, ulong, ulong) .. cpp:function:: bool fmpz_factorxx::set_factor_pp1(Fmpz_expr, ulong, ulong, ulong) Factorise an integer and store its factors. See ``fmpz_factor`` etc. .. cpp:function:: Fmpz_expr fmpz_factorxx::expand() const .. cpp:function:: Fmpz_expr fmpz_factorxx::expand_iterative() const .. cpp:function:: Fmpz_expr fmpz_factorxx::expand_multiexp() const .. cpp:function:: fmpz_factorxx factor(Fmpz_expr) .. cpp:function:: fmpz_factorxx factor(T:fits_into_slong) .. cpp:function:: Ltuple_expr factor_trial_range(Fmpz_expr) .. cpp:function:: fmpz_factorxx factor_pp1(Fmpz_expr) .. cpp:function:: void print(const fmpz_factorxx&) Integer matrices (``fmpz_mat``) =============================================================================== .. type:: fmpz_matxx The class ``fmpz_matxx`` wraps ``fmpz_mat_t``, and so represents matrices with coefficients in $\mathbf{Z}$. Owing to the design of ``fmpz_mat_t``, the use of ``fmpz_matxx`` has a number of peculiarities. - Matrix assignment does not automatically resize. This also includes assigning (and thus evaluating) a lazy expression to an ordinary matrix. As a consequence, the evaluation code cannot use temporary merging, and may thus create more temporaries than a similar expression involving non-matrices. - Sever.. cpp:functions operating on ``fmpz_mat_t`` do not allow aliasing. The flintxx layer just passes expressions on to the C layer, so it is the responsibility of the user to avoid aliasing where it is disallowed. Note that since no temporary merging is used with matrices, aliases are never introduced by the evaluation code. Miscellaneous ------------------------------------------------------------------------------- .. cpp:function:: slong Fmpz_mat_expr::rank() const .. cpp:function:: Fmpz_expr Fmpz_mat_expr::det_modular_given_divisor( Fmpz_mat_expr, Fmpz_expr) const See ``fmpz_mat_det_modular_given_divisor``. .. cpp:function:: Fmpz_mat_target Fmpz_mat_target::operator=(T:fits_into_slong) .. cpp:function:: Fmpz_mat_target Fmpz_mat_target::operator=(const char*) C++ particulars ------------------------------------------------------------------------------- .. cpp:function:: slong Fmpz_mat_expr::rows() const .. cpp:function:: slong Fmpz_mat_expr::cols() const Obtain the number of rows/columns in this matrix. The.. cpp:functions never cause evaluation (the matrix size is computed from the operations in the expression template and the size of the input matrices). .. cpp:function:: Fmpz_mat_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``sqr``, ``charpoly``, ``det``, ``det_bareiss``, ``det_bound``, ``det_cofactor``, ``det_divisor``, ``trace``, ``transpose``. .. cpp:function:: Fmpz_mat_expr::binary operation(??) const The following bina.. cpp:functions are made available as member functions: ``det_modular``, ``det_modular_accelerated``, ``divexact``, ``mul_classical``, ``mul_multi_mod``, ``pow``, code{solve}, ``solve_bound``, ``solve_cramer``, ``solve_dixon``, ``solve_fflu``. Memory management ------------------------------------------------------------------------------- .. cpp:function:: fmpz_matxx::fmpz_matxx(slong i, slong j) Allocate a matrix of size $i \times j$. Basic assignment and manipulation ------------------------------------------------------------------------------- .. cpp:function:: ?? Fmpz_mat_expr::at(T:fits_into_slong, U:fits_into_slong) const Unified coefficient access to the matrix entries. .. cpp:function:: void Fmpq_mat_target::set_zero() .. cpp:function:: void Fmpq_mat_target::set_one() .. cpp:function:: static fmpq_matxx fmpq_matxx::zero(slong rows, slong cols) .. cpp:function:: static fmpq_matxx fmpq_matxx::one(slong rows, slong cols) Input and output ------------------------------------------------------------------------------- .. cpp:function:: print(Fmpz_mat_expr) .. cpp:function:: print(FILE*, Fmpz_mat_expr) .. cpp:function:: print_pretty(Fmpz_mat_expr) .. cpp:function:: print_pretty(FILE*, Fmpz_mat_expr) .. cpp:function:: read(Fmpz_mat_target) .. cpp:function:: read(FILE*, Fmpz_mat_target) Comparison ------------------------------------------------------------------------------- The overloaded operator ``==`` can be used for equality testing. Additionally, we have the followi.. cpp:functions. .. cpp:function:: bool Fmpz_mat_expr::is_empty() const .. cpp:function:: bool Fmpz_mat_expr::is_quare() const Conversion ------------------------------------------------------------------------------- .. cpp:function:: static fmpz_matxx fmpz_matxx::lift(Nmod_mat_expr) .. cpp:function:: static fmpz_matxx fmpz_matxx::lift_unsigned(Nmod_mat_expr) See ``fmpz_mat_set_nmod_mat`` and ``fmpz_mat_set_nmod_mat_unsigned``. .. cpp:function:: static fmpz_matxx fmpz_matxx::reduce(Fmpq_mat_expr, Fmz_expr) See ``fmpq_mat_get_fmpz_mat_mod_fmpz``. .. cpp:function:: static fmpz_matxx fmpz_matxx::from_integral_fraction(Fmpq_mat_expr) .. cpp:function:: void Fmpz_mat_target::set_integral_fraction(Fmpq_mat_expr) See ``fmpq_mat_get_fmpz_mat``. Raises ``flint_exception`` if the argument has non-integer entries. Randomisation ------------------------------------------------------------------------------- .. cpp:function:: void Fmpz_mat_target::set_randbits(frandxx& state, mp_bitcnt_t bits) .. cpp:function:: void Fmpz_mat_target::set_randtest(frandxx& state, mp_bitcnt_t bits) .. cpp:function:: void Fmpz_mat_target::set_randintrel(frandxx& state, mp_bitcnt_t bits) .. cpp:function:: void Fmpz_mat_target::set_randsimdioph(frandxx& state, mp_bitcnt_t bits, mp_bitcount_t bits2) .. cpp:function:: void Fmpz_mat_target::set_randtrulike(frandxx& state, mp_bitcnt_t bits, ulong q) .. cpp:function:: void Fmpz_mat_target::set_randtrulike2(frandxx& state, mp_bitcnt_t bits, ulong q) .. cpp:function:: void Fmpz_mat_target::set_randajtai(frandxx& state, mp_bitcnt_t bits, double alpha) .. cpp:function:: void Fmpz_mat_target::set_randrank(frandxx& state, slong rank, mp_bitcnt_t bits) .. cpp:function:: void Fmpz_mat_target::set_randdet(frandxx& state, Fmpz_expr d) See ``fmpz_mat_randbits`` etc. .. cpp:function:: static fmpz_matxx fmpz_matxx::randbits(slong r, slong c, frandxx& state, mp_bitcnt_t bits) .. cpp:function:: static fmpz_matxx fmpz_matxx::randtest(slong r, slong c, frandxx& state, mp_bitcnt_t bits) .. cpp:function:: static fmpz_matxx fmpz_matxx::randintrel(slong r, slong c, frandxx& state, mp_bitcnt_t bits) .. cpp:function:: static fmpz_matxx fmpz_matxx::randsimdioph(slong r, slong c, frandxx& state, mp_bitcnt_t bits, mp_bitcount_t bits2) .. cpp:function:: static fmpz_matxx fmpz_matxx::randtrulike(slong r, slong c, frandxx& state, mp_bitcnt_t bits, ulong q) .. cpp:function:: static fmpz_matxx fmpz_matxx::randtrulike2(slong r, slong c, frandxx& state, mp_bitcnt_t bits, ulong q) .. cpp:function:: static fmpz_matxx fmpz_matxx::randajtai(slong r, slong c, frandxx& state, mp_bitcnt_t bits, double alpha) .. cpp:function:: static fmpz_matxx fmpz_matxx::randrank(slong r, slong c, frandxx& state, slong rank, mp_bitcnt_t bits) .. cpp:function:: static fmpz_matxx fmpz_matxx::randdet(slong r, slong c, frandxx& state, Fmpz_expr d) Static versions of the above, where the first two arguments specify the dimensions of the matrix. .. cpp:function:: int Fmpz_mat_target::set_randpermdiag(frandxx& state, Vec v) See ``fmpz_mat_randpermdiag``. The type ``vec`` must have methods ``_array()`` and ``size()`` similar to ``fmpz_vecxx``. .. cpp:function:: void Fmpz_mat_target::apply_randops(frandxx& state, slong count) See ``fmpz_mat_randops``. Transpose ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr transpose(Fmpz_mat_expr) Modular reduction and reconstruction ------------------------------------------------------------------------------- To reduce a single matrix modulo a word-sized modulus, see ``nmod_matxx::reduce``. We use a special class ``nmod_mat_vector`` to represent a vector of matrices reduced with respect to differing moduli. .. cpp:function:: Fmpz_mat_expr CRT(Fmpz_mat_expr, Fmpz_expr, Nmod_mat_expr, bool) See ``fmpz_mat_CRT_ui``. .. cpp:function:: nmod_mat_vector::nmod_mat_vector(slong rows, slong cols, const std::vector& primes) Initialize a vector of matrices with dimensions given by ``rows``, ``cols`` and moduli given by ``primes``. .. cpp:function:: nmod_matxx_ref nmod_mat_vector::operator[](std::size_t idx) .. cpp:function:: nmod_matxx_srcref nmod_mat_vector::operator[](std::size_t idx) const Obtain a reference to one of the stored matrices. .. cpp:function:: std::size_t nmod_mat_vector::size() const Obtain the number of stored matrices. .. cpp:function:: void nmod_mat_vector::set_multi_mod(Fmpz_mat_expr m) Reduce ``m`` modulo each of the primes stored in this vector, and store the results. See ``fmpz_mat_multi_mod_ui``. .. cpp:function:: void nmod_mat_vector::set_multi_mod_precomp(Fmpz_mat_expr m, const fmpz_combxx& comb) Reduce ``m`` modulo each of the primes stored in this vector, and store the results. Use precomputed data in ``comp``. See ``fmpz_mat_multi_mod_ui_precomp``. .. cpp:function:: nmod_mat_vector multi_mod(Fmpz_mat_expr m, const std::vector& primes) .. cpp:function:: nmod_mat_vector multi_mod_precomp(Fmpz_mat_expr m, const std::vector& primes, const fmpz_combxx& comb) Convenien.. cpp:functions combining the allocation of memory and modular reduction. Arithmetic ------------------------------------------------------------------------------- The overloaded operators ``+ - *`` can be used for ordinary matrix-matrix and matrix-scalar arithmetic. Additionally, we provide the followi.. cpp:functions. .. cpp:function:: Fmpz_mat_expr divexact(Fmpz_mat_expr, Fmpz_expr) .. cpp:function:: Fmpz_mat_expr divexact(Fmpz_mat_expr, T:is_integer) .. cpp:function:: Fmpz_mat_expr mul_classical(Fmpz_mat_expr, Fmpz_mat_expr) .. cpp:function:: Fmpz_mat_expr mul_multi_mod(Fmpz_mat_expr, Fmpz_mat_expr) .. cpp:function:: Fmpz_expr sqr(Fmpz_mat_expr) .. cpp:function:: Fmpz_mat_expr pow(Fmpz_mat_expr, T:is_unsigned_integer) Inverse ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr inv(Fmpz_mat_expr) ``ltupleref(b, M, D) = inv(A)`` has the same effect as ``b = fmpz_mat_inv(m, d, a)``, where ``m, d, a`` are the underlying C objects corresponding to ``M, D, A``. Trace ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_mat_expr trace(Fmpz_mat_expr) Determinant ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr det(Fmpz_mat_expr) .. cpp:function:: Fmpz_expr det_cofactor(Fmpz_mat_expr) .. cpp:function:: Fmpz_expr det_bareiss(Fmpz_mat_expr) .. cpp:function:: Fmpz_expr det_divisor(Fmpz_mat_expr) .. cpp:function:: Fmpz_expr det_bound(Fmpz_mat_expr) .. cpp:function:: Fmpz_expr det_modular(Fmpz_mat_expr, bool proved) .. cpp:function:: Fmpz_expr det_modular_accelerated(Fmpz_mat_expr, bool proved) .. cpp:function:: Fmpz_expr det_modular_given_divisor(Fmpz_mat_expr, Fmpz_expr, bool proved) Characteristic polynomial ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr charpoly(Fmpz_mat_expr) Rank ------------------------------------------------------------------------------- .. cpp:function:: slong rank(Fmpz_mat_expr) Non-singular solving ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr solve(Fmpz_mat_expr B, Fmpz_mat_expr X) .. cpp:function:: Ltuple_expr solve_dixon(Fmpz_mat_expr B, Fmpz_mat_expr X) .. cpp:function:: Ltuple_expr solve_cramer(Fmpz_mat_expr B, Fmpz_mat_expr X) .. cpp:function:: Ltuple_expr solve_fflu(Fmpz_mat_expr B, Fmpz_mat_expr X) ``ltupleref(w, M, D) = solve(B, X)`` has the same effect as ``w = fmpz_mat_solve(m, d, b, x)``, where ``m, d, b, x`` are the underlying C objects corresponding to ``M, D, B, X``. Similarly for the oth.. cpp:functions. .. cpp:function::Ltuple_expr solve_bound(Fmpz_mat_expr B, Fmpz_mat_expr X) Row reduction ------------------------------------------------------------------------------- Beware that compared to the C interface, the flintxx row reduction interface changes some argument orders. This is to facilitate default arguments. .. cpp:function:: slong find_pivot_any(Fmpz_mat_expr, slong, slong, slong) See ``fmpz_mat_find_pivot_any``. .. cpp:function:: Ltuple_expr fflu(Fmpz_mat_expr A, permxx* perm = 0, bool rankcheck = false) See ``fmpz_mat_fflu``. .. cpp:function:: Ltuple_expr rref(Fmpz_mat_expr A) See ``fmpz_mat_rref``. Modular gaussian elimination ------------------------------------------------------------------------------- .. cpp:function:: slong Fmpz_mat_target::set_rref_mod(Fmpz_expr n, permxx* perm = 0) See ``fmpz_mat_rref_mod``. Nullspace ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr nullspace(Fmpz_mat_expr A) ``ltupleref(n, B) = nullspace(A)`` has the same effect as ``n = fmpz_mat_nullspace(b, a)``, where ``b, a`` are the underlying ``fmpz_mat_t`` corresponding to ``B, A``. Polynomials over the integers (``fmpz_polyxx``) =============================================================================== C++ particulars ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``derivative``, ``primitive_part``, ``sqr``, ``sqr_classical``, ``sqr_karatsuba``, ``sqr_KS``, ``sqrt``, ``sqrt_classical``, ``content``, ``height``, ``bound_roots``, ``twonorm``. .. cpp:function:: Fmpz_poly_expr::binary operation(??) const The following bina.. cpp:functions are made available as member functions: ``compose_divconquer``, ``compose_horner``, ``div_basecase``, ``div_divconquer``, ``divexact``, ``divrem``, ``divrem_basecase``, ``divrem_divconquer``, ``div_root``, ``evaluate_divconquer``, ``evaluate_horner``, ``fdiv_2exp``, ``gcd``, ``gcd_heuristic``, ``gcd_modular``, ``gcd_subresultant``, ``inv_series``, ``inv_series_newton``, ``lcm``, ``mul_2exp``, ``mul_classical``, ``mul_karatsuba``, ``mul_KS``, ``mulmid_classical``, ``mul_SS``, ``shift_left``, ``shift_right``, ``pow``, ``pow_addchains``, ``pow_binexp``, ``pow_binomial``, ``pow_multinomial``, ``pseudo_div``, ``pseudo_divrem``, ``pseudo_divrem_basecase``, ``pseudo_divrem_cohen``, ``pseudo_divrem_divconquer``, ``pseudo_rem``, ``pseudo_rem_cohen``, ``resultant``, ``reverse``, ``revert_series``, ``revert_series_lagrange``, ``revert_series_lagrange_fast``, ``revert_series_newton``, ``smod``, ``sqrlow``, ``sqrlow_classical``, ``sqrlow_karatsuba_n``, ``sqrlow_KS``, ``taylor_shift``, ``taylor_shift_horner``, ``taylor_shift_divconquer``, ``tdiv``, ``tdiv_2exp``, ``xgcd``, ``xgcd_modular``, ``divides``. .. cpp:function:: Fmpz_poly_expr::ternary operation(??, ??) const The following terna.. cpp:functions are made available as member functions: ``compose_series``, ``compose_series_brent_kung``, ``compose_horner``, ``div_series``, ``mulhigh_classical``, ``mulhigh_karatsuba_n``, ``mulhigh_n``, ``mullow``, ``mullow_classical``, ``mullow_karatsuba_n``, ``mullow_KS``, ``mullow_SS``, ``pow_trunc``. .. cpp:function:: Fmpz_poly_expr Fmpz_poly_expr::operator()(Fmpz_poly_expr) const .. cpp:function:: Fmpz_poly_expr Fmpz_poly_expr::operator()(Fmpz_expr) const Overloaded ``operator()`` for evaluation or composition. Memory management ------------------------------------------------------------------------------- .. cpp:function:: fmpz_polyxx::fmpz_polyxx() .. cpp:function:: fmpz_polyxx::fmpz_polyxx(slong alloc) See ``fmpz_poly_init2``. .. cpp:function:: fmpz_polyxx::fmpz_polyxx(const char* str) See ``fmpz_poly_set_str``. .. cpp:function:: void Fmpz_poly_target realloc(slong alloc) .. cpp:function:: void Fmpz_poly_target::fit_length(slong len) .. cpp:function:: void Fmpz_poly_target::_normalise() .. cpp:function:: void Fmpz_poly_target::_set_length(slong len) Polynomial parameters ------------------------------------------------------------------------------- .. cpp:function:: slong Fmpz_poly_expr::length() const .. cpp:function:: slong Fmpz_poly_expr::degree() const Assignment and basic manipulation ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_target Fmpz_poly_target::operator=(T:is_integer) .. cpp:function:: Fmpz_poly_target Fmpz_poly_target::operator=(Fmpz_expr) .. cpp:function:: Fmpz_poly_target Fmpz_poly_target::operator=(const char*) .. cpp:function:: std::string Fmpz_poly_expr::to_string() const .. cpp:function:: std::string Fmpz_poly_expr::pretty(const char* x) const See ``fmpz_poly_get_str_pretty``. .. cpp:function:: void Fmpz_poly_target::set_zero() .. cpp:function:: void Fmpz_poly_target::set_one() .. cpp:function:: static fmpz_polyxx fmpz_polyxx::zero() .. cpp:function:: static fmpz_polyxx fmpz_polyxx::one() .. cpp:function:: void Fmpz_poly_target::zero_coeffs(slong i, slong j) .. cpp:function:: Fmpz_poly_expr reverse(Fmpz_poly_expr, T:fits_into_slong) .. cpp:function:: void Fmpz_poly_target::truncate(slong) Randomisation ------------------------------------------------------------------------------- .. cpp:function:: static fmpz_polyxx fmpz_polyxx::randtest(frandxx& state, slong len, mp_bitcnt_t bits) .. cpp:function:: static fmpz_polyxx fmpz_polyxx::randtest_unsigned(frandxx& state, slong len, mp_bitcnt_t bits) .. cpp:function:: static fmpz_polyxx fmpz_polyxx::randtest_not_zero(frandxx& state, slong len, mp_bitcnt_t bits) See ``fmpz_poly_randtest`` etc. Getting and setting coefficients ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr Fmpz_poly_expr::get_coeff(slong n) Obtain coefficient $n$ of the polynomial. It is valid to call this with $n$ greater than the degree, in which case zero is returned. .. cpp:function:: void Fmpz_poly_target::set_coeff(slong n, Fmpz_expr) .. cpp:function:: void Fmpz_poly_target::set_coeff(slong n, T:is_integer) .. cpp:function:: ?? Fmpz_poly_expr::coeff(slong n) const Unified coefficient access for coefficient $n$. The result is undefined if $n$ is greater than the degree of the polynomial (or negative). If the leading coefficient of the polynomial is set to zero in this way, a call to ``_normalise`` is necessary. .. cpp:function:: ?? Fmpz_poly_expr::lead() const Unified coefficient access for the leading coefficient. The result is undefined if the length of the polynomial is zero. If this is used to set the leading coefficient to zero, call to ``_normalise`` is necessary. Comparison ------------------------------------------------------------------------------- As usual, ``fmpz_polyxx`` can be compared using ``operator==``. Additionally, the followi.. cpp:functions are provided. .. cpp:function:: bool Fmpz_poly_expr::is_one() const .. cpp:function:: bool Fmpz_poly_expr::is_zero() const .. cpp:function:: bool Fmpz_poly_expr::is_unit() const Addition and subtraction ------------------------------------------------------------------------------- The overloaded operators ``+ -`` can be used for addition, subtraction and negation. Scalar multiplication and division ------------------------------------------------------------------------------- The overloaded operators ``* /`` can be used for scalar multiplication and division, and the operator \code{\%} for remaindering. For finer control, the followi.. cpp:functions are provided. .. cpp:function:: Fmpz_poly_expr mul_2exp(Fmpz_poly_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_poly_expr fdiv_2exp(Fmpz_poly_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_poly_expr tdiv(Fmpz_poly_expr, Fmpz_expr) .. cpp:function:: Fmpz_poly_expr tdiv(Fmpz_poly_expr, T:is_integer) .. cpp:function:: Fmpz_poly_expr divexact(Fmpz_poly_expr, Fmpz_expr) .. cpp:function:: Fmpz_poly_expr divexact(Fmpz_poly_expr, T:is_integer) .. cpp:function:: Fmpz_poly_expr smod(Fmpz_poly_expr, Fmpz_expr) See ``fmpz_poly_scalar_smod_fmpz``. Bit packing ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr bit_pack(Fmpz_poly_expr, T:fits_into_mp_bitcnt_t) .. cpp:function:: static Fmpz_poly_expr fmpz_polyxx::bit_unpack(Fmpz_expr, T:fits_into_mp_bitcnt_t) .. cpp:function:: static Fmpz_poly_expr fmpz_polyxx::bit_unpack_unsigned(Fmpz_expr, traits::fits_into_mp_bitcnt_t) Multiplication ------------------------------------------------------------------------------- The overloaded operator ``*`` can also be used for poly-poly multiplication. Additionally, the followi.. cpp:functions are provided. .. cpp:function:: Fmpz_poly_expr mul_classical(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr mulmid_classical(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr mul_karatsuba(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr mul_SS(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr mul_KS(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr mullow(Fmpz_poly_expr, Fmpz_poly_expr, slong) .. cpp:function:: Fmpz_poly_expr mullow_classical(Fmpz_poly_expr, Fmpz_poly_expr, slong) .. cpp:function:: Fmpz_poly_expr mullow_karatsuba_n(Fmpz_poly_expr, Fmpz_poly_expr, slong) .. cpp:function:: Fmpz_poly_expr mullow_KS(Fmpz_poly_expr, Fmpz_poly_expr, slong) .. cpp:function:: Fmpz_poly_expr mullow_SS(Fmpz_poly_expr, Fmpz_poly_expr, slong) .. cpp:function:: Fmpz_poly_expr mulhigh_n(Fmpz_poly_expr, Fmpz_poly_expr, slong) .. cpp:function:: Fmpz_poly_expr mulhigh_classical(Fmpz_poly_expr, Fmpz_poly_expr, slong) .. cpp:function:: Fmpz_poly_expr mulhigh_karatsuba_n(Fmpz_poly_expr, Fmpz_poly_expr, slong) Squaring ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr sqr(Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr sqr_KS(Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr sqr_karatsuba(Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr sqr_classical(Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr sqrlow(Fmpz_poly_expr, T:fits_into_slong n) .. cpp:function:: Fmpz_poly_expr sqrlow_classical(Fmpz_poly_expr, T:fits_into_slong n) .. cpp:function:: Fmpz_poly_expr sqrlow_KS(Fmpz_poly_expr, T:fits_into_slong n) .. cpp:function:: Fmpz_poly_expr sqrlow_karatsuba_n(Fmpz_poly_expr, T:fits_into_slong n) Powering ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr pow(Fmpz_poly_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_poly_expr pow_multinomial(Fmpz_poly_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_poly_expr pow_binomial(Fmpz_poly_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_poly_expr pow_binexp(Fmpz_poly_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_poly_expr pow_addchains(Fmpz_poly_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_poly_expr pow_trunc(Fmpz_poly_expr, ulong e, slong n) Shifting ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr shift_left(Fmpz_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpz_poly_expr shift_right(Fmpz_poly_expr, T:fits_into_slong) Bit sizes and norms ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr height(Fmpz_poly_expr) .. cpp:function:: Fmpz_expr twonorm(Fmpz_poly_expr) .. cpp:function:: ulong Fmpz_poly_expr::max_limbs() const .. cpp:function:: slong Fmpz_poly_expr::max_bits() const Greatest common divisor ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr gcd(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr gcd_subresultant(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr gcd_heuristic(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr gcd_modular(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr lcm(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Ltuple_expr xgcd(Fmpz_poly_expr f, Fmpz_poly_expr g) .. cpp:function:: Ltuple_expr xgcd_modular(Fmpz_poly_expr f, Fmpz_poly_expr g) ``ltupleref(N, Q, R) = xgcd(F, G)`` has the same effect as ``fmpz_poly_xgcd(n, q, r, f, g)`` where ``n, q, r, f, g`` are the underlying C objects. .. cpp:function:: Fmpz_expr resultant(Fmpz_poly_expr) Gaussian content ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr content(Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr primitive_part(Fmpz_poly_expr) Square-free ------------------------------------------------------------------------------- .. cpp:function:: bool Fmpz_poly_expr::is_squarefree() const Euclidean division ------------------------------------------------------------------------------- The overloaded operators ``/ %`` can be used for euclidean division and remainder. Additionally, the followi.. cpp:functions are provided. .. cpp:function:: Fmpz_poly_expr div_basecase(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr div_divconquer(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr rem_basecase(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Ltuple_expr divrem(Fmpz_poly_expr A, Fmpz_poly_expr B) .. cpp:function:: Ltuple_expr divrem_basecase(Fmpz_poly_expr A, Fmpz_poly_expr B) .. cpp:function:: Ltuple_expr divrem_divconquer(Fmpz_poly_expr A, Fmpz_poly_expr B) ``ltupleref(Q, R) = divrem(A, B)`` has the same effect as ``fmpz_poly_divrem(q, r, a, b)``, where ``q, r, a, b`` are the underlying ``fmpz_poly_t`` corresponding to ``Q, R, A, B``. .. cpp:function:: Fmpz_poly_expr div_root(Fmpz_poly_expr, Fmpz_expr) Divisibility testing ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr divides(Fmpz_poly_expr A, Fmpz_poly_expr B) ``ltupleref(d, Q) = divides(A, B)`` sets ``d`` to ``true`` and ``Q`` to ``A/B`` if ``B`` divides ``A``, and else sets ``d`` to ``false``. See ``fmpz_poly_divides``. Power series division ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr inv_series_newton(Fmpz_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpz_poly_expr inv_series(Fmpz_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpz_poly_expr div_series(Fmpz_poly_expr, Fmpz_poly_expr, slong n) Pseudo division ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr pseudo_divrem(Fmpz_poly_expr A, Fmpz_poly_expr B) .. cpp:function:: Ltuple_expr pseudo_divrem_basecase(Fmpz_poly_expr A, Fmpz_poly_expr B) .. cpp:function:: Ltuple_expr pseudo_divrem_divconquer(Fmpz_poly_expr A, Fmpz_poly_expr B) ``ltupleref(Q, R, d) = pseudo_divrem(A, B)`` has the same effect as\\ ``fmpz_poly_pseudo_divrem(q, r, &d, a, b)``, where ``q, r, a, b`` are the underlying ``fmpz_poly_t`` corresponding to ``Q, R, A, B``. .. cpp:function:: Ltuple_expr pseudo_divrem_cohen(Fmpz_poly_expr A, Fmpz_poly_expr B) ``ltupleref(Q, R) = pseudo_divrem_cohen(A, B)`` has the same effect as\\ ``fmpz_poly_pseudo_divrem_cohen(q, r, a, b)``, where ``q, r, a, b`` are the underlying ``fmpz_poly_t`` corresponding to ``Q, R, A, B``. .. cpp:function:: Ltuple_expr pseudo_div(Fmpz_poly_expr A, Fmpz_poly_expr B) .. cpp:function:: Ltuple_expr pseudo_rem(Fmpz_poly_expr A, Fmpz_poly_expr B) ``ltupleref(Q, d) = pseudo_div(A, B)`` has the same effect as ``fmpz_poly_pseudo_div(q, &d, a, b)``, where ``q, a, b`` are the underlying ``fmpz_poly_t`` corresponding to ``Q, A, B``. .. cpp:function:: Fmpz_poly_expr pseudorem_cohen(Fmpz_poly_expr, Fmpz_poly_expr) Derivative ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr derivative(Fmpz_poly_expr) Evaluation ------------------------------------------------------------------------------- The overloaded ``operator()`` can be used for evaluation. Additionally, the followi.. cpp:functions are provided. .. cpp:function:: Fmpz_expr evaluate(Fmpz_poly_expr, Fmpz_expr) .. cpp:function:: Fmpz_vec_expr evaluate(Fmpz_poly_expr, Fmpz_vec_expr) .. cpp:function:: Fmpz_expr evaluate_horner(Fmpz_poly_expr, Fmpz_expr) .. cpp:function:: Fmpz_expr evaluate_divconquer(Fmpz_poly_expr, Fmpz_expr) .. cpp:function:: mp_limb_t evaluate_mod(Fmpz_poly_expr p, mp_limb_t x, mp_limb_t n) Interpolation ------------------------------------------------------------------------------- .. cpp:function:: static Fmpz_poly_expr fmpz_polyxx::interpolate(Fmpz_vec_expr xs, Fmpz_vec_expr ys) See ``fmpz_poly_interpolate_fmpz_vec``. Composition. ------------------------------------------------------------------------------- The overloaded ``operator()`` can be used for composition. Additionally, the followi.. cpp:functions are provided. .. cpp:function:: Fmpz_poly_expr compose(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr compose_horner(Fmpz_poly_expr, Fmpz_poly_expr) .. cpp:function:: Fmpz_poly_expr compose_divconquer(Fmpz_poly_expr, Fmpz_poly_expr) Taylor shift ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr taylor_shift(Fmpz_poly_expr, Fmpz_expr) .. cpp:function:: Fmpz_poly_expr taylor_shift_horner(Fmpz_poly_expr, Fmpz_expr) .. cpp:function:: Fmpz_poly_expr taylor_shift_divconquer(Fmpz_poly_expr, Fmpz_expr) Power series composition ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr compose_series(Fmpz_poly_expr, Fmpz_poly_expr, slong) .. cpp:function:: Fmpz_poly_expr compose_series_horner(Fmpz_poly_expr, Fmpz_poly_expr, slong) .. cpp:function:: Fmpz_poly_expr compose_series_brent_kung(Fmpz_poly_expr, Fmpz_poly_expr, slong) Power series reversion ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr revert_series(Fmpz_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpz_poly_expr revert_series_newton(Fmpz_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpz_poly_expr revert_series_lagrange(Fmpz_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpz_poly_expr revert_series_lagrange_fast(Fmpz_poly_expr, T:fits_into_slong) Square root ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr sqrt(Fmpz_poly_expr p) .. cpp:function:: Fmpz_poly_expr sqrt_classical(Fmpz_poly_expr p) Compute the square root of ``p``, provided ``p`` is a perfect square. Else raise ``flint_exception``. See ``fmpz_poly_sqrt``. Signature ------------------------------------------------------------------------------- .. cpp:function:: void Fmpz_poly_expr::signature(slong& r1, slong& r2) const See ``fmpz_poly_signature``. Hensel lifting ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr hensel_lift(Fmpz_poly_expr f, Fmpz_poly_expr g, Fmpz_poly_expr h, Fmpz_poly_expr a, Fmpz_poly_expr b, Fmpz_expr p, Fmpz_expr p1) .. cpp:function:: Ltuple_expr hensel_lift_without_inverse(Fmpz_poly_expr f, Fmpz_poly_expr g, Fmpz_poly_expr h, Fmpz_poly_expr a, Fmpz_poly_expr b, Fmpz_expr p, Fmpz_expr p1) .. cpp:function:: Ltuple_expr hensel_lift_only_inverse(Fmpz_poly_expr G, Fmpz_poly_expr H, Fmpz_poly_expr a, Fmpz_poly_expr b, Fmpz_expr p, Fmpz_expr p1) See ``fmpz_poly_hensel_lift`` etc. .. cpp:function:: fmpz_poly_factorxx::set_hensel_lift_once(Fmpz_poly_expr, const nmod_poly_factorxx&, slong) .. cpp:function:: fmpz_poly_factorxx hensel_lift_once(Fmpz_poly_expr, const nmod_poly_factorxx&, slong) See ``fmpz_poly_hensel_lift_once``. Note that these two .. cpp:functions are defined in the ``fmpz_factorxx`` module. Input and output ------------------------------------------------------------------------------- .. cpp:function:: print(Fmpz_poly_expr) .. cpp:function:: print(FILE*, Fmpz_poly_expr) .. cpp:function:: print_pretty(Fmpz_poly_expr, const char* var) .. cpp:function:: print_pretty(FILE*, Fmpz_poly_expr, const char* var) .. cpp:function:: read(Fmpz_poly_target) .. cpp:function:: read(FILE*, Fmpz_poly_target) .. cpp:function:: read_pretty(Fmpz_poly_target, const char* var) .. cpp:function:: read_pretty(FILE*, Fmpz_poly_target, const char* var) Modular reduction and reconstruction ------------------------------------------------------------------------------- For modular reduction, see ``nmod_polyxx::reduce``. .. cpp:function:: Fmpz_poly_expr Fmpz_poly_expr::CRT(Fmpz_expr, Nmod_poly_expr, bool) .. cpp:function:: Fmpz_poly_expr CRT(Fmpz_poly_expr, Fmpz_expr, Nmod_poly_expr, bool) See ``fmpz_poly_CRT_ui``. Products ------------------------------------------------------------------------------- .. cpp:function:: static Fmpz_poly_expr fmpz_polyxx::product_roots(Fmpz_vec_expr xs) See ``fmpz_poly_product_roots_fmpz_vec``. Roots ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr bound_roots(Fmpz_poly_expr p) Factorisation of polynomials over the integers (``fmpz_poly_factorxx``) =============================================================================== Miscellaneous ------------------------------------------------------------------------------- .. cpp:function:: bool fmpz_poly_factorxx::operator==(const fmpz_poly_factorxx&) Compare two factorisations. .. cpp:function:: ulong fmpz_poly_factorxx::size() const Return the number of stored factors. .. cpp:function:: slong fmpz_poly_factorxx::exp(slong i) const .. cpp:function:: slong& fmpz_poly_factorxx::exp(slong i) Obtain the exponent of the ith factor. .. cpp:function:: fmpz_polyxx_srcref fmpz_poly_factorxx::p(slong i) const .. cpp:function:: fmpz_polyxx_ref fmpz_poly_factorxx::p(slong i) Obtain the ith factor. .. cpp:function:: fmpzxx_srcref fmpz_poly_factorxx::content() const .. cpp:function:: fmpzxx_ref fmpz_poly_factorxx::content() Obtain the content of the factorised polynomial. Memory management ------------------------------------------------------------------------------- .. cpp:function:: fmpz_poly_factorxx::fmpz_poly_factorxx() .. cpp:function:: explicit fmpz_poly_factorxx::fmpz_poly_factorxx(slong alloc) Initialise an empty factorisation. .. cpp:function:: fmpz_poly_factorxx::fmpz_poly_factorxx(const fmpz_poly_factorxx& o) Copy a factorisation. .. cpp:function:: void fmpz_poly_factorxx::realloc(slong a) .. cpp:function:: void fmpz_poly_factorxx::fit_length(slong a) Manipulating factors ------------------------------------------------------------------------------- .. cpp:function:: void fmpz_poly_factorxx::insert(Fmpz_poly_expr p, slong e) .. cpp:function:: void fmpz_poly_factorxx::concat(const fmpz_poly_factorxx&) Factoring algorithms ------------------------------------------------------------------------------- .. cpp:function:: void fmpz_poly_factorxx::set_factor_squarefree(Fmpz_poly_expr p) .. cpp:function:: void fmpz_poly_factorxx::set_factor_zassenhaus(Fmpz_poly_expr p) .. cpp:function:: void fmpz_poly_factorxx::set_factor_zassenhaus_recombination(const fmpz_poly_factorxx& lifted_fac, Fmpz_poly_expr F, Fmpz_expr P, slong exp) .. cpp:function:: fmpz_poly_factorxx::factor_squarefree(Fmpz_poly_expr) .. cpp:function:: fmpz_poly_factorxx::factor_zassenhaus(Fmpz_poly_expr) Rationals (``fmpq``) =============================================================================== C++ particulars ------------------------------------------------------------------------------- .. cpp:function:: ?? Fmpq_expr::num() const .. cpp:function:: ?? Fmpq_expr::den() const Unified coefficient access to numerator and denominator. If this is used to modify the object, a call to ``canonicalise()`` may be necessary. Memory management ------------------------------------------------------------------------------- .. cpp:function:: fmpqxx::fmqxx() Initialize to zero. .. cpp:function:: fmpqxx::fmpqxx(Fmpz_src num, Fmpz_src den) .. cpp:function:: fmpqxx::fmpqxx(T:fits_into_slong num, U:is_unsigned_integer den) Initialize from numerator ``num`` and denominator ``den``. Canonicalisation ------------------------------------------------------------------------------- .. cpp:function:: void Fmpq_target::canonicalise() .. cpp:function:: bool Fmpq_src::is_canonical() const Basic assignment ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_expr Fmpq_expr::abs() const .. cpp:function:: Fmpq_expr abs(Fmpq_expr) .. cpp:function:: void Fmpq_target::set_zero() .. cpp:function:: void Fmpq_target::set_one() .. cpp:function:: static fmpqxx fmpqxx::zero() .. cpp:function:: static fmpqxx fmpqxx::one() Comparison ------------------------------------------------------------------------------- The overloaded relational operators can be used for comparison. Additionally, we have the followi.. cpp:functions. .. cpp:function:: bool Fmpq_expr::is_zero() const .. cpp:function:: bool Fmpq_expr::is_one() const .. cpp:function:: int Fmpq_expr::sgn() const .. cpp:function:: mp_bitcnt_t Fmpq_expr::height_bits() const .. cpp:function:: Fmpz_expr Fmpq_expr::height() const .. cpp:function:: mp_bitcnt_t height_bits(Fmpq_expr) .. cpp:function:: Fmpq_expr height(Fmpq_expr) Conversion ------------------------------------------------------------------------------- Conversion can be done using the assignment operator, and through the followi.. cpp:functions. .. cpp:function:: static fmpqxx fmpqxx::frac(const T& t, const U& u) Same as ``fmpqxx res;res.set_frac(t, u)``. .. cpp:function:: static fmpqxx fmpqxx::integer(const T& t) Same as ``fmpqxx res;res.set_integer(t)``. .. cpp:function:: void Fmpq_target::set_frac(const T& t, const U& u) ``f.set_frac(t, u)`` has the same effect as ``f.num() = t;f.den() = u;f.canonicalise()``. .. cpp:function:: void Fmpq_target::set_integer(const T& t) ``f.set_integer(t)`` has the same effect as ``f.num() = t;f.den() = 1u``; .. cpp:function:: std::string Fmpq_expr::to_string(int base = 10) const Input and output ------------------------------------------------------------------------------- .. cpp:function:: int print(Fmpq_expr) .. cpp:function:: int print(FILE*, Fmpq_expr) Random number generation ------------------------------------------------------------------------------- .. cpp:function:: static fmpqxx fmpqxx::randbits(frandxx& state) .. cpp:function:: static fmpqxx fmpqxx::randtest(frandxx& state) .. cpp:function:: static fmpqxx fmpqxx::randtest_not_zero(frandxx& state) Arithmetic ------------------------------------------------------------------------------- The overloaded operators ``+ - * /`` can be used for arithmetic. Additionally, we provide the followi.. cpp:functions. .. cpp:function:: Fmpq_expr Fmpq_expr::inv() const .. cpp:function:: Fmpq_expr Fmpq_expr::pow(T:fits_into_slong) const .. cpp:function:: Fmpq_expr inv(Fmpq_expr) .. cpp:function:: Fmpq_expr pow(Fmpq_expr, T:fits_into_slong) .. cpp:function:: Fmpq_expr operator<<(Fmpq_expr, T:is_integer) .. cpp:function:: Fmpq_expr operator>>(Fmpq_expr, T:is_integer) Shift operators are overloaded. See ``fmpq_div_2exp`` and ``fmpq_mul_2exp``. Modular reduction and rational reconstruction ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_expr operator%(Fmpq_expr, Fmpz_expr) See ``fmpq_mod_fmpz``. The modular reduction operator may raise a ``flint_exception`` if modular inversion is not possible. .. cpp:function:: static Fmpq_expr fmpqxx::reconstruct(Fmpz_expr a, Fmpz_expr m, Fmpz_expr N, Fmpz_expr D) .. cpp:function:: static Fmpq_expr fmpqxx::reconstruct(Fmpz_expr a, Fmpz_expr m) Rational reconstruction. May raise a ``flint_exception`` if reconstruction is not possible. See ``fmpq_reconstruct_fmpz`` and ``fmpq_reconstruct_fmpz2``. Rational enumeration ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_expr Fmpq_expr::next_minimal() const .. cpp:function:: Fmpq_expr Fmpq_expr::next_signed_minimal() const .. cpp:function:: Fmpq_expr Fmpq_expr::next_calkin_wilf() const .. cpp:function:: Fmpq_expr Fmpq_expr::next_signed_calkin_wilf() const Continued fractions ------------------------------------------------------------------------------- .. cpp:function:: slong Fmpq_expr::cfrac_bound() const .. cpp:function:: template void Fmpq_target::set_cfrac(const Vec& v, slong n) Set value to a partial fraction expansion. The same conventions apply to ``v`` as in the constructor. .. cpp:function:: template static fmpqxx fmpqxx::from_cfrac(const Vec& v, slong n) Initialize from a partial fraction expansion. ``v`` must be an instance of a class which provides a method ``_array()`` that returns (a pointer to) an array of ``fmpz``. One such class is ``fmpz_vecxx``. The array must have size (at least) ``n``. Matrices over the rationals (``fmpq_matxx``) =============================================================================== The class ``fmpq_matxx`` wraps ``fmpq_mat_t``. Like ``fmpz_matxx``, many operations on ``fmpq_matxx`` do not support aliasing. The details can be found in the documentation of ``fmpq_mat_t``. Since ``fmpq_matxx`` does not use temporary merging, evaluation of subexpressions never creates new aliases. .. cpp:function:: Fmpq_mat_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``inv``, ``transpose``, ``det``, ``trace``, ``numden_entrywise``, ``numden_rowwise``, ``numden_colwise``, ``numden_matwise``, ``num_rowwise``. .. cpp:function:: Fmpq_mat_expr::binary operation(??) const The following bina.. cpp:functions are made available as member functions: ``solve_dixon``, ``solve_fraction_free``, ``mul_cleared``, ``mul_direct``. .. cpp:function:: Fmpq_mat_expr operator?(??, ??) Arithmetic operators ``+ - * /`` are overloaded when provided by ``fmpq_mat_t``. .. cpp:function:: Fmpq_mat_expr operator-(Fmpq_mat_expr) The unary negation operator is overloaded. .. cpp:function:: Fmpq_mat_target Fmpq_mat_target::operator=(Fmpz_mat_expr) See ``fmpq_mat_set_fmpz_mat``. Memory management ------------------------------------------------------------------------------- .. cpp:function:: fmpq_matxx::fmpq_matxx(slong m, slong n) See ``fmpq_mat_init``. Input and output ------------------------------------------------------------------------------- .. cpp:function:: int print(Fmpq_mat_expr) Entry access ------------------------------------------------------------------------------- .. cpp:function:: ?? Fmpq_mat_expr::at(slong, slong) const Unified coefficient access to the entries of the matrix. Basic assignment ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_mat_expr transpose(Fmpq_poly_mat_expr) .. cpp:function:: void Fmpq_mat_target::set_zero() .. cpp:function:: void Fmpq_mat_target::set_one() .. cpp:function:: static fmpq_matxx fmpq_matxx::zero(slong rows, slong cols) .. cpp:function:: static fmpq_matxx fmpq_matxx::one(slong rows, slong cols) Random matrix generation ------------------------------------------------------------------------------- .. cpp:function:: void Fmpq_mat_target::set_randtest(frandxx& state, slong len, mp_bitcnt_t) .. cpp:function:: static fmpq_matxx fmpq_matxx::randtest(slong rows, slong cols, frandxx& state, slong len, mp_bitcnt_t) .. cpp:function:: void Fmpq_mat_target::set_randtest_unsigned(frandxx& state, slong len, mp_bitcnt_t) .. cpp:function:: static fmpq_matxx fmpq_matxx::randtest_unsigned(slong rows, slong cols, frandxx& state, slong len, mp_bitcnt_t) Special matrices ------------------------------------------------------------------------------- .. cpp:function:: void Fmpq_target::set_hilbert_matrix() .. cpp:function:: Fmpq_mat_expr hilbert_matrix(slong m, slong n) Basic properties ------------------------------------------------------------------------------- .. cpp:function:: bool Fmpq_mat_expr::is_zero() const .. cpp:function:: bool Fmpq_mat_expr::is_empty() const .. cpp:function:: bool Fmpq_mat_expr::is_square() const .. cpp:function:: bool Fmpq_mat_expr::is_integral() const Integer matrix conversion ------------------------------------------------------------------------------- .. cpp:function:: static fmpq_matxx fmpq_matxx::frac(Fmpz_mat_expr, Fmpz_expr) .. cpp:function:: void Fmpq_mat_target::set_frac(Fmpz_mat_expr, Fmpz_expr) See ``fmpq_mat_set_fmpz_mat_div_fmpz``. .. cpp:function:: static fmpq_matxx fmpq_matxx::integer_matrix(Fmpz_mat_expr) See ``fmpq_mat_set_fmpz_mat``. .. cpp:function:: Fmpz_mat_expr num_rowwise(Fmpq_mat_expr) This has the effect of calling ``fmpq_mat_get_fmpz_mat_rowwise`` with second argument ``NULL``. .. cpp:function:: Ltuple_expr numden_entrywise(Fmpq_mat_expr) See ``fmpq_mat_get_fmpz_mat_entrywise``. .. cpp:function:: Ltuple_expr numden_matwise(Fmpq_mat_expr) See ``fmpq_mat_get_fmpz_mat_matwise``. .. cpp:function:: Ltuple_expr numden_rowwise(Fmpq_mat_expr) See ``fmpq_mat_get_fmpz_mat_rowwise``. .. cpp:function:: Ltuple_expr numden_colwise(Fmpq_mat_expr) See ``fmpq_mat_get_fmpz_mat_colwise``. Modular reduction and rational reconstruction ------------------------------------------------------------------------------- To reduce an ``fmpq_matxx`` modulo an ``fmpzxx`` to get an ``fmpz_matxx``, see ``fmpz_matxx::reduce``. .. cpp:function:: static fmpq_matxx fmpq_matxx::reconstruct(Fmpz_mat_expr, Fmpz_expr) See ``fmpq_mat_set_fmpz_mat_mod_fmpz``. Matrix multiplication ------------------------------------------------------------------------------- The overloaded ``operator*`` can be used for matrix multiplication. Finer control can be obtained using the followi.. cpp:functions. .. cpp:function:: Fmpq_mat_expr mul_direct(Fmpq_mat_expr, Fmpq_mat_expr) .. cpp:function:: Fmpq_mat_expr mul_cleared(Fmpq_mat_expr, Fmpq_mat_expr) Trace ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_expr trace(Fmpq_mat_expr) Determinant ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_expr det(Fmpq_mat_expr) Nonsingular solving ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_mat_expr solve_dixon(Fmpq_mat_expr B, Fmpq_mat_expr X) .. cpp:function:: Fmpq_mat_expr solve_fraction_free(Fmpq_mat_expr B, Fmpq_mat_expr X) See ``fmpq_mat_solve_dixon`` and ``fmpq_mat_solve_fraction_free``. Raises ``flint_exception`` if $B$ is singular. Inverse ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_mat_expr inv(Fmpq_mat_expr A) Compute the inverse of the square matrix $A$. Raises ``flint_exception`` if $A$ is singular. The modulus is required to be prime. Echelon form ------------------------------------------------------------------------------- .. cpp:function:: bool Fmpq_mat_target::pivot(slong r, slong c, permxx* perm = 0) See ``fmpq_mat_pivot``. .. cpp:function:: Ltuple_expr rref(Fmpq_mat_expr) .. cpp:function:: Ltuple_expr rref_classical(Fmpq_mat_expr) .. cpp:function:: Ltuple_expr rref_fraction_free(Fmpq_mat_expr) See ``fmpq_mat_rref`` etc. Polynomials over the rationals (``fmpq_poly``) =============================================================================== C++ particulars ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_expr Fmpq_poly_expr::operator()(Fmpq_poly_expr) const .. cpp:function:: Fmpq_poly_expr Fmpq_poly_expr::operator()(Fmpq_expr) const Overloaded ``operator()`` for evaluation or composition. .. cpp:function:: Fmpq_poly_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``derivative``, ``integral``, ``inv``, ``make_monic``, ``primitive_part``, ``content``. .. cpp:function:: Fmpq_poly_expr::binary operation(??) const The following bina.. cpp:functions are made available as member functions: ``asinh_series``, ``asin_series``, ``atanh_series``, ``atan_series``, ``cosh_series``, ``cos_series``, ``divrem``, ``exp_series``, ``gcd``, ``inv_series``, ``inv_series_newton``, ``lcm``, ``log_series``, ``pow``, ``resultant``, ``reverse``, ``revert_series``, ``revert_series_lagrange``, ``revert_series_lagrange_fast``, ``revert_series_newton``, ``sinh_series``, ``tanh_series``, ``tan_series``, ``xgcd``, ``rescale``,\\ ``shift_left``, ``shift_right``. .. cpp:function:: Fmpq_poly_expr::ternary operation(??, ??) const The following terna.. cpp:functions are made available as member functions: ``compose_series``, ``compose_series_brent_kung``, ``compose_series_horner``, ``div_series``, ``mullow``. Memory management ------------------------------------------------------------------------------- .. cpp:function:: fmpq_polyxx::fmpq_polyxx() .. cpp:function:: fmpq_polyxx::fmpq_polyxx(slong alloc) See ``fmpq_poly_init2``. .. cpp:function:: fmpq_polyxx::fmpq_polyxx(const char* str) See ``fmpq_poly_set_str``. .. cpp:function:: void Fmpq_poly_target realloc(slong alloc) .. cpp:function:: void Fmpq_poly_target::fit_length(slong len) .. cpp:function:: void Fmpq_poly_target::_normalise() .. cpp:function:: void Fmpq_poly_target::_set_length(slong len) .. cpp:function:: void Fmpq_poly_target::canonicalise() .. cpp:function:: bool Fmpq_poly_src::is_canonical() const Polynomial parameters ------------------------------------------------------------------------------- .. cpp:function:: slong Fmpq_poly_expr::length() const .. cpp:function:: slong Fmpq_poly_expr::degree() const Accessing the numerator and denominator ------------------------------------------------------------------------------- .. cpp:function:: fmpqxx_ref Fmpq_poly_target::get_coeff_numref(slong n) .. cpp:function:: fmpqxx_srcref Fmpq_poly_src::get_coeff_numref(slong n) const Obtain a reference to the numerator of coefficient $n$. The result is undefined if $n$ is greater than the degree of the polynomial (or negative). If this is used to modify the object, a call to ``canonicalise()`` may be necessary. (No unified access, see ``get_coeff``.) .. cpp:function:: ?? Fmpq_poly_expr::den() const Unified coefficient access to the denominator of the polynomial. If this is used to modify the object, a call to ``canonicalise()`` may be necessary. Random testing ------------------------------------------------------------------------------- .. cpp:function:: static fmpq_polyxx fmpq_polyxx::randtest(frandxx& state, slong len, mp_bitcnt_t bits) .. cpp:function:: static fmpq_polyxx fmpq_polyxx::randtest_unsigned(frandxx& state, slong len, mp_bitcnt_t bits) .. cpp:function:: static fmpq_polyxx fmpq_polyxx::randtest_not_zero(frandxx& state, slong len, mp_bitcnt_t bits) See ``fmpq_poly_randtest`` etc. Assignment ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_target Fmpq_poly_target::operator=(T:is_integer) .. cpp:function:: Fmpq_poly_target Fmpq_poly_target::operator=(Fmpq_expr) .. cpp:function:: Fmpq_poly_target Fmpq_poly_target::operator=(Fmpz_expr) .. cpp:function:: Fmpq_poly_target Fmpq_poly_target::operator=(Fmpz_poly_expr) .. cpp:function:: Fmpq_poly_target Fmpq_poly_target::operator=(const char*) .. cpp:function:: void Fmpq_poly_target::set_zero() .. cpp:function:: void Fmpq_poly_target::set_one() .. cpp:function:: static fmpq_polyxx fmpq_polyxx::zero() .. cpp:function:: static fmpq_polyxx fmpq_polyxx::one() .. cpp:function:: Fmpq_poly_expr inv(Fmpq_poly_expr) .. cpp:function:: static fmpq_polyxx fmpq_polyxx::get_slice(Fmpq_poly_expr, slong i, slong j) .. cpp:function:: void Fmpq_poly_target::truncate(slong) .. cpp:function:: Fmpq_poly_expr reverse(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: std::string Fmpq_poly_expr::pretty(const char* x) const See ``fmpq_poly_get_str_pretty``. .. cpp:function:: std::string Fmpq_poly_expr::to_string() const Getting and setting coefficients ------------------------------------------------------------------------------- .. cpp:function:: Fmpqxx_expr Fmpq_poly_expr::get_coeff(slong n) const .. cpp:function:: void Fmpq_poly_target::set_coeff(slong n, Fmpz_expr) .. cpp:function:: void Fmpq_poly_target::set_coeff(slong n, Fmpq_expr) .. cpp:function:: void Fmpq_poly_target::set_coeff(slong n, T:is_integer) Comparison ------------------------------------------------------------------------------- The overloaded operators ``== != >= >`` etc. can be used for comparison. Additionally, we have the followi.. cpp:functions. .. cpp:function:: bool Fmpq_poly_expr::is_one() const .. cpp:function:: bool Fmpq_poly_expr::is_zero() const Arithmetic ------------------------------------------------------------------------------- The overloaded operators ``* / + -`` can be used for both polynomial-polynomial and polynomial-scalar arithmetic. Additionally, we provide the followi.. cpp:functions. .. cpp:function:: Fmpq_poly_expr mullow(Fmpq_poly_expr, Fmpq_poly_expr, slong) Powering ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_expr pow(Fmpq_poly_expr, T:is_unsigned_integer) Shifting ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_expr shift_left(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr shift_right(Fmpq_poly_expr, T:fits_into_slong) Euclidean division ------------------------------------------------------------------------------- The overloaded operators ``/ %`` can be used for euclidean division and remainder. Additionally, we have the followi.. cpp:functions. .. cpp:function:: Ltuple_expr divrem(Fmpq_poly_expr A, Fmpq_poly_expr B) ``ltupleref(Q, R) = divrem(A, B)`` has the same effect as ``fmpq_poly_divrem(q, r, a, b)`` where ``q, r, a, b`` are the underlying ``fmpq_poly_t`` corresponding to ``Q, R, A, B``. Power series division ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_expr inv_series_newton(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr inv_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr div_series(Fmpq_poly_expr, Fmpq_poly_expr, slong n) Greatest common divisor ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_expr gcd(Fmpq_poly_expr, Fmpq_poly_expr) .. cpp:function:: Fmpq_poly_expr lcm(Fmpq_poly_expr, Fmpq_poly_expr) .. cpp:function:: Ltuple_expr xgcd(Fmpq_poly_expr f, Fmpq_poly_expr g) ``ltupleref(G, S, T) = xgcd(A, B)`` has the same effect as ``fmpq_poly_xgcd(g, s, t, a, b)``, where ``g, s, t, a, b`` denote the underlying ``fmpq_poly_t`` corresponding to ``G, S, T, A, B``. .. cpp:function:: Fmpq_expr resultant(Fmpq_poly_expr) Derivative and integral ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_expr derivative(Fmpq_poly_expr) .. cpp:function:: Fmpq_poly_expr integral(Fmpq_poly_expr) Square roots ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_expr sqrt_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr invsqrt_series(Fmpq_poly_expr, T:fits_into_slong) Transcendent.. cpp:functions ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_expr exp_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr log_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr atan_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr atanh_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr asin_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr asinh_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr tan_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr sin_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr cos_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr sinh_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr cosh_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr tanh_series(Fmpq_poly_expr, T:fits_into_slong) Evaluation ------------------------------------------------------------------------------- The overloaded ``operator()`` can be used for evaluation. Additionally we have the following. .. cpp:function:: Fmpq_expr evaluate(Fmpq_poly_expr, Fmpq_expr) .. cpp:function:: Fmpq_expr evaluate(Fmpq_poly_expr, Fmpz_expr) Interpolation ------------------------------------------------------------------------------- .. cpp:function:: static Fmpq_poly_expr fmpq_polyxx::interpolate(Fmpz_vec_expr xs, Fmpz_vec_expr ys) See ``fmpq_poly_interpolate_fmpq_vec``. Composition ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_expr compose(Fmpq_poly_expr, Fmpq_poly_expr) .. cpp:function:: Fmpq_poly_expr rescale(Fmpq_poly_expr, Fmpq_expr) Power series composition ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_expr compose_series(Fmpq_poly_expr, Fmpq_poly_expr, slong) .. cpp:function:: Fmpq_poly_expr compose_series_horner(Fmpq_poly_expr, Fmpq_poly_expr, slong) .. cpp:function:: Fmpq_poly_expr compose_series_brent_kung(Fmpq_poly_expr, Fmpq_poly_expr, slong) Power series reversion ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_expr revert_series(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr revert_series_newton(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr revert_series_lagrange(Fmpq_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpq_poly_expr revert_series_lagrange_fast(Fmpq_poly_expr, T:fits_into_slong) Gaussian content ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_expr content(Fmpq_poly_expr) .. cpp:function:: Fmpq_poly_expr primitive_part(Fmpq_poly_expr) .. cpp:function:: bool Fmpq_poly_expr::is_monic() const .. cpp:function:: Fmpq_poly_expr make_monic(Fmpq_poly_expr) Square-free ------------------------------------------------------------------------------- .. cpp:function:: bool Fmpq_poly_expr::is_squarefree() const Input and output ------------------------------------------------------------------------------- .. cpp:function:: print(Fmpq_poly_expr) .. cpp:function:: print(FILE*, Fmpq_poly_expr) .. cpp:function:: print_pretty(Fmpq_poly_expr, const char* var) .. cpp:function:: print_pretty(FILE*, Fmpq_poly_expr, const char* var) .. cpp:function:: read(Fmpq_poly_target) .. cpp:function:: read(FILE*, Fmpq_poly_target) Ration.. cpp:functions (``fmpz_poly_q``) =============================================================================== Memory management ------------------------------------------------------------------------------- .. cpp:function:: fmpz_poly_qxx::fmpz_poly_qxx() .. cpp:function:: fmpz_poly_qxx::fmpz_poly_qxx(const char*) See ``fmpz_poly_q_set_str``. .. cpp:function:: void Fmpz_poly_q_target::canonicalise() .. cpp:function:: bool Fmpz_poly_q_src::is_canonical() const .. cpp:function:: ?? Fmpz_poly_q_expr::num() const .. cpp:function:: ?? Fmpz_poly_q_expr::den() const Unified coefficient access to the numerator or denominator of the rational .. cpp:function. If this is used for modification, a call to ``canonicalise()`` may be necessary. Randomisation ------------------------------------------------------------------------------- .. cpp:function:: static fmpz_poly_qxx fmpz_poly_qxx::randtest(frandxx& state, slong len1, mp_bitcnt_t bits1, slong len2, mp_bitcnt_t bits2) .. cpp:function:: static fmpz_poly_qxx fmpz_poly_qxx::randtest_not_zero(frandxx& state, slong len1, mp_bitcnt_t bits1, slong len2, mp_bitcnt_t bits2) See ``fmpz_poly_q_randtest`` etc. Assignment ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_q_target Fmpz_poly_q_target::operator=(T:fits_into_slong) .. cpp:function:: void Fmpz_poly_q_target::set_zero() .. cpp:function:: void Fmpz_poly_q_target::set_one() .. cpp:function:: static fmpz_poly_qxx fmpz_poly_qxx::zero() .. cpp:function:: static fmpz_poly_qxx fmpz_poly_qxx::one() .. cpp:function:: Fmpz_poly_q_expr inv(Fmpz_poly_q_expr) .. cpp:function:: Fmpz_poly_q_expr Fmpz_poly_q_expr::inv() const Comparison ------------------------------------------------------------------------------- The overloaded operator ``==`` can be used for comparison. Additionally, we have the followi.. cpp:functions. .. cpp:function:: bool Fmpz_poly_q_expr::is_one() const .. cpp:function:: bool Fmpz_poly_q_expr::is_zero() const Powering ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_q_expr pow(Fmpz_poly_q_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_poly_q_expr Fmpz_poly_q_expr::pow(T:is_unsigned_integer) const Derivative ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_q_expr Fmpz_poly_q_expr::derivative() const .. cpp:function:: Fmpz_poly_q_expr derivative(Fmpz_poly_q_expr) Input and output ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_q_target Fmpz_poly_q_target::operator=(const char*) See ``fmpz_poly_q_set_str``. .. cpp:function:: std::string Fmpz_poly_q_expr::to_string() const See ``fmpz_poly_q_get_str``. .. cpp:function:: std::string Fmpz_poly_q_expr::pretty(const char* x) const See ``fmpz_poly_q_get_str_pretty``. .. cpp:function:: int print(Fmpz_poly_q_expr) .. cpp:function:: int print_pretty(Fmpz_poly_q_expr, const char* var) Matrices of polynomials over the integers (``fmpz_poly_mat``) =============================================================================== The class ``fmpz_poly_matxx`` wraps ``fmpz_poly_mat_t``, and so represents matrices with coefficients in $\mathbf{Z}[X]$. Its usage is similar to ``fmpz_matxx`` in most regards. .. cpp:function:: Fmpz_poly_mat_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``det``, ``det_fflu``, ``det_interpolate``, ``trace``, ``sqr``, ``sqr_classical``, ``sqr_KS``, ``transpose``. .. cpp:function:: Fmpz_poly_mat_expr::binary operation(??) const The following bina.. cpp:functions are made available as member functions: ``solve``, ``solve_fflu``, ``mul_classical``, ``mul_interpolate``, ``mul_KS``, ``pow``, ``sqrlow``. .. cpp:function:: Fmpz_poly_mat_expr::three operation(??) const The following threea.. cpp:functions are made available as member functions: ``mullow``, ``pow_trunc``. .. cpp:function:: Fmpz_mat_expr Fmpz_poly_mat_expr::operator()(Fmpz_expr) const ``operator()`` is overloaded for matrix evaluation. .. cpp:function:: Fmpz_poly_mat_expr operator?(??, ??) Arithmetic operators ``+ - *`` are overloaded when provided by ``fmpz_poly_mat_t``. .. cpp:function:: Fmpz_poly_mat_expr operator-(Fmpz_poly_mat_expr) The unary negation operator is overloaded. Input and output ------------------------------------------------------------------------------- .. cpp:function:: int print_pretty(Fmpz_poly_mat_expr, const char* x) Basic properties ------------------------------------------------------------------------------- .. cpp:function:: slong Fmpz_poly_mat_expr::rows() const .. cpp:function:: slong Fmpz_poly_mat_expr::cols() const Obtain the number of rows/columns in this matrix. The.. cpp:functions never cause evaluation (the matrix size is computed from the operations in the expression template and the size of the input matrices). Basic assignment and manipulation ------------------------------------------------------------------------------- .. cpp:function:: ?? Fmpz_poly_mat_expr::at(T:fits_into_slong, U:fits_into_slong) const Unified coefficient access to the matrix entries. Standard matrices ------------------------------------------------------------------------------- .. cpp:function:: void Fmpz_poly_mat_target::set_zero() .. cpp:function:: void Fmpz_poly_mat_target::set_one() .. cpp:function:: static fmpz_poly_matxx fmpz_poly_matxx::zero(slong rows, slong cols) .. cpp:function:: static fmpz_poly_matxx fmpz_poly_matxx::one(slong rows, slong cols) Random matrix generation ------------------------------------------------------------------------------- .. cpp:function:: void Fmpz_poly_mat_target::set_randtest(frandxx& state, slong len, mp_bitcnt_t) .. cpp:function:: void Fmpz_poly_mat_target::set_randtest_unsigned(frandxx& state, slong len, mp_bitcnt_t) .. cpp:function:: void Fmpz_poly_mat_target::set_randtest_sparse(frandxx& state, slong len, mp_bitcnt_t, float) .. cpp:function:: static fmpz_poly_matxx fmpz_poly_matxx::randtest(slong rows, slong cols, frandxx&, slong len, mp_bitcnt_t) .. cpp:function:: static fmpz_poly_matxx fmpz_poly_matxx::randtest_unsigned(slong rows, slong cols, frandxx&, slong len, mp_bitcnt_t) .. cpp:function:: static fmpz_poly_matxx fmpz_poly_matxx::randtest_sparse(slong rows, slong cols, frandxx&, slong len, mp_bitcnt_t, float density) See ``fmpz_poly_mat_randtest`` etc. Basic comparison and properties ------------------------------------------------------------------------------- .. cpp:function:: bool Fmpz_poly_mat_expr::is_zero() const .. cpp:function:: bool Fmpz_poly_mat_expr::is_one() const .. cpp:function:: bool Fmpz_poly_mat_expr::is_empty() const .. cpp:function:: bool Fmpz_poly_mat_expr::is_square() const Norms ------------------------------------------------------------------------------- .. cpp:function:: slong Fmpz_poly_mat_expr::max_length() const .. cpp:function:: slong Fmpz_poly_mat_expr::max_bits() const Transpose ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_mat_expr transpose(Fmpz_poly_mat_expr) Arithmetic ------------------------------------------------------------------------------- Basic arithmetic is most easily done using the overloaded operators ``+ * -``. Finer control can be obtained using the followi.. cpp:functions. .. cpp:function:: Fmpz_mat_expr mul_classical(Fmpz_mat_expr, Fmpz_mat_expr) .. cpp:function:: Fmpz_mat_expr mul_KS(Fmpz_mat_expr, Fmpz_mat_expr) .. cpp:function:: Fmpz_poly_mat_expr mullow(Fmpz_poly_mat_expr, Fmpz_poly_mat_expr, slong) .. cpp:function:: Fmpz_poly_mat_expr sqr(Fmpz_poly_mat_expr) .. cpp:function:: Fmpz_poly_mat_expr sqr_KS(Fmpz_poly_mat_expr) .. cpp:function:: Fmpz_poly_mat_expr sqr_classical(Fmpz_poly_mat_expr) .. cpp:function:: Fmpz_poly_mat_expr sqrlow(Fmpz_poly_mat_expr, T:fits_into_slong n) .. cpp:function:: Fmpz_poly_mat_expr pow(Fmpz_poly_mat_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_poly_mat_expr pow_trunc(Fmpz_poly_mat_expr, T:is_unsigned_integer, T:fits_into_slong) .. cpp:function:: Fmpz_poly_mat_expr prod(Fmpz_poly_mat_vec_expr) Row reduction ------------------------------------------------------------------------------- Beware that compared to the C interface, the flintxx row reduction interface changes some argument orders. This is to facilitate default arguments. .. cpp:function:: slong find_pivot_any(Fmpz_poly_mat_expr, slong, slong, slong) See ``fmpz_poly_mat_find_pivot_any``. .. cpp:function:: slong find_pivot_partial(Fmpz_poly_mat_expr, slong, slong, slong) See ``fmpz_poly_mat_find_pivot_partial``. .. cpp:function:: Ltuple_expr fflu(Fmpz_poly_mat_expr A, permxx* perm = 0, bool rankcheck = false) See ``fmpz_poly_mat_fflu``. .. cpp:function:: Ltuple_expr rref(Fmpz_poly_mat_expr A) See ``fmpz_poly_mat_rref``. Trace ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr trace(Fmpz_poly_mat_expr) Determinant and rank ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr det(Fmpz_poly_mat_expr) .. cpp:function:: Fmpz_poly_expr det_fflu(Fmpz_poly_mat_expr) .. cpp:function:: Fmpz_poly_expr det_interpolate(Fmpz_poly_mat_expr) .. cpp:function:: slong rank(Fmpz_poly_mat_expr) Inverse ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr inv(Fmpz_poly_mat_expr) ``ltupleref(b, M, D) = inv(A)`` has the same effect as ``b = fmpz_poly_mat_inv(m, d, a)``, where ``m, d, a`` are the underlying C objects corresponding to ``M, D, A``. Nullspace ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr nullspace(Fmpz_poly_mat_expr A) ``ltupleref(n, B) = nullspace(A)`` has the same effect as\\ ``n = fmpz_poly_mat_nullspace(b, a)``, where ``b, a`` are the underlying ``fmpz_poly_mat_t`` corresponding to ``B, A``. Solving ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr solve(Fmpz_poly_mat_expr B, Fmpz_poly_mat_expr X) .. cpp:function:: Ltuple_expr solve_fflu(Fmpz_poly_mat_expr B, Fmpz_poly_mat_expr X) .. cpp:function:: Ltuple_expr solve_fflu_precomp(const permxx&, Fmpz_poly_mat_expr B, Fmpz_poly_mat_expr FFLU, Fmpz_poly_mat_expr X) ``ltupleref(w, M, D) = solve(B, X)`` has the same effect as\\ ``w = fmpz_poly_mat_solve(m, d, b, x)``, where ``m, d, b, x`` are the underlying C objects corresponding to ``M, D, B, X``. Similarly for the oth.. cpp:functions. Integers mod `n` (``nmod``) =============================================================================== The class ``nmodxx`` encapsulates the use of ``mp_limb_t`` together with ``nmod_t`` for doing arithmetic modulo a word-sized integer. It is defined in ``nmod_vecxx.h``. The C++ equivalent to ``nmod_t`` is ``nmodxx_ctx``. There is a reference version ``nmodxx_ctx_srcref``. The C++ equivalent to ``mp_limb_t`` in this context is ``nmodxx``. Immediate ``nmodxx`` expressions store both an ``mp_limb_t`` and an ``nmodxx_ctx_srcref``. The most common ways to construct ``nmodxx`` are using the static member functions ``nmodxx::red`` and ``nmodxx::make_nored``. For convenience, ``operator%`` is overloaded with right hand side ``nmodxx_ctx`` (or ``nmodxx_ctx_srcref``) to call ``nmodxx::red``. Just like when ``mp_limb_t`` is passed to ``nmod_t`` operations, the limb stored in ``nmodxx`` is assumed to be reduced, and under this assumption, all computations yield reduced data. It is assumed that any expression of ``nmodxx`` involves only one modulus, so that all contexts are interchangeable. Miscellaneous ------------------------------------------------------------------------------- .. cpp:function:: explicit nmodxx_ctx::nmodxx_ctx(mp_limb_t n) Initialise a new context for operations modulo $n$. .. cpp:function:: nmodxx_ctx_srcref::nmodxx_ctx_srcref(const nmodxx_ctx&) Initialise a reference to an ``nmodxx_ctx``. .. cpp:function:: static nmodxx_ctx_srcref::make(const nmod_t& nm) Initialise a reference pointing to an ``nmod_t``. .. cpp:function:: const nmod_t& nmodxx_ctx::_nmod() const .. cpp:function:: const nmod_t& nmodxx_ctx_srcref::_nmod() const Obtain a reference to the underlying ``nmod_t``. .. cpp:function:: mp_limb_t nmodxx_ctx::n() const .. cpp:function:: mp_limb_t nmodxx_ctx_srcref::n() const Obtain the modulus stored in this context. .. cpp:function:: nmodxx::nmodxx(nmodxx_ctx_srcref ctx) Initialise an ``nmodxx`` to zero. .. cpp:function:: static nmodxx nmodxx::make_nored(mp_limb_t n, nmodxx_ctx_srcref ctx) Initialise an ``nmodxx`` to $n$, performing no reductions. .. cpp:function:: static nmodxx nmodxx::red(mp_limb_t n, nmodxx_ctx_srcref ctx) .. cpp:function:: static nmodxx nmodxx::red(Fmpz_expr n, nmodxx_ctx_srcref ctx) .. cpp:function:: static nmodxx nmodxx::red(Fmpq_expr n, nmodxx_ctx_srcref ctx) Initialise an ``nmodxx`` to the reduction of $n$. .. cpp:function:: static nmodxx_ref nmodxx_ref::make(mp_limb_t& l, nmodxx_ctx_srcref c) .. cpp:function:: static nmodxx_srcref nmodxx_srcref::make(const mp_limb_t&, nmodxx_ctx_srcref) Obtain a flintxx reference object pointing to ``l``, which is interpreted as a limb reduced modulo ``c``. .. cpp:function:: void Nmod_target::reduce() Reduce the stored limb. .. cpp:function:: void Nmod_target::set_nored(mp_limb_t n) Set the stored limb to $n$. .. cpp:function:: std::string Nmod_expr::to_string() const Convert self into a string of the form "a mod b". .. cpp:function:: mp_limb_t Nmod_expr::to() const Obtain the stored limb. .. cpp:function:: nmodxx_ctx_srcref Nmod_expr::estimate_ctx() const Obtain the context of any immediate subexpression. (By our homogeneity assumptions, the result of this operation does not depend on the subexpression chosen.) .. cpp:function:: Nmod_expr Nmod_expr::inv() const .. cpp:function:: Nmod_expr Nmod_expr::pow(T:is_unsigned_integer) const .. cpp:function:: Nmod_expr operator??(Nmod_expr, Nmod_expr) Arithmetic operators ``+ - * /`` are overloaded for nmod expressions. .. cpp:function:: Nmod_expr operator-(Nmod_expr) .. cpp:function:: Nmod_expr pow(Nmod_expr, T:is_unsigned_integer) .. cpp:function:: Nmod_expr inv(Nmod_expr) Polynomials over integers mod `n` (``nmod_polyxx``) =============================================================================== The class ``nmod_polyxx`` wraps ``nmod_poly_t``. Like ``nmodxx``, instances of ``nmod_polyxx`` always have an associated ``nmodxx_ctx`` storing the operating modulus. No expression may involve more than one modulus at a time. In order to reduce convert a ``fmpz_polyxx`` or ``fmpq_polyxx`` to ``nmod_polyxx``, see the ``reduce`` method of ``fmpz_polyxx`` or ``fmpq_polyxx``, respectively. .. cpp:function:: nmodxx_ctx_srcref Nmod_poly_expr::estimate_ctx() const Obtain the relevant context. This never causes evaluation. .. cpp:function:: Nmod_poly_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``derivative``, ``integral``, ``make_monic``, ``sqrt``. .. cpp:function:: Nmod_poly_expr::binary operation() const The following bina.. cpp:functions are made available as member functions:\\ ``compose_divconquer``, ``compose_horner``, ``div_basecase``,\\ ``div_divconquer``, ``div_newton``, ``divrem``,\\ ``divrem_basecase``, ``divrem_divconquer``,\\ ``divrem_newton``, ``div_root``, ``evaluate_fast``,\\ ``evaluate_iter``, ``gcd``, ``gcd_euclidean``, ``gcd_hgcd``,\\ ``inv_series``, ``inv_series_basecase``, ``inv_series_newton``,\\ ``invsqrt_series``, ``mul_classical``, ``mul_KS``,\\ ``shift_left``, ``shift_right``, ``pow``,\\ ``pow_binexp``, ``rem_basecase``, ``resultant``,\\ ``resultant_euclidean``, ``reverse``, ``revert_series``,\\ ``revert_series_lagrange``, ``revert_series_lagrange_fast``,\\ ``revert_series_newton``, ``sqrt_series``, ``taylor_shift``,\\ ``taylor_shift_convolution``, ``taylor_shift_horner``, ``xgcd``,\\ ``xgcd_euclidean``, ``xgcd_hgcd``, ``log_series``,\\ ``exp_series``, ``exp_series_basecase``, ``atan_series``,\\ ``atanh_series``, ``asin_series``, ``asinh_series``,\\ ``sin_series``, ``cos_series``, ``tan_series``,\\ ``sinh_series``, ``cosh_series``, ``tanh_series``. .. cpp:function:: Nmod_poly_expr Nmod_poly_expr::inflate(T:is_unsigned_integer) const ``See inflate``. .. cpp:function:: Nmod_poly_expr Nmod_poly_expr::deflate(T:is_unsigned_integer) const ``See deflate``. .. cpp:function:: Nmod_poly_expr::ternary operation(??, ??) const The following terna.. cpp:functions are made available as member functions:\\ ``compose_mod``, ``compose_mod_horner``,\\ ``compose_series_brent_kung``, ``compose_series``,\\ ``compose_series_brent_kung``, ``compose_series_divconquer``,\\ ``compose_series_horner``, ``div_newton_n_preinv``,\\ ``divrem_newton_n_preinv``, ``div_series``, ``mulhigh``,\\ ``mulhigh_classical``, ``mullow``, ``mullow_classical``,\\ ``mullow_KS``, ``mulmod``, ``powmod_binexp``, ``pow_trunc``,\\ ``pow_trunc_binexp``. .. cpp:function:: Nmod_poly_expr::fourary operation(??, ??, ??) const The followi.. cpp:functions of four arguments are made available as memb.. cpp:functions: ``compose_mod_brent_kung_preinv``, ``mulmod_preinv``, ``powmod_binexp_preinv``. .. cpp:function:: Nmod_poly_expr Nmod_poly_expr::operator()(Nmod_poly_expr) const .. cpp:function:: Nmod_expr Nmod_poly_expr::operator()(Nmod_expr) const .. cpp:function:: Nmod_vec_expr Nmod_poly_expr::operator()(Nmod_vec_expr) const The ``operator()`` is overloaded for evaluation or composition, depending on the argument. .. cpp:function:: Nmod_poly_expr operator?(??, ??) Arithmetic operators ``+ - * / %`` are overloaded when provided by ``nmod_poly_t``. .. cpp:function:: Nmod_poly_expr operator-(Nmod_poly_expr) The unary negation operator is overloaded. .. cpp:function:: Nmod_poly_target Nmod_poly_target::operator=(const char*) See ``nmod_poly_set_str``. Raises ``flint_exception`` if the string is malformed. Conversion ------------------------------------------------------------------------------- .. cpp:function:: static nmod_polyxx nmod_polyxx::reduce(Fmpz_mod_poly_expr, nmodxx_ctx_srcref) .. cpp:function:: static nmod_polyxx nmod_polyxx::reduce(Fmpq_mod_poly_expr, nmodxx_ctx_srcref) .. cpp:function:: static nmod_polyxx nmod_polyxx::reduce(Fmpz_mod_poly_expr, mp_limb_t) .. cpp:function:: static nmod_polyxx nmod_polyxx::reduce(Fmpq_mod_poly_expr, mp_limb_t) See ``fmpz_poly_get_nmod_poly``. .. cpp:function:: static nmod_polyxx nmod_polyxx::from_ground(Nmod_expr e) .. cpp:function:: static nmod_polyxx nmod_polyxx::from_ground(mp_limb_t e, nmodxx_ctx_srcref c) Consider $e \in \mathbf{Z}/n\mathbf{Z}$ as an element of $\mathbf{Z}/n\mathbf{Z}[X]$. Input and output ------------------------------------------------------------------------------- .. cpp:function:: print(Nmod_poly_expr) .. cpp:function:: print(FILE*, Nmod_poly_expr) .. cpp:function:: read(Nmod_poly_target) .. cpp:function:: read(FILE*, Nmod_poly_target) Memory management ------------------------------------------------------------------------------- .. cpp:function:: nmod_polyxx::nmod_polyxx(mp_limb_t modulus) .. cpp:function:: nmod_polyxx::nmod_polyxx(mp_limb_t modulus, slong alloc) .. cpp:function:: nmod_polyxx::nmod_polyxx(nmodxx_ctx_srcref ctx) .. cpp:function:: nmod_polyxx::nmod_polyxx(nmodxx_ctx_srcref ctx, slong alloc) Instantiate ``nmod_polyxx`` relative to some modulus. If the second argument is provided, space is allocated for ``alloc`` coefficients. .. cpp:function:: nmod_polyxx::nmod_polyxx(const char* str) Instantiate ``nmod_polyxx`` from a string representation. The modulus is parsed (second integer in the string) and the polynomial is initialised with this modulus, then ``nmod_poly_set_str`` is called. Raises ``flint_exception`` if the string is malformed. .. cpp:function:: static nmod_polyxx nmod_polyxx::zero(mp_limb_t n) .. cpp:function:: static nmod_polyxx nmod_polyxx::one(mp_limb_t n) .. cpp:function:: void Nmod_poly_target realloc(slong alloc) .. cpp:function:: void Nmod_poly_target::fit_length(slong len) .. cpp:function:: void Nmod_poly_target::_normalise() Polynomial properties ------------------------------------------------------------------------------- .. cpp:function:: slong Nmod_poly_expr::length() const .. cpp:function:: slong Nmod_poly_expr::degree() const .. cpp:function:: slong Nmod_poly_expr::max_bits() const .. cpp:function:: mp_limb_t Nmod_poly_expr::modulus() const Assignment and basic manipulation ------------------------------------------------------------------------------- .. cpp:function:: void Nmod_poly_target::truncate(slong) .. cpp:function:: void Nmod_poly_target::set_zero() .. cpp:function:: void Nmod_poly_target::set_one() .. cpp:function:: Nmod_poly_expr reverse(Nmod_poly_expr, T:fits_into_slong) Randomisation ------------------------------------------------------------------------------- .. cpp:function:: void Nmod_target::set_randtest(frandxx& state, slong len) .. cpp:function:: void Nmod_target::set_randtest_irreducible(frandxx& state, slong len) .. cpp:function:: static nmod_polyxx nmod_polyxx::randtest(mp_limb_t n, frandxx& state, slong len) .. cpp:function:: static nmod_polyxx nmod_polyxx::randtest_irreducible(mp_limb_t n, frandxx& state, slong len) Getting and setting coefficients ------------------------------------------------------------------------------- .. cpp:function:: Nmodxx_expr Nmod_poly_expr::get_coeff(slong n) const .. cpp:function:: void Nmod_target::set_coeff(slong i, Nmodxx_expr) .. cpp:function:: void Nmod_target::set_coeff(slong i, mp_limb_t) Input and output ------------------------------------------------------------------------------- .. cpp:function:: std::string Nmod_poly_expr::to_string() const .. cpp:function:: std::ostream& operator<<(std::ostream&, Nmod_poly_expr) Output to streams is done by first converting to string. Comparison ------------------------------------------------------------------------------- .. cpp:function:: bool Nmod_poly_expr::is_one() const .. cpp:function:: bool Nmod_poly_expr::is_zero() const .. cpp:function:: bool operator==(Nmod_poly_expr, Nmod_poly_expr) Scalar multiplication and division ------------------------------------------------------------------------------- Scalar multiplication is provided via overloaded ``operator*``. Additionally, the followi.. cpp:functions are implemented: .. cpp:function:: Nmod_poly_expr make_monic(Nmod_poly_expr) Bit packing and unpacking ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr Nmod_poly_expr::bit_pack(T:fits_into_mp_bitcnt_t) const .. cpp:function:: static nmod_polyxx nmod_polyxx::bit_unpack(Fmpz_expr, T:fits_into_mp_bitcnt_t) const Multiplication ------------------------------------------------------------------------------- Basic multiplication is provided via overloaded ``operator*``. Finer control can be obtained using the followi.. cpp:functions. .. cpp:function:: Nmod_poly_expr mul_classical(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr mul_KS(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr mullow(Nmod_poly_expr, Nmod_poly_expr, slong) .. cpp:function:: Nmod_poly_expr mullow_classical(Nmod_poly_expr, Nmod_poly_expr, slong) .. cpp:function:: Nmod_poly_expr mullow_KS(Nmod_poly_expr, Nmod_poly_expr, slong) .. cpp:function:: Nmod_poly_expr mulhigh(Nmod_poly_expr, Nmod_poly_expr, slong) .. cpp:function:: Nmod_poly_expr mulhigh_classical(Nmod_poly_expr, Nmod_poly_expr, slong) .. cpp:function:: Nmod_poly_expr mulmod(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr mulmod_preinv(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) Powering ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_expr pow(Nmod_poly_expr, T:is_unsigned_integer) .. cpp:function:: Nmod_poly_expr pow_binexp(Nmod_poly_expr, T:is_unsigned_integer) .. cpp:function:: Nmod_poly_expr pow_trunc(Nmod_poly_expr, T:is_unsigned_integer, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr pow_trunc_binexp(Nmod_poly_expr, T:is_unsigned_integer, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr powmod_binexp(Nmod_poly_expr, T:is_unsigned_integer, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr powmod_binexp_preinv(Nmod_poly_expr, T:is_unsigned_integer, Nmod_poly_expr, Nmod_poly_expr) Division ------------------------------------------------------------------------------- Basic division and remainder is provided by overloaded ``operator/`` and ``operator%``. Finer control can be obtained using the following functions. .. cpp:function:: Ltuple_expr divrem(Nmod_poly_expr A, Nmod_poly_expr B) .. cpp:function:: Ltuple_expr divrem_basecase(Nmod_poly_expr A, Nmod_poly_expr B) .. cpp:function:: Ltuple_expr divrem_divconquer(Nmod_poly_expr A, Nmod_poly_expr B) .. cpp:function:: Ltuple_expr divrem_newton(Nmod_poly_expr A, Nmod_poly_expr B) .. cpp:function:: Ltuple_expr divrem_newton_n_preinv(Nmod_poly_expr A, Nmod_poly_expr B) .. cpp:function:: Nmod_poly_expr div_basecase(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr div_divconquer(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr div_newton(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr div_newton_n_preinv(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr rem_basecase(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr inv_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr inv_series_basecase(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr inv_series_newton(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr div_series(Nmod_poly_expr, Nmod_poly_expr, slong n) .. cpp:function:: Nmod_poly_expr div_root(Nmod_poly_expr, Nmod_expr) Derivative and integral ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_expr derivative(Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr integral(Nmod_poly_expr) Evaluation ------------------------------------------------------------------------------- Basic evaluation and multipoint evaluation can be achieved using the overloaded ``operator()``. Finer control can be obtained using the followi.. cpp:functions. .. cpp:function:: Nmod_expr evaluate(Nmod_poly_expr, Nmod_expr) .. cpp:function:: Nmod_vec_expr evaluate(Nmod_poly_expr, Nmod_vec_expr) .. cpp:function:: Nmod_vec_expr evaluate_fast(Nmod_poly_expr, Nmod_vec_expr) .. cpp:function:: Nmod_vec_expr evaluate_iter(Nmod_poly_expr, Nmod_vec_expr) Interpolation ------------------------------------------------------------------------------- .. cpp:function:: static Nmod_poly_expr fmpz_polyxx::interpolate(Nmod_vec_expr xs, Nmod_vec_expr ys) .. cpp:function:: static Nmod_poly_expr fmpz_polyxx::interpolate_barycentric(Nmod_vec_expr xs, Nmod_vec_expr ys) .. cpp:function:: static Nmod_poly_expr fmpz_polyxx::interpolate_fast(Nmod_vec_expr xs, Nmod_vec_expr ys) .. cpp:function:: static Nmod_poly_expr fmpz_polyxx::interpolate_newton(Nmod_vec_expr xs, Nmod_vec_expr ys) Composition ------------------------------------------------------------------------------- Basic composition can be achieved with the overloaded ``operator()``. Finer control can be obtained using the followi.. cpp:functions. .. cpp:function:: Nmod_poly_expr compose(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr compose_horner(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr compose_divconquer(Nmod_poly_expr, Nmod_poly_expr) Taylor Shift ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_expr taylor_shift(Nmod_poly_expr, Nmod_expr) .. cpp:function:: Nmod_poly_expr taylor_shift_horner(Nmod_poly_expr, Nmod_expr) .. cpp:function:: Nmod_poly_expr taylor_shift_convolution(Nmod_poly_expr, Nmod_expr) Modular composition ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_expr compose_mod(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr compose_mod_horner(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr compose_mod_divconquer(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr compose_mod_brent_kung(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr compose_mod_brent_kung_preinv(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) Greatest common divisor ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_expr gcd(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr gcd_euclidean(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_poly_expr gcd_hgcd(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Ltuple_expr xgcd(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Ltuple_expr xgcd_euclidean(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Ltuple_expr xgcd_hgcd(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_expr resultant(Nmod_poly_expr, Nmod_poly_expr) .. cpp:function:: Nmod_expr resultant_euclidean(Nmod_poly_expr, Nmod_poly_expr) Power series composition ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_expr compose_series(Nmod_poly_expr, Nmod_poly_expr, slong) .. cpp:function:: Nmod_poly_expr compose_series_horner(Nmod_poly_expr, Nmod_poly_expr, slong) .. cpp:function:: Nmod_poly_expr compose_series_brent_kung(Nmod_poly_expr, Nmod_poly_expr, slong) .. cpp:function:: Nmod_poly_expr compose_series_divconquer(Nmod_poly_expr, Nmod_poly_expr, slong) Power series reversion ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_expr revert_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr revert_series_newton(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr revert_series_lagrange(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr revert_series_lagrange_fast(Nmod_poly_expr, T:fits_into_slong) Square roots ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_expr sqrt_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr invsqrt_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr sqrt_series(Nmod_poly_expr p) Compute the square root of $p$. Raises ``flint_exception`` if $p$ is not a perfect square. Transcendent.. cpp:functions ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_expr exp_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr log_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr atan_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr atanh_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr asin_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr asinh_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr tan_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr sin_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr cos_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr sinh_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr cosh_series(Nmod_poly_expr, T:fits_into_slong) .. cpp:function:: Nmod_poly_expr tanh_series(Nmod_poly_expr, T:fits_into_slong) Products ------------------------------------------------------------------------------- .. cpp:function:: static Nmod_poly_expr fmpz_polyxx::product_roots(Nmod_vec_expr xs) Inflation and deflation ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_expr inflate(Nmod_poly_expr, T:is_unsigned_integer) .. cpp:function:: Nmod_poly_expr deflate(Nmod_poly_expr, T:is_unsigned_integer) .. cpp:function:: slong Nmod_poly_expr::deflation() const Factorisation ------------------------------------------------------------------------------- .. cpp:function:: bool Nmod_poly_expr::is_squarefree() const .. cpp:function:: bool Nmod_poly_expr::is_irreducible() const .. cpp:function:: slong Nmod_poly_target::remove(Nmod_poly_expr) .. cpp:function:: nmod_poly_factorxx::nmod_poly_factorxx() Initialise an empty factorisation. .. cpp:function:: nmod_poly_factorxx::nmod_poly_factorxx(const nmod_poly_factorxx& o) Copy a factorisation. .. cpp:function:: bool nmod_poly_factorxx::operator==(const nmod_poly_factorxx&) Compare two factorisations. .. cpp:function:: ulong nmod_poly_factorxx::size() const Return the number of stored factors. .. cpp:function:: slong nmod_poly_factorxx::exp(slong i) const .. cpp:function:: slong& nmod_poly_factorxx::exp(slong i) Obtain the exponent of the ith factor. .. cpp:function:: nmod_polyxx_srcref nmod_poly_factorxx::p(slong i) const .. cpp:function:: nmod_polyxx_ref nmod_poly_factorxx::p(slong i) Obtain the ith factor. .. cpp:function:: void nmod_poly_factorxx::realloc(slong a) .. cpp:function:: void nmod_poly_factorxx::fit_length(slong a) .. cpp:function:: void nmod_poly_factorxx::insert(Nmod_poly_expr p, slong e) .. cpp:function:: void nmod_poly_factorxx::concat(const nmod_poly_factorxx&) .. cpp:function:: void nmod_poly_factorxx::set_factor(Nmod_poly_expr) .. cpp:function:: void nmod_poly_factorxx::set_factor_cantor_zassenhaus(Nmod_poly_expr) .. cpp:function:: void nmod_poly_factorxx::set_factor_berlekamp(Nmod_poly_expr) .. cpp:function:: void nmod_poly_factorxx::set_factor_kaltofen_shoup(Nmod_poly_expr) .. cpp:function:: void nmod_poly_factorxx::set_factor_with_cantor_zassenhaus(Nmod_poly_expr) .. cpp:function:: void nmod_poly_factorxx::set_factor_with_berlekamp(Nmod_poly_expr) .. cpp:function:: void nmod_poly_factorxx::set_factor_with_kaltofen_shoup(Nmod_poly_expr) .. cpp:function:: void nmod_poly_factorxx::set_factor_squarefree(Nmod_poly_expr) Factorise a polynomial and store its factors. See ``nmod_poly_factor`` etc. .. cpp:function:: void nmod_poly_factorxx::set_factor_equal_deg_probab(frandxx&, Nmod_poly_expr, slong) .. cpp:function:: void nmod_poly_factorxx::set_factor_equal_deg(Nmod_poly_expr, slong) See ``nmod_poly_factor_equal_deg_prob`` and ``nmod_poly_factor_equal_deg``. .. cpp:function:: void nmod_poly_factorxx::set_factor_distinct_deg(Nmod_poly_expr p, std::vector& degs) See ``nmod_poly_factor_distinct_deg``. Note that ``degs`` must have sufficient size to hold all factors. The size of ``degs`` is not modified. .. cpp:function:: nmod_poly_factorxx factor(Nmod_poly_expr) .. cpp:function:: nmod_poly_factorxx factor_cantor_zassenhaus(Nmod_poly_expr) .. cpp:function:: nmod_poly_factorxx factor_berlekamp(Nmod_poly_expr) .. cpp:function:: nmod_poly_factorxx factor_kaltofen_shoup(Nmod_poly_expr) .. cpp:function:: nmod_poly_factorxx factor_with_cantor_zassenhaus(Nmod_poly_expr) .. cpp:function:: nmod_poly_factorxx factor_with_berlekamp(Nmod_poly_expr) .. cpp:function:: nmod_poly_factorxx factor_with_kaltofen_shoup(Nmod_poly_expr) .. cpp:function:: nmod_poly_factorxx factor_squarefree(Nmod_poly_expr) Matrices of integers mod `n` (``nmod_mat``) =============================================================================== The class ``nmod_matxx`` wraps ``nmod_mat_t``. Like ``nmodxx``, instances of ``nmod_matxx`` always have an associated ``nmodxx_ctx`` storing the operating modulus. No expression may involve more than one modulus at a time. Like ``fmpz_matxx``, many operations on ``nmod_matxx`` do not support aliasing. The details can be found in the documentation of ``nmod_mat_t``. Since ``nmod_matxx`` does not use temporary merging, evaluation of subexpressions never creates new aliases. =============================================================================== .. cpp:function:: nmodxx_ctx_srcref Nmod_mat_expr::estimate_ctx() const Obtain the relevant context. This never causes evaluation. .. cpp:function:: Nmod_mat_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``inv``, ``transpose``, ``trace``, ``det``. .. cpp:function:: Nmod_mat_expr::binary operation(??) const The following bina.. cpp:functions are made available as member functions: ``solve``, ``mul_classical``, ``mul_strassen``. .. cpp:function:: Nmod_mat_expr::ternary operation(??, ??) const The following terna.. cpp:functions are made available as member functions: ``solve_tril``, ``solve_tril_recursive``, ``solve_tril_classical``, ``solve_triu``, ``solve_triu_recursive``, ``solve_triu_classical``. .. cpp:function:: Nmod_mat_expr operator?(??, ??) Arithmetic operators ``+ - *`` are overloaded when provided by ``nmod_mat_t``. .. cpp:function:: Nmod_mat_expr operator-(Nmod_mat_expr) The unary negation operator is overloaded. Conversion ------------------------------------------------------------------------------- .. cpp:function:: static nmod_matxx::reduce(Fmpz_mat_expr, mp_limb_t modulus) See ``fmpz_mat_get_nmod_mat``. Input and output ------------------------------------------------------------------------------- .. cpp:function:: int print(Nmod_mat_expr) Memory management ------------------------------------------------------------------------------- .. cpp:function:: nmod_matxx::nmod_matxx(slong m, slong n, mp_limb_t modulus) See ``nmod_mat_init``. Basic properties and manipulation ------------------------------------------------------------------------------- .. cpp:function:: ?? Nmod_mat_expr::at(T:fits_into_slong, U:fits_into_slong) const Unified coefficient access to the matrix entries. .. cpp:function:: slong Nmod_mat_expr::rows() const .. cpp:function:: slong Nmod_mat_expr::cols() const Obtain the number of rows/columns in this matrix. The.. cpp:functions never cause evaluation (the matrix size is computed from the operations in the expression template and the size of the input matrices). .. cpp:function:: bool Nmod_mat_expr::is_zero() const .. cpp:function:: bool Nmod_mat_expr::is_empty() const .. cpp:function:: bool Nmod_mat_expr::is_square() const .. cpp:function:: mp_limb_t Nmod_mat_expr::modulus() const .. cpp:function:: void Nmod_mat_target::set_zero() .. cpp:function:: static nmod_matxx nmod_matxx::zero(slong rows, slong cols, mp_limb_t modulus) See ``nmod_mat_zero``. Random matrix generation ------------------------------------------------------------------------------- .. cpp:function:: void Nmod_mat_target::set_randtest(frandxx&) .. cpp:function:: void Nmod_mat_target::set_randfull(frandxx&) .. cpp:function:: void Nmod_mat_target::set_randrank(frandxx&, slong rank) .. cpp:function:: void Nmod_mat_target::set_randtril(frandxx&, bool unit) .. cpp:function:: void Nmod_mat_target::set_randtriu(frandxx&, bool unit) See ``nmod_mat_randtest`` etc. .. cpp:function:: static nmod_matxx nmod_matxx::randtest(slong rows, slong cols, mp_limb_t M, frandxx&) .. cpp:function:: static nmod_matxx nmod_matxx::randfull(slong rows, slong cols, mp_limb_t M, frandxx&) .. cpp:function:: static nmod_matxx nmod_matxx::randrank(slong rows, slong cols, mp_limb_t M, frandxx&, slong rank) .. cpp:function:: static nmod_matxx nmod_matxx::randtril(slong rows, slong cols, mp_limb_t M, frandxx&, bool unit) .. cpp:function:: static nmod_matxx nmod_matxx::randtriu(slong rows, slong cols, mp_limb_t M, frandxx&, bool unit) Static versions of the above. .. cpp:function:: int Nmod_mat_target::set_randpermdiag(frandxx&, const Vec& v) ``M.set_randpermdiag(Rand, V)`` has the same effect as ``nmod_mat_randpermdiag(m, rand, V._array(), V.size())``, where ``m`` and ``rand`` are the underlying C structs corresponding to ``M`` and ``Rand``. One possibility for Vec is ``nmod_vecxx``. .. cpp:function:: void Nmod_target::apply_randops(frandxx&, slong count) See ``nmod_mat_randops``. Transpose ------------------------------------------------------------------------------- .. cpp:function:: Nmod_mat_expr transpose(Nmod_mat_expr) Matrix multiplication ------------------------------------------------------------------------------- The overloaded ``operator*`` can be used for both matrix-matrix and matrix-scalar multiplication. Finer control can be obtained with the following functions. .. cpp:function:: Nmod_mat_expr mul_classical(Nmod_mat_expr, Nmod_mat_expr) .. cpp:function:: Nmod_mat_expr mul_strassen(Nmod_mat_expr, Nmod_mat_expr) Trace ------------------------------------------------------------------------------- .. cpp:function:: Nmod_expr trace(Nmod_mat_expr) Determinant and rank ------------------------------------------------------------------------------- .. cpp:function:: Nmod_expr det(Nmod_mat_expr) .. cpp:function:: slong rank(Nmod_mat_expr) Inverse ------------------------------------------------------------------------------- .. cpp:function:: Nmod_mat_expr inv(Nmod_mat_expr A) Compute the inverse of the square matrix $A$. Raises ``flint_exception`` if $A$ is singular. The modulus is required to be prime. Triangular solving ------------------------------------------------------------------------------- .. cpp:function:: Nmod_mat_expr solve_triu(Nmod_mat_expr, Nmod_mat_expr, bool unit) .. cpp:function:: Nmod_mat_expr solve_triu_classical(Nmod_mat_expr, Nmod_mat_expr, bool unit) .. cpp:function:: Nmod_mat_expr solve_triu_recursive(Nmod_mat_expr, Nmod_mat_expr, bool unit) .. cpp:function:: Nmod_mat_expr solve_tril(Nmod_mat_expr, Nmod_mat_expr, bool unit) .. cpp:function:: Nmod_mat_expr solve_tril_classical(Nmod_mat_expr, Nmod_mat_expr, bool unit) .. cpp:function:: Nmod_mat_expr solve_tril_recursive(Nmod_mat_expr, Nmod_mat_expr, bool unit) Non-singular square solving ------------------------------------------------------------------------------- .. cpp:function:: Nmod_mat_expr solve(Nmod_mat_expr B, Nmod_mat_expr X) .. cpp:function:: Nmod_vec_expr solve(Nmod_mat_expr B, Nmod_vec_expr X) See ``nmod_mat_solve`` and ``nmod_mat_solve_vec``. Raises ``flint_exception`` if $B$ is singular. LU decomposition ------------------------------------------------------------------------------- .. cpp:function:: Tuple Nmod_mat_target::set_lu(bool rank_check = false) .. cpp:function:: Tuple Nmod_mat_target::set_lu_classical(bool rank_check = false) .. cpp:function:: Tuple Nmod_mat_target::set_lu_recursive(bool rank_check = false) See ``nmod_mat_lu`` etc. Reduced row echelon form ------------------------------------------------------------------------------- .. cpp:function:: void Nmod_mat_target::set_rref() Nullspace ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr nullspace(Nmod_mat_expr) Matrices of polynomials over integers mod `n` (``nmod_poly_matxx``) =============================================================================== The class ``nmod_poly_matxx`` wraps ``nmod_poly_mat_t``. Like ``nmod_matxx``, instances of ``nmod_poly_matxx`` always have an associated ``nmodxx_ctx`` storing the operating modulus. No expression may involve more than one modulus at a time. Contrary to ``nmod_poly_mat_t``, it is \emph{not} valid to use instances of ``nmod_poly_matxx`` with zero rows or columns. Like ``fmpz_matxx``, many operations on ``nmod_poly_matxx`` do not support aliasing. The details can be found in the documentation of ``nmod_poly_mat_t``. Since ``nmod_poly_matxx`` does not use temporary merging, evaluation of subexpressions never creates new aliases. Miscellaneous ------------------------------------------------------------------------------- .. cpp:function:: nmodxx_ctx_srcref Nmod_poly_mat_expr::estimate_ctx() const Obtain the relevant context. This never causes evaluation. .. cpp:function:: Nmod_poly_mat_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``det``, ``det_fflu``, ``det_interpolate``, ``trace``, ``sqr``, ``sqr_classical``, ``sqr_interpolate``, ``sqr_KS``, ``transpose``. .. cpp:function:: Nmod_poly_mat_expr::binary operation(??) const The following bina.. cpp:functions are made available as member functions: ``solve``, ``solve_fflu``, ``mul_classical``, ``mul_interpolate``, ``mul_KS``, ``pow``. .. cpp:function:: Nmod_mat_expr Nmod_poly_mat_expr::operator()(Nmod_expr) const ``operator()`` is overloaded for matrix evaluation. .. cpp:function:: Nmod_poly_mat_expr operator?(??, ??) Arithmetic operators ``+ - *`` are overloaded when provided by ``nmod_poly_mat_t``. .. cpp:function:: Nmod_poly_mat_expr operator-(Nmod_poly_mat_expr) The unary negation operator is overloaded. Input and output ------------------------------------------------------------------------------- .. cpp:function:: int print_pretty(Nmod_poly_mat_expr, const char*) Memory management ------------------------------------------------------------------------------- .. cpp:function:: nmod_poly_matxx::nmod_poly_matxx(slong m, slong n, mp_limb_t modulus) See ``nmod_poly_mat_init``. Basic assignment and manipulation ------------------------------------------------------------------------------- .. cpp:function:: ?? Nmod_poly_mat_expr::at(T:fits_into_slong, U:fits_into_slong) const Unified coefficient access to the matrix entries. Standard matrices ------------------------------------------------------------------------------- .. cpp:function:: static nmod_poly_matxx nmod_poly_matxx::zero(slong rows, slong cols, mp_limb_t n) .. cpp:function:: static nmod_poly_matxx nmod_poly_matxx::one(slong rows, slong cols, mp_limb_t n) .. cpp:function:: void Nmod_poly_mat_target::set_zero() .. cpp:function:: void Nmod_poly_mat_target::set_one() Random matrix generation ------------------------------------------------------------------------------- .. cpp:function:: void Nmod_poly_mat_target::set_randtest(frandxx&, slong) .. cpp:function:: void Nmod_poly_mat_target::set_randtest_sparse(frandxx&, slong, float) .. cpp:function:: static nmod_poly_matxx nmod_poly_matxx::randtest(slong rows, slong cols, mp_limb_t n, slong len) .. cpp:function:: static nmod_poly_matxx nmod_poly_matxx::randtest_sparse(slong rows, slong cols, mp_limb_t n, slong len, float density) See ``nmod_poly_mat_randtest`` etc. Basic comparison and properties ------------------------------------------------------------------------------- .. cpp:function:: slong Nmod_poly_mat_expr::rows() const .. cpp:function:: slong Nmod_poly_mat_expr::cols() const Obtain the number of rows/columns in this matrix. The.. cpp:functions never cause evaluation (the matrix size is computed from the operations in the expression template and the size of the input matrices). .. cpp:function:: bool Nmod_poly_mat_expr::is_zero() const .. cpp:function:: bool Nmod_poly_mat_expr::is_one() const .. cpp:function:: bool Nmod_poly_mat_expr::is_empty() const .. cpp:function:: bool Nmod_poly_mat_expr::is_square() const .. cpp:function:: mp_limb_t Nmod_poly_mat_expr::modulus() const Norms ------------------------------------------------------------------------------- .. cpp:function:: slong Nmod_poly_mat_expr::max_length() const Arithmetic ------------------------------------------------------------------------------- The overloaded operators ``+ - *`` can be used for both matrix-matrix and matrix-scalar multiplication, and matrix-matrix addition/subtraction. Finer control can be obtained with the followi.. cpp:functions. .. cpp:function:: Nmod_poly_mat_expr mul_classical(Nmod_poly_mat_expr, Nmod_poly_mat_expr) .. cpp:function:: Nmod_poly_mat_expr mul_interpolate(Nmod_poly_mat_expr, Nmod_poly_mat_expr) Row reduction ------------------------------------------------------------------------------- Beware that compared to the C interface, the flintxx row reduction interface changes some argument orders. This is to facilitate default arguments. .. cpp:function:: slong find_pivot_any(Nmod_poly_mat_expr, slong, slong, slong) See ``nmod_poly_mat_find_pivot_any``. .. cpp:function:: slong find_pivot_partial(Nmod_poly_mat_expr, slong, slong, slong) See ``nmod_poly_mat_find_pivot_partial``. .. cpp:function:: Ltuple_expr fflu(Nmod_poly_mat_expr A, permxx* perm = 0, bool rankcheck = false) See ``nmod_poly_mat_fflu``. .. cpp:function:: Ltuple_expr rref(Nmod_poly_mat_expr A) See ``nmod_poly_mat_rref``. Transpose ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_mat_expr transpose(Nmod_poly_mat_expr A) Compute the transpose of $A$. Trace ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_expr trace(Nmod_poly_mat_expr) Determinant and rank ------------------------------------------------------------------------------- .. cpp:function:: Nmod_poly_expr det(Nmod_poly_mat_expr) .. cpp:function:: Nmod_poly_expr det_fflu(Nmod_poly_mat_expr) .. cpp:function:: Nmod_poly_expr det_interpolate(Nmod_poly_mat_expr) .. cpp:function:: slong rank(Nmod_poly_mat_expr) Inverse ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr inv(Nmod_poly_mat_expr A) ``ltupleref(worked, M, P) = inv(A)`` has the same effect as ``worked = nmod_poly_mat_inv(m, p, a)``, where ``m, p, a`` are the C structs underlying ``M, P, A``. Nullspace ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr nullspace(Nmod_poly_mat_expr) Solving ------------------------------------------------------------------------------- .. cpp:function:: Ltuple_expr solve(Nmod_poly_mat_expr, Nmod_poly_mat_expr) .. cpp:function:: Ltuple_expr solve_fflu(Nmod_poly_mat_expr, Nmod_poly_mat_expr) .. cpp:function:: Ltuple_expr solve_fflu_precomp(const permxx&, Nmod_poly_mat_expr B, Nmod_poly_mat_expr FFLU, Nmod_poly_mat_expr X) ``ltupleref(worked, M, P) = solve(A, X)`` has the same effect as ``worked = nmod_poly_mat_solve(m, p, a, x)``, where ``m, p, a, x`` are the C structs underlying ``M, P, A, X``. Polynomials over integers mod `n` (``fmpz_mod_poly``) =============================================================================== .. cpp:function:: Fmpz_mod_poly_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``derivative``, ``integral``, ``make_monic``, ``sqr``. .. cpp:function:: Fmpz_mod_poly_expr::binary operation() const The following bina.. cpp:functions are made available as member functions:\\ ``compose_divconquer``, ``compose_horner``, ``div_basecase``,\\ ``div_divconquer``, ``div_newton``, ``divrem``,\\ ``divrem_basecase``, ``divrem_divconquer``,\\ ``divrem``, ``divrem_f``,\\ ``gcd``, ``gcd_euclidean``, ``gcd_euclidean_f``, ``gcd_f``,\\ ``gcdinv``, ``invmod``, ``inv_series_newton``,\\ ``shift_left``, ``shift_right``, ``pow``,\\ ``rem_basecase``, ``xgcd``, ``xgcd_euclidean``. .. cpp:function:: Fmpz_mod_poly_expr::ternary operation(??, ??) const The following terna.. cpp:functions are made available as member functions:\\ ``compose_mod``, ``compose_mod_horner``,\\ ``compose_series_brent_kung``, ``mullow``,\\ ``mulmod``, ``powmod_binexp``, ``pow_trunc``,\\ ``pow_trunc_binexp``. .. cpp:function:: Fmpz_mod_poly_expr Fmpz_mod_poly_expr::operator()(Fmpz_mod_poly_expr) const .. cpp:function:: Fmpz_mod_expr Fmpz_mod_poly_expr::operator()(Fmpz_mod_expr) const The ``operator()`` is overloaded for evaluation or composition, depending on the argument. .. cpp:function:: Fmpz_mod_poly_expr operator?(??, ??) Arithmetic operators ``+ - * %`` are overloaded when provided by ``nmod_poly_t``. .. cpp:function:: Fmpz_mod_poly_expr operator-(Fmpz_mod_poly_expr) The unary negation operator is overloaded. Input and output ------------------------------------------------------------------------------- .. cpp:function:: print(Fmpz_mod_poly_expr) .. cpp:function:: print(FILE*, Fmpz_mod_poly_expr) .. cpp:function:: print_pretty(Fmpz_mod_poly_expr, const char* var) .. cpp:function:: print_pretty(FILE*, Fmpz_mod_poly_expr, const char* var) .. cpp:function:: read(Fmpz_mod_poly_target) .. cpp:function:: read(FILE*, Fmpz_mod_poly_target) Memory management ------------------------------------------------------------------------------- .. cpp:function:: fmpz_mod_polyxx::fmpz_mod_polyxx(Fmpz_expr n) .. cpp:function:: fmpz_mod_polyxx::fmpz_mod_polyxx(Fmpz_expr n, slong alloc) .. cpp:function:: void Fmpz_mod_poly_target realloc(slong alloc) .. cpp:function:: void Fmpz_mod_poly_target::fit_length(slong len) .. cpp:function:: void Fmpz_mod_poly_target::_normalise() .. cpp:function:: void Fmpz_mod_poly_target::truncate(slong) Randomisation ------------------------------------------------------------------------------- .. cpp:function:: void Fmpz_mod_poly_mat_target::set_randtest(frandxx&, slong) .. cpp:function:: void Fmpz_mod_poly_mat_target::set_randtest_irreducible(frandxx&, slong) .. cpp:function:: void Fmpz_mod_poly_mat_target::set_randtest_not_zero(frandxx&, slong) See ``fmpz_mod_poly_randtest``, etc. .. cpp:function:: static fmpz_mod_polyxx fmpz_mod_polyxx::randtest(Fmpz_expr, frandx&, slong) .. cpp:function:: static fmpz_mod_polyxx fmpz_mod_polyxx::randtest_not_zero(Fmpz_expr, frandx&, slong) .. cpp:function:: static fmpz_mod_polyxx fmpz_mod_polyxx::randtest_irreducible(Fmpz_expr, frandx&, slong) Static versions of the above. Attributes ------------------------------------------------------------------------------- .. cpp:function:: fmpzxx_srcref Fmpz_mod_poly_mat_expr::modulus() const Obtain the relevant modulus. This never causes evaluation. .. cpp:function:: slong Fmpz_mod_poly_expr::length() const .. cpp:function:: slong Fmpz_mod_poly_expr::degree() const .. cpp:function:: ?? Fmpz_mod_poly_expr::lead() const Unified coefficient access for the leading coefficient. The result is undefined if the length of the polynomial is zero. Assignment and swap ------------------------------------------------------------------------------- .. cpp:function:: void Fmpz_mod_poly_target::zero_coeffs(slong i, slong j) .. cpp:function:: void Fmpz_mod_poly_target::set_zero() .. cpp:function:: static fmpz_mod_polyxx fmpz_mod_polyxx::zero(Fmpz_expr m) Conversion ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_mod_poly_target Fmpz_mod_poly_target::operator=(T:is_unsigned_integer) .. cpp:function:: Fmpz_mod_poly_target Fmpz_mod_poly_target::operator=(Fmpz_expr) .. cpp:function:: Fmpz_mod_poly_target Fmpz_mod_poly_target::operator=(Fmpz_poly_expr) See ``fmpz_mod_poly_set_ui``, ``fmpz_mod_poly_set_fmpz`` and ``fmpz_mod_poly_set_fmpz_poly``. .. cpp:function:: Fmpz_poly_expr Fmpz_mod_poly_expr::to() const Comparison ------------------------------------------------------------------------------- .. cpp:function:: bool Fmpz_mod_poly_expr::is_zero() const Getting and setting coefficients ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr Fmpz_mod_poly_expr::get_coeff(slong n) const .. cpp:function:: void Fmpz_mod_target::set_coeff(slong i, Fmpz_expr) .. cpp:function:: void Fmpz_mod_target::set_coeff(slong i, T:is_unsigned_integer) Shifting ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_mod_poly_expr shift_left(Fmpz_mod_poly_expr, T:fits_into_slong) .. cpp:function:: Fmpz_mod_poly_expr shift_right(Fmpz_mod_poly_expr, T:fits_into_slong) Multiplication ------------------------------------------------------------------------------- The overloaded ``operator*`` can be used for both poly-poly and poly-scalar multiplication. Finer control can be obtained using the followi.. cpp:functions. .. cpp:function:: Fmpz_mod_poly_expr mullow(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr, slong) .. cpp:function:: Fmpz_mod_poly_expr sqr(Fmpz_mod_poly_expr) .. cpp:function:: Fmpz_mod_poly_expr mulmod(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Powering ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_mod_poly_expr pow(Fmpz_mod_poly_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_mod_poly_expr pow_binexp(Fmpz_mod_poly_expr, T:is_unsigned_integer) .. cpp:function:: Fmpz_mod_poly_expr pow_trunc(Fmpz_mod_poly_expr, T:is_unsigned_integer, T:fits_into_slong) .. cpp:function:: Fmpz_mod_poly_expr pow_trunc_binexp(Fmpz_mod_poly_expr, T:is_unsigned_integer, T:fits_into_slong) .. cpp:function:: Fmpz_mod_poly_expr powmod_binexp(Fmpz_mod_poly_expr, T:is_unsigned_integer, Fmpz_mod_poly_expr) .. cpp:function:: Fmpz_mod_poly_expr powmod_binexp(Fmpz_mod_poly_expr, Fmpz_expr, Fmpz_mod_poly_expr) Division ------------------------------------------------------------------------------- The overloaded operators ``/ %`` can be used for division and remainder. Finer control can be obtained using the followi.. cpp:functions. .. cpp:function:: Ltuple_expr divrem(Fmpz_mod_poly_expr A, Fmpz_mod_poly_expr B) .. cpp:function:: Ltuple_expr divrem_basecase(Fmpz_mod_poly_expr A, Fmpz_mod_poly_expr B) .. cpp:function:: Ltuple_expr divrem_divconquer(Fmpz_mod_poly_expr A, Fmpz_mod_poly_expr B) .. cpp:function:: Ltuple_expr divrem_f(Fmpz_mod_poly_expr A, Fmpz_mod_poly_expr B) .. cpp:function:: Fmpz_mod_poly_expr div_basecase(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Fmpz_mod_poly_expr rem_basecase(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Fmpz_mod_poly_expr rem(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: slong Fmpz_mod_poly_target::remove(Fmpz_mod_poly_expr) Power series inversion ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_mod_poly_expr inv_series_newton(Fmpz_mod_poly_expr, T:fits_into_slong) Greatest common divisor ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_mod_poly_expr gcd(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Fmpz_mod_poly_expr gcd_euclidean(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Ltuple_expr xgcd(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Ltuple_expr xgcd_euclidean(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Ltuple_expr gcdinv(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Ltuple_expr gcd_f(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Ltuple_expr gcd_euclidean_f(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Fmpz_mod_poly_expr invmod(Fmpz_mod_poly_expr f, Fmpz_mod_poly_expr g) See ``fmpz_mod_poly_invmod``. Raises ``flint_exception`` if $f$ and $g$ are not coprime. Derivative ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_mod_poly_expr derivative(Fmpz_mod_poly_expr) Evaluation ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_mod_expr evaluate(Fmpz_mod_poly_expr, Fmpz_mod_expr) Composition ------------------------------------------------------------------------------- Basic composition can be achieved with the overloaded ``operator()``. Finer control can be obtained using the followi.. cpp:functions. .. cpp:function:: Fmpz_mod_poly_expr compose(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Fmpz_mod_poly_expr compose_horner(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Fmpz_mod_poly_expr compose_divconquer(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Modular composition ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_mod_poly_expr compose_mod(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Fmpz_mod_poly_expr compose_mod_horner(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Fmpz_mod_poly_expr compose_mod_divconquer(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) .. cpp:function:: Fmpz_mod_poly_expr compose_mod_brent_kung(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Radix conversion ------------------------------------------------------------------------------- .. cpp:function:: fmpz_mod_poly_radixxx::fmpz_mod_poly_radixxx(Fmpz_poly_expr, slong deg) Initialise temporary data for radix conversion. See ``fmpz_mod_poly_radix_init``. .. cpp:function:: Fmpz_mod_poly_vec_expr Fmpz_mod_poly_expr::radix(const fmpz_mod_poly_radxxx&) .. cpp:function:: Fmpz_mod_poly_vec_expr radix(Fmpz_mod_poly_expr F, const fmpz_mod_poly_radxxx&) Perform radix conversion. See ``fmpz_mod_poly_radix``. Note that computing the output vector size requires knowing the degree of ``F``. In the current implementation, this will result in evaluating ``F`` twice. In order to avoid this, pass in ``F`` in evaluated form, or do not form expressions requiring temporaries. Factoring polynomials over the integers mod `n` (``fmpz_mod_poly_factor``) =============================================================================== .. cpp:function:: bool Fmpz_mod_poly_expr::is_squarefree() const .. cpp:function:: bool Fmpz_mod_poly_expr::is_irreducible() const .. cpp:function:: bool Fmpz_mod_poly_expr::is_irreducible_ddf() const .. cpp:function:: bool Fmpz_mod_poly_expr::is_irreducible_rabin() const .. cpp:function:: slong Fmpz_mod_poly_target::remove(Fmpz_mod_poly_expr) .. cpp:function:: fmpz_mod_poly_factorxx::nmod_poly_factorxx() Initialise an empty factorisation. .. cpp:function:: fmpz_mod_poly_factorxx::nmod_poly_factorxx(const nmod_poly_factorxx& o) Copy a factorisation. .. cpp:function:: bool fmpz_mod_poly_factorxx::operator==(const nmod_poly_factorxx&) Compare two factorisations. .. cpp:function:: ulong fmpz_mod_poly_factorxx::size() const Return the number of stored factors. .. cpp:function:: slong fmpz_mod_poly_factorxx::exp(slong i) const .. cpp:function:: slong& fmpz_mod_poly_factorxx::exp(slong i) Obtain the exponent of the ith factor. .. cpp:function:: fmpz_mod_polyxx_srcref nmod_poly_factorxx::p(slong i) const .. cpp:function:: fmpz_mod_polyxx_ref nmod_poly_factorxx::p(slong i) Obtain the ith factor. .. cpp:function:: void fmpz_mod_poly_factorxx::realloc(slong a) .. cpp:function:: void fmpz_mod_poly_factorxx::fit_length(slong a) .. cpp:function:: void fmpz_mod_poly_factorxx::insert(Fmpz_mod_poly_expr p, slong e) .. cpp:function:: void fmpz_mod_poly_factorxx::concat(const nmod_poly_factorxx&) .. cpp:function:: void fmpz_mod_poly_factorxx::set_factor(Fmpz_mod_poly_expr) .. cpp:function:: void fmpz_mod_poly_factorxx::set_factor_cantor_zassenhaus(Fmpz_mod_poly_expr) .. cpp:function:: void fmpz_mod_poly_factorxx::set_factor_berlekamp(Fmpz_mod_poly_expr) .. cpp:function:: void fmpz_mod_poly_factorxx::set_factor_kaltofen_shoup(Fmpz_mod_poly_expr) .. cpp:function:: void fmpz_mod_poly_factorxx::set_factor_squarefree(Fmpz_mod_poly_expr) Factorise a polynomial and store its factors. See ``fmpz_mod_poly_factor`` etc. .. cpp:function:: void fmpz_mod_poly_factorxx::set_factor_equal_deg_probab(frandxx&, Fmpz_mod_poly_expr, slong) .. cpp:function:: void fmpz_mod_poly_factorxx::set_factor_equal_deg(Fmpz_mod_poly_expr, slong) See ``fmpz_mod_poly_factor_equal_deg_prob`` and ``fmpz_mod_poly_factor_equal_deg``. .. cpp:function:: void fmpz_mod_poly_factorxx::set_factor_distinct_deg(Fmpz_mod_poly_expr p, std::vector& degs) See ``fmpz_mod_poly_factor_distinct_deg``. Note that ``degs`` must have sufficient size to hold all factors. The size of ``degs`` is not modified. .. cpp:function:: fmpz_mod_poly_factorxx factor(Fmpz_mod_poly_expr) .. cpp:function:: fmpz_mod_poly_factorxx factor_cantor_zassenhaus(Fmpz_mod_poly_expr) .. cpp:function:: fmpz_mod_poly_factorxx factor_berlekamp(Fmpz_mod_poly_expr) .. cpp:function:: fmpz_mod_poly_factorxx factor_kaltofen_shoup(Fmpz_mod_poly_expr) .. cpp:function:: fmpz_mod_poly_factorxx factor_squarefree(Fmpz_mod_poly_expr) P-adics (``padic``) =============================================================================== The type ``padicxx`` wraps the C interface ``padic_t``, and the type ``padicxx_ctx`` wraps ``padic_ctx_t``. Evaluating composite expressions requires temporary objects, which must be initialised to a certain precision and with a certain context. The padicxx library employs the following rules: - In any compound expression, there must only be one context involved. - Temporary objects are initialised to the maximum precision of any subexpression. In most use cases, all objects in a compound expression have the same precision, and so temporary expressions are evaluated to this precision. If you need temporary subexpressions to be evaluated to higher precision, the ``toN`` method can be used on immediates to increase their effective precision, thus (potentially) increasing the precision of intermediates. Context ------------------------------------------------------------------------------- .. cpp:function:: padicxx_ctx::padicxx_ctx(Fmpz_src p, slong min, slong max, padic_print_mode mode) Initialize a padic context. See ``padic_ctx_init``. .. cpp:function:: padic_ctx_t& padicxx_ctx::_ctx() const Obtain a reference to the underlying C data structure. Note that this reference is mutable even if the instance of ``padicxx_ctx`` it is obtained from is not. This is because the context contains data which is not user-visible, and the.. cpp:functions change them. If this is called on a constant instance of ``padicxx_ctx``, you must ensure that no user-visible state is changed. .. cpp:function:: padic_print_mode& padicxx_ctx::mode() .. cpp:function:: padic_print_mode padicxx_ctx::mode() const C++ particulars ------------------------------------------------------------------------------- .. cpp:function:: padicxx_ctx_srcref Padic_src::get_ctx() const .. cpp:function:: padic_ctx_t& Padic_src::_ctx() const Obtain a reference to the context of this instance. .. cpp:function:: padicxx_ctx_srcref Padic_expr::estimate_ctx() const Obtain a reference to a context occurring in a subexpression. As per the first rule in the introduction to this section, all such contexts are the same by definition. .. cpp:function:: Padic_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``exp``, ``exp_balanced``, ``exp_rectangular``, ``inv``, ``log``, ``log_balanced``, ``log_satoh``, ``sqrt``, ``teichmuller``. .. cpp:function:: Padic_expr Padic_expr::pow(T:fits_into_slong) const .. cpp:function:: padicxx_srcref Padic_src::toN(sslong N) const Obtain a new version of the operand, with changed effective precision. Input and output ------------------------------------------------------------------------------- .. cpp:function:: int print(Padic_expr) .. cpp:function:: int print(FILE*, Padic_expr) Data structures ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr Padic_expr::unit() const See ``padic_unit``. .. cpp:function:: slong Padic_expr::val() const .. cpp:function:: slong& Padic_target::val() .. cpp:function:: slong Padic_expr::prec() const .. cpp:function:: slong& Padic_target::prec() Obtain the precision of this instance. See ``padic_prec``. Note that this never requires evaluation. Memory management ------------------------------------------------------------------------------- .. cpp:function:: padicxx::padicxx(padicxx_ctx_srcref) Initialize padic number to default precision. See ``padic_init``. .. cpp:function:: padicxx::padicxx(padicxx_ctx_srcref c, slong N) Initialize padic number to precision $N$. See ``padic_init2``. .. cpp:function:: void Padic_target::reduce() See ``padic_reduce``. Randomisation ------------------------------------------------------------------------------- .. cpp:function:: static padicxx padicxx::randtest(frandxx& state, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) .. cpp:function:: static padicxx padicxx::randtest_int(frandxx& state, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) .. cpp:function:: static padicxx padicxx::randtest_not_zero(frandxx& state, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) Obtain a random padic number of precision ``prec``. See ``padic_randtest``, ``padic_randtest_int`` and ``padic_randtest_not_zero``. Conversion ------------------------------------------------------------------------------- .. cpp:function:: Padic_target Padic_target::operator=(T:is_integer) .. cpp:function:: Padic_target Padic_target::operator=(Fmpz_expr) .. cpp:function:: Padic_target Padic_target::operator=(Fmpq_expr) .. cpp:function:: padicxx padicxx::from_QQ(Fmpq_expr, padicxx_ctx_srcref) .. cpp:function:: padicxx padicxx::from_QQ(Fmpz_expr, padicxx_ctx_srcref) .. cpp:function:: padicxx padicxx::from_QQ(T:is_integer, padicxx_ctx_srcref) .. cpp:function:: padicxx padicxx::from_QQ(Fmpq_expr, padicxx_ctx_srcref, sslong N) .. cpp:function:: padicxx padicxx::from_QQ(Fmpz_expr, padicxx_ctx_srcref, sslong N) .. cpp:function:: padicxx padicxx::from_QQ(T:is_integer, padicxx_ctx_srcref, sslong N) .. cpp:function:: void Padic_target::set_zero() .. cpp:function:: void Padic_target::set_one() .. cpp:function:: padicxx padicxx::zero(padicxx_ctx_srcref) .. cpp:function:: padicxx padicxx::zero(padicxx_ctx_srcref, sslong N) .. cpp:function:: padicxx padicxx::one(padicxx_ctx_srcref) .. cpp:function:: padicxx padicxx::one(padicxx_ctx_srcref, sslong N) .. cpp:function:: bool Padic_expr::is_zero() const .. cpp:function:: bool Padic_expr::is_one() const .. cpp:function:: fmpzxx Padic_expr::to() const Convert self to ``fmpzxx``, if possible. See ``padic_get_fmpz``. .. cpp:function:: fmpqxx Padic_expr::to() const Convert self to ``fmpqxx``. See ``padic_get_fmpz``. .. cpp:function:: std::string Fmpz_expr::to_string() const Arithmetic operations ------------------------------------------------------------------------------- The overloaded operators ``+ - * / << >>`` can be used for arithmetic operations, provided these are implemented for ``padic_t``. .. cpp:function:: Padic_expr inv(Padic_expr) .. cpp:function:: Padic_expr sqrt(Padic_expr) Compute square root. May raise ``flint_exception`` if no square root exists. See ``padic_sqrt``. .. cpp:function:: Padic_expr pow(Padic_expr, T:fits_into_slong) Exponential ------------------------------------------------------------------------------- .. cpp:function:: Padic_expr exp(Padic_expr) .. cpp:function:: Padic_expr exp_rectangular(Padic_expr) .. cpp:function:: Padic_expr exp_balanced(Padic_expr) Compute the exponenti.. cpp:function. These may raise ``flint_exception`` if the series do not converge. Logarithm ------------------------------------------------------------------------------- .. cpp:function:: Padic_expr log(Padic_expr) .. cpp:function:: Padic_expr log_rectangular(Padic_expr) .. cpp:function:: Padic_expr log_balanced(Padic_expr) .. cpp:function:: Padic_expr log_satoh(Padic_expr) Compute the logarit.. cpp:function. These may raise ``flint_exception`` if the series do not converge. Polynomials over the `p`-adics (``padic_poly``) =============================================================================== The type ``padic_polyxx`` wraps ``padic_poly``. Like ``padicxx``, every instance of ``padic_polyxx`` contains a reference to a context ``padicxx_ctx``, and stores its own precision. The same rules regarding temporary expressions apply to ``padic_polyxx`` as to ``padicxx``. C++ particulars ------------------------------------------------------------------------------- .. cpp:function:: padicxx_ctx_srcref Padic_poly_src::get_ctx() const .. cpp:function:: padic_ctx_t& Padic_poly_src::_ctx() const Obtain a reference to the context of this instance. .. cpp:function:: padicxx_ctx_srcref Padic_poly_expr::estimate_ctx() const Obtain a reference to a context occurring in a subexpression. .. cpp:function:: Padic_poly_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``derivative``. .. cpp:function:: Padic_poly_expr::binary operation() const The following bina.. cpp:functions are made available as member functions: ``pow``, ``compose_pow``, ``inv_series``, ``shift_left``, ``shift_right``. .. cpp:function:: padic_polyxx_srcref Padic_poly_src::toN(sslong N) const Obtain a new version of the operand, with changed effective precision. Input and output ------------------------------------------------------------------------------- .. cpp:function:: int print(Padic_expr) .. cpp:function:: int print(FILE*, Padic_expr) .. cpp:function:: int print_pretty(Padic_expr, const char*) .. cpp:function:: int print_pretty(FILE*, Padic_expr, const char*) Memory management ------------------------------------------------------------------------------- .. cpp:function:: padic_polyxx::padic_polyxx(padicxx_ctx_srcref) Initialise to zero. See ``padic_poly_init``. .. cpp:function:: padic_polyxx::padic_polyxx(padicxx_ctx_srcref, slong prec, slong alloc = 0) See ``padic_poly_init2``. .. cpp:function:: void Padic_poly_target realloc(slong alloc) .. cpp:function:: void Padic_poly_target::fit_length(slong len) .. cpp:function:: void Padic_poly_target::canonicalise() .. cpp:function:: void Padic_poly_target::reduce() .. cpp:function:: void Padic_poly_target::truncate(slong) Polynomial parameters ------------------------------------------------------------------------------- .. cpp:function:: slong Padic_poly_expr::length() const .. cpp:function:: slong Padic_poly_expr::degree() const .. cpp:function:: slong Padic_expr::val() const .. cpp:function:: slong& Padic_target::val() .. cpp:function:: slong Padic_expr::prec() const .. cpp:function:: slong& Padic_target::prec() Randomisation ------------------------------------------------------------------------------- .. cpp:function:: static padic_polyxx padic_polyxx::randtest(frandxx& state, padicxx_ctx_srcref ctx, slong len, slong prec = PADIC_DEFAULT_PREC) .. cpp:function:: static padic_polyxx padic_polyxx::randtest_val(frandxx& state, padicxx_ctx_srcref ctx, slong len, slong val, slong prec = PADIC_DEFAULT_PREC) .. cpp:function:: static padic_polyxx padic_polyxx::randtest_not_zero(frandxx& state, slong len, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) Assignment and basic manipulation ------------------------------------------------------------------------------- The overloaded ``operator=`` can be used for assignments. Additionally, we provide the followi.. cpp:functions. .. cpp:function:: padic_polyxx padic_polyxx::from_QQ(T:is_integer, padicxx_ctx_srcref, sslong N) .. cpp:function:: padic_polyxx padic_polyxx::from_QQ(Fmpz_expr, padicxx_ctx_srcref, sslong N) .. cpp:function:: padic_polyxx padic_polyxx::from_QQ(Fmpq_expr, padicxx_ctx_srcref, sslong N) .. cpp:function:: padic_polyxx padic_polyxx::from_QQ(T:is_integer, padicxx_ctx_srcref) .. cpp:function:: padic_polyxx padic_polyxx::from_QQ(Fmpz_expr, padicxx_ctx_srcref) .. cpp:function:: padic_polyxx padic_polyxx::from_QQ(Fmpq_expr, padicxx_ctx_srcref) .. cpp:function:: padic_polyxx padic_polyxx::from_QQX(Fmpz_poly_expr, padicxx_ctx_srcref, sslong N) .. cpp:function:: padic_polyxx padic_polyxx::from_QQX(Fmpq_poly_expr, padicxx_ctx_srcref, sslong N) .. cpp:function:: padic_polyxx padic_polyxx::from_QQX(Fmpz_poly_expr, padicxx_ctx_srcref) .. cpp:function:: padic_polyxx padic_polyxx::from_QQX(Fmpz_poly_expr, padicxx_ctx_srcref) .. cpp:function:: padic_polyxx padic_polyxx::from_ground(Padic_expr) .. cpp:function:: fmpz_polyxx Padic_poly_expr::to() const Convert to an integer polynomial. Raises ``flint_exception`` if the polynomial is not p-adically integral. See ``padic_poly_get_fmpz_poly``. .. cpp:function:: fmpq_polyxx Padic_poly_expr::to() const See ``padic_poly_get_fmpq_poly``. .. cpp:function:: padic_polyxx padic_polyxx::zero(const padic_polyxx_ctx&) .. cpp:function:: padic_polyxx padic_polyxx::zero(const padic_polyxx_ctx&, sslong N) .. cpp:function:: padic_polyxx padic_polyxx::one(const padic_polyxx_ctx&) .. cpp:function:: padic_polyxx padic_polyxx::one(const padic_polyxx_ctx&, sslong N) Getting and setting coefficients ------------------------------------------------------------------------------- .. cpp:function:: Padic_expr Padic_poly_expr::get_coeff(slong n) const .. cpp:function:: void Padic_poly_target::set_coeff(slong i, Padic_expr) Comparison ------------------------------------------------------------------------------- The overloaded ``operator==`` can be used for comparison. .. cpp:function:: bool Padic_poly_expr::is_zero() const .. cpp:function:: bool Padic_poly_expr::is_one() const Arithmetic ------------------------------------------------------------------------------- The overloaded operators ``+ - *`` can be used for arithmetic. Powering ------------------------------------------------------------------------------- .. cpp:function:: Padic_poly_expr pow(Padic_poly_expr, T:fits_into_slong) Series inversion ------------------------------------------------------------------------------- .. cpp:function:: Padic_poly_expr inv_series_newton(Padic_poly_expr, T:fits_into_slong) Derivative ------------------------------------------------------------------------------- .. cpp:function:: Padic_poly_expr derivative(Padic_poly_expr) Shifting ------------------------------------------------------------------------------- .. cpp:function:: Padic_poly_expr shift_left(Padic_poly_expr, T:fits_into_slong) .. cpp:function:: Padic_poly_expr shift_right(Padic_poly_expr, T:fits_into_slong) Evaluation and composition ------------------------------------------------------------------------------- The overloaded ``operator()`` can be used for both evaluation and composition. .. cpp:function:: Padic_expr evaluate(Padic_poly_expr, Padic_expr) .. cpp:function:: Padic_poly_expr compose(Padic_poly_expr, Padic_poly_expr) .. cpp:function:: Padic_poly_expr compose_pow(Padic_poly_expr, T:fits_into_slong) Testing ------------------------------------------------------------------------------- .. cpp:function:: bool Padic_poly_src::is_canonical() const .. cpp:function:: bool Padic_poly_src::is_reduced() const Matrices of $p$-adics (``padic_mat``) =============================================================================== The type ``padic_matxx`` wraps ``padic_mat``. Like ``padicxx``, every instance of ``padic_matxx`` contains a reference to a context ``padicxx_ctx``, and stores its own precision. The same rules regarding temporary expressions apply to ``padic_matxx`` as to ``padicxx``. C++ particulars ------------------------------------------------------------------------------- .. cpp:function:: padicxx_ctx_srcref Padic_mat_src::get_ctx() const .. cpp:function:: padic_ctx_t& Padic_mat_src::_ctx() const Obtain a reference to the context of this instance. .. cpp:function:: padicxx_ctx_srcref Padic_mat_expr::estimate_ctx() const Obtain a reference to a context occurring in a subexpression. .. cpp:function:: padic_matxx_srcref Padic_mat_src::toN(sslong N) const Obtain a new version of the operand, with changed effective precision. .. cpp:function:: slong Padic_mat_expr::rows() const .. cpp:function:: slong Padic_mat_expr::cols() const Obtain the number of rows/columns of this matrix. This never evaluates. .. cpp:function:: slong Padic_mat_expr::val() const .. cpp:function:: slong& Padic_mat_target::val() .. cpp:function:: Padic_mat_expr Padic_mat_expr::transpose() const Input and output ------------------------------------------------------------------------------- .. cpp:function:: int print(Padic_mat_expr) .. cpp:function:: int print(FILE*, Padic_mat_expr) .. cpp:function:: int print_pretty(Padic_mat_expr) .. cpp:function:: int print_pretty(FILE*, Padic_mat_expr) Memory management ------------------------------------------------------------------------------- .. cpp:function:: padic_matxx::padic_matxx(padicxx_ctx_srcref, slong rows, slong cols) See ``padic_mat_init``. .. cpp:function:: padic_matxx::padic_matxx(padicxx_ctx_srcref, slong rows, slong cols, slong prec) See ``padic_mat_init2``. .. cpp:function:: void Padic_mat_target::canonicalise() .. cpp:function:: void Padic_mat_target::reduce() .. cpp:function:: bool Padic_mat_src::is_canonical() const .. cpp:function:: bool Padic_mat_src::is_reduced() const .. cpp:function:: bool Padic_mat_src::is_square() const .. cpp:function:: bool Padic_mat_src::is_empty() const Basic assignment ------------------------------------------------------------------------------- Overloaded ``operator=`` can be used for assignment. .. cpp:function:: void Padic_mat_target::set_zero() .. cpp:function:: void Padic_mat_target::set_one() .. cpp:function:: padic_matxx padic_matxx::zero(padicxx_ctx_srcref) .. cpp:function:: padic_matxx padic_matxx::zero(padicxx_ctx_srcref, sslong N) .. cpp:function:: padic_matxx padic_matxx::one(padicxx_ctx_srcref) .. cpp:function:: padic_matxx padic_matxx::one(padicxx_ctx_srcref, sslong N) Conversion ------------------------------------------------------------------------------- Converting from a ``fmpq_matxx`` can be done using ``operator=``, or the followi.. cpp:functions. .. cpp:function:: padic_matxx padic_matxx::from_QQ(Fmpq_mat_expr, padicxx_ctx_srcref) .. cpp:function:: fmpq_matxx Padic_mat_expr::to() const Entries ------------------------------------------------------------------------------- .. cpp:function:: ?? Padic_mat_expr::at(slong i, slong j) Unified coefficient access to the underlying integer matrix. See ``padic_mat_entry``. .. cpp:function:: Fmpz_expr Padic_mat_expr::get_entry(slong i, slong j) .. cpp:function:: void Padic_mat_target::set_entry(slong i, slong j, Padic_expr) Comparison ------------------------------------------------------------------------------- Overloaded ``operator==`` can be used for comparison. .. cpp:function:: bool Padic_mat_expr::is_zero() const Random matrix generation ------------------------------------------------------------------------------- .. cpp:function:: static padic_polyxx padic_polyxx::randtest(slong rows, slong cols, frandxx& state, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) Transpose ------------------------------------------------------------------------------- .. cpp:function:: Padic_mat_expr transpose(Padic_mat_expr) Arithmetic ------------------------------------------------------------------------------- Overloaded operators ``+ - * /`` can be used for arithmetic. Q-adics (``qadic``) =============================================================================== The type ``qadicxx`` wraps the C interface ``qadic_t``, and the type ``qadicxx_ctx`` wraps ``qadic_ctx_t``. Evaluating composite expressions requires temporary objects, which must be initialised to a certain precision and with a certain context. The same rules apply as for ``padicxx``. Context ------------------------------------------------------------------------------- .. cpp:function:: qadicxx_ctx::qadicxx_ctx(Fmpz_src p, sslong min, slong max, padic_print_mode mode, const char* var = "x") Initialize a qadic context. See ``qadic_ctx_init_conway``. .. cpp:function:: qadic_ctx_t& qadicxx_ctx::_ctx() const Obtain a reference to the underlying C data structure. Note that this reference is mutable even if the instance of ``qadicxx_ctx`` it is obtained from is not. This is because the context contains data which is not user-visible, and the.. cpp:functions change them. If this is called on a constant instance of ``qadicxx_ctx``, you must ensure that no user-visible state is changed. .. cpp:function:: padicxx_ctx_srcref qadicxx_ctx::pctx() const Obtain a reference to the underlying padic context. C++ particulars ------------------------------------------------------------------------------- .. cpp:function:: padicxx_ctx_srcref Qadic_src::get_ctx() const .. cpp:function:: const qadicxx_ctx& Qadic_src::get_qctx() const .. cpp:function:: qadic_ctx_t& Qadic_src::_ctx() const Obtain a reference to the context of this instance. .. cpp:function:: const qadicxx_ctx& Qadic_expr::estimate_ctx() const Obtain a reference to a context occurring in a subexpression. As per the first rule in the introduction to this section, all such contexts are the same by definition. .. cpp:function:: Qadic_expr::unary operation() const The following una.. cpp:functions are made available as member functions: ``exp``, ``exp_balanced``, ``exp_rectangular``, ``inv``, ``log``, ``log_balanced``, ``teichmuller``, ``trace``, ``norm``, ``norm_analytic``, ``norm_resultant``. .. cpp:function:: Qadic_expr Qadic_expr::pow(Fmpz_expr) const .. cpp:function:: Qadic_expr Qadic_expr::frobenius(T:fits_into_slong) const .. cpp:function:: qadicxx_srcref Qadic_src::toN(sslong N) const Obtain a new version of the operand, with changed effective precision. Data structures ------------------------------------------------------------------------------- .. cpp:function:: int print_pretty(Qadic_expr) .. cpp:function:: int print_pretty(FILE*, Qadic_expr) Data structures ------------------------------------------------------------------------------- .. cpp:function:: slong Qadic_expr::val() const .. cpp:function:: slong Qadic_expr::prec() const Obtain the precision of this instance. See ``qadic_prec``. Note that this never requires evaluation. Memory management ------------------------------------------------------------------------------- .. cpp:function:: qadicxx::qadicxx(const qadicxx_ctx&) Initialize qadic number to default precision. See ``qadic_init``. .. cpp:function:: qadicxx::qadicxx(const qadicxx_ctx& c, slong N) Initialize qadic number to precision $N$. See ``qadic_init2``. .. cpp:function:: void Qadic_target::reduce() See ``qadic_reduce``. Randomisation ------------------------------------------------------------------------------- .. cpp:function:: static qadicxx qadicxx::randtest(frandxx& state, const qadicxx_ctx& ctx, slong prec = PADIC_DEFAULT_PREC) .. cpp:function:: static qadicxx qadicxx::randtest_int(frandxx& state, slong val, const qadicxx_ctx& ctx, slong prec = PADIC_DEFAULT_PREC) .. cpp:function:: static qadicxx qadicxx::randtest_val(frandxx& state, const qadicxx_ctx& ctx, slong prec = PADIC_DEFAULT_PREC) .. cpp:function:: static qadicxx qadicxx::randtest_not_zero(frandxx& state, const qadicxx_ctx& ctx, slong prec = PADIC_DEFAULT_PREC) Obtain a random qadic number of precision ``prec``. See ``qadic_randtest``, ``qadic_randtest_int`` and ``qadic_randtest_not_zero``. Conversion ------------------------------------------------------------------------------- .. cpp:function:: Qadic_target Qadic_target::operator=(T:is_unsigned_integer) .. cpp:function:: Qadic_target Qadic_target::operator=(Padic_expr) .. cpp:function:: qadicxx qadicxx::from_ground(Padic_expr, const qadicxx_ctx&) .. cpp:function:: void Qadic_target::set_zero() .. cpp:function:: void Qadic_target::set_one() .. cpp:function:: void Qadic_target::set_gen(const qadicxx_ctx&) .. cpp:function:: qadicxx qadicxx::zero(const qadicxx_ctx&) .. cpp:function:: qadicxx qadicxx::zero(const qadicxx_ctx&, sslong N) .. cpp:function:: qadicxx qadicxx::one(const qadicxx_ctx&) .. cpp:function:: qadicxx qadicxx::one(const qadicxx_ctx&, sslong N) .. cpp:function:: qadicxx qadicxx::gen(const qadicxx_ctx&) .. cpp:function:: qadicxx qadicxx::gen(const qadicxx_ctx&, sslong N) .. cpp:function:: bool Qadic_expr::is_zero() const .. cpp:function:: bool Qadic_expr::is_one() const .. cpp:function:: padicxx Qadic_expr::to() const Convert self to ``padicxx``, if possible. See ``qadic_get_padic``. Arithmetic operations ------------------------------------------------------------------------------- The overloaded operators ``+ - * / << >>`` can be used for arithmetic operations, provided these are implemented for ``qadic_t``. .. cpp:function:: Qadic_expr inv(Qadic_expr) .. cpp:function:: Qadic_expr pow(Qadic_expr, Fmpz_expr) Exponential ------------------------------------------------------------------------------- .. cpp:function:: Qadic_expr exp(Qadic_expr) .. cpp:function:: Qadic_expr exp_rectangular(Qadic_expr) .. cpp:function:: Qadic_expr exp_balanced(Qadic_expr) Compute the exponenti.. cpp:function. These may raise ``flint_exception`` if the series do not converge. Logarithm ------------------------------------------------------------------------------- .. cpp:function:: Qadic_expr log(Qadic_expr) .. cpp:function:: Qadic_expr log_balanced(Qadic_expr) Compute the logarit.. cpp:function. These may raise ``flint_exception`` if the series do not converge. Speci.. cpp:functions ------------------------------------------------------------------------------- .. cpp:function:: Qadic_expr teichmuller(Qadic_expr) .. cpp:function:: Padic_expr trace(Qadic_expr) .. cpp:function:: Padic_expr norm(Qadic_expr) .. cpp:function:: Padic_expr norm_analytic(Qadic_expr) .. cpp:function:: Padic_expr norm_resultant(Qadic_expr) Arithmet.. cpp:functions (``arith``) =============================================================================== The ``arithxx`` module wraps the ``arith`` module, i.e. provides functions for computing number theoret.. cpp:functions. Primorials ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr primorial(T:fits_into_slong) Harmonic numbers ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_expr harmonic_number(T:fits_into_slong) Stirling numbers ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr stirling_number_1u(T:fits_into_slong, T:fits_into_slong) .. cpp:function:: Fmpz_expr stirling_number_1(T:fits_into_slong, T:fits_into_slong) .. cpp:function:: Fmpz_expr stirling_number_2(T:fits_into_slong, T:fits_into_slong) .. cpp:function:: Fmpz_vec_expr stirling_number_1u_vec(T:fits_into_slong, T:fits_into_slong) .. cpp:function:: Fmpz_vec_expr stirling_number_1_vec(T:fits_into_slong, T:fits_into_slong) .. cpp:function:: Fmpz_vec_expr stirling_number_2_vec(T:fits_into_slong, T:fits_into_slong) .. cpp:function:: Fmpz_vec_expr stirling_number_1u_vec_next(Fmpz_vec_expr v, T:fits_into_slong n) .. cpp:function:: Fmpz_vec_expr stirling_number_1_vec_next(Fmpz_vec_expr v, T:fits_into_slong n) .. cpp:function:: Fmpz_vec_expr stirling_number_2_vec_next(Fmpz_vec_expr v, T:fits_into_slong n) Given the vector $v$ of length $k$, compute the next vector of Stirling numbers. The size of the new vector is $k + 1$ if $k = n$, and else $k$. See ``arith_stirling_number_1u_vec_next`` etc. .. cpp:function:: Fmpz_mat_expr stirling_matrix_1u(T:fits_into_slong m, T:fits_into_slong) .. cpp:function:: Fmpz_mat_expr stirling_matrix_1(T:fits_into_slong m, T:fits_into_slong) .. cpp:function:: Fmpz_mat_expr stirling_matrix_2(T:fits_into_slong m, T:fits_into_slong) Compute an $m \times n$ Stirling matrix. See ``arith_stirling_matrix_1u`` etc. Bell numbers ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr bell_number(T:is_unsigned_integer) .. cpp:function:: Fmpz_expr bell_number_bsplit(T:is_unsigned_integer) .. cpp:function:: Fmpz_expr bell_number_multi_mod(T:is_unsigned_integer) .. cpp:function:: Fmpz_vec_expr bell_number_vec(T:is_unsigned_integer) .. cpp:function:: Fmpz_vec_expr bell_number_vec_recursive(T:is_unsigned_integer) .. cpp:function:: Fmpz_vec_expr bell_number_vec_multi_mod(T:is_unsigned_integer) .. cpp:function:: Nmod_expr bell_number_nmod(T:is_unsigned_integer, Nmodxx_ctx_src) .. cpp:function:: Nmod_vec_expr bell_number_nmod_vec(T:is_unsigned_integer, Nmodxx_ctx_src) .. cpp:function:: Nmod_vec_expr bell_number_nmod_vec_recursive(T:is_unsigned_integer, Nmodxx_ctx_src) .. cpp:function:: Nmod_vec_expr bell_number_nmod_vec_series(T:is_unsigned_integer, Nmodxx_ctx_src) .. cpp:function:: double bell_number_size(ulong n) Bernoulli numbers and polynomials ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_expr bernoulli_number(T:is_unsigned_integer) .. cpp:function:: Fmpq_vec_expr bernoulli_number_vec(T:fits_into_slong) .. cpp:function:: Fmpz_expr bernoulli_number_denom(T:is_unsigned_integer) .. cpp:function:: double bernoulli_number_size(ulong) .. cpp:function:: Fmpq_poly_expr bernoulli_polynomial(T:is_unsigned_integer) Euler numbers and polynomials ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_expr euler_number(T:is_unsigned_integer) .. cpp:function:: Fmpq_vec_expr euler_number_vec(T:fits_into_slong) .. cpp:function:: double euler_number_size(ulong) .. cpp:function:: Fmpq_poly_expr euler_polynomial(T:is_unsigned_integer) Legendre polynomials ------------------------------------------------------------------------------- .. cpp:function:: Fmpq_poly_expr legendre_polynomial(T:is_unsigned_integer) .. cpp:function:: Fmpz_poly_expr chebyshev_t_polynomial(T:is_unsigned_integer) .. cpp:function:: Fmpz_poly_expr chebyshev_u_polynomial(T:is_unsigned_integer) Multiplicati.. cpp:functions ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr euler_phi(Fmpz_expr) .. cpp:function:: int moebius_mu(Fmpz_expr) .. cpp:function:: Fmpz_expr divisor_sigma(Fmpz_expr, ulong) .. cpp:function:: Fmpz_poly_expr divisors(Fmpz_expr) .. cpp:function:: Fmpz_expr ramanujan_tau(Fmpz_expr) .. cpp:function:: Fmpz_poly_expr ramanujan_tau_series(T:fits_into_slong) Cyclotomic polynomials ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr cyclotomic_polynomial(T:is_unsigned_integer) .. cpp:function:: Fmpz_poly_expr cos_minpoly(T:is_unsigned_integer) Swinnerton-Dyer polynomials ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_poly_expr swinnerton_dyer_polynomial(T:is_unsigned_integer) Landau.. cpp:function ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_vec_expr landau_function_vec(T:is_unsigned_integer) Dedekind sums ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr dedekind_sum_naive(Fmpz_expr, Fmpz_expr) .. cpp:function:: Fmpz_expr dedekind_sum(Fmpz_expr, Fmpz_expr) Number of partitions ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_vec_expr number_of_partitions_vec(T:fits_into_slong) .. cpp:function:: Nmod_vec_expr number_of_partitions_nmod_vec(T:fits_into_slong) .. cpp:function:: Fmpz_expr number_of_partitions(T:is_unsigned_integer) Sums of squares ------------------------------------------------------------------------------- .. cpp:function:: Fmpz_expr sum_of_squares(T:is_unsigned_integer, Fmpz_expr) .. cpp:function:: Fmpz_vec_expr sum_of_squares(T:is_unsigned_integer, T:fits_into_slong) flint2-2.8.4/doc/source/fmpq.rst000066400000000000000000000727351414523752600165140ustar00rootroot00000000000000.. _fmpq: **fmpq.h** -- rational numbers =============================================================================== Description. 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. 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) Returns nonzero if ``x`` and ``y`` are equal, and zero otherwise. Assumes that ``x`` and ``y`` are both in canonical form. .. function:: int fmpq_sgn(const fmpq_t x) Returns the sign of the rational number `x`. .. 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_ui(const fmpq_t x, ulong y) Returns negative if `x < y`, zero if `x = y`, and positive if `x > y`. .. function:: int fmpq_cmp_si(const fmpq_t x, slong y) Returns negative if `x < y`, zero if `x = y`, and positive if `x > y`. .. function:: int fmpq_equal_ui(const fmpq_t x, ulong y) Returns `1` if `x = y`, otherwise returns `0`. .. function:: int fmpq_equal_si(const fmpq_t x, slong y) Returns `1` if `x = y`, otherwise returns `0`. .. 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:: void 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:: void fmpq_init_set_mpz_frac_readonly(fmpq_t z, const mpz_t p, const mpz_t q) Assuming ``z`` is an ``fmpz_t`` which will not be cleaned up, this temporarily copies ``p`` and ``q`` into the numerator and denominator of ``z`` for read only operations only. The user must not run ``fmpq_clear`` on ``z``. .. 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. .. 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 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``. Assumes that the inputs are in canonical form, and produces output in canonical form. 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, placing the result in canonical form. 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``. The result is placed in canonical form, assuming that ``src`` is already in canonical form. .. 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 gcd`(ps, qr)/(qs)`. (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} = a/b`. Unlike :func:`fmpq_gcd`, this function 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` which is 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` 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` 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` 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 `x` is not canonical or `Q` is less than the denominator of `x`. .. function:: void fmpq_simplest_between(fmpq_t x, const fmpq_t l, const fmpq_t r) 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) 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 reduced, but their denominators do need to be positive. `x` will be 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 <= 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 | 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`. flint2-2.8.4/doc/source/fmpq_mat.rst000066400000000000000000000515451414523752600173510ustar00rootroot00000000000000.. _fmpq-mat: **fmpq_mat.h** -- matrices over the rational numbers =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpq_mat_struct .. type:: fmpq_mat_t Description. 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) Set ``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``. 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. 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. flint2-2.8.4/doc/source/fmpq_mpoly.rst000066400000000000000000001010651414523752600177210ustar00rootroot00000000000000.. _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 an 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 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 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 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 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``, ect. .. 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(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, fmpq_t c, const fmpq_mpoly_ctx_t ctx) int fmpq_mpoly_equal_fmpz(const fmpq_mpoly_t A, 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 thows 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 thows 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, ulong const * 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, fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_set_coeff_fmpq_ui(fmpq_mpoly_t A, const fmpq_t c, ulong const * exp, 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 function 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_fmpz_fmpz(fmpq_mpoly_t A, const fmpz_t c, fmpz * const * 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_si_fmpz(fmpq_mpoly_t A, slong c, fmpz * const * 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, 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`` 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 cofficients of *A* when viewed as a polynomial in the variables *vars*. Return `1` for success and `0` for failure. Upon succcess, *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 vise 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*. flint2-2.8.4/doc/source/fmpq_mpoly_factor.rst000066400000000000000000000071641414523752600212640ustar00rootroot00000000000000.. _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:: void fmpq_mpoly_factor_swap(fmpq_mpoly_factor_t f, fmpq_mpoly_factor_t g, const fmpq_mpoly_ctx_t ctx) Efficiently swap *f* and *g*. .. 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 recommend 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. flint2-2.8.4/doc/source/fmpq_poly.rst000066400000000000000000002245311414523752600175500ustar00rootroot00000000000000.. _fmpq-poly: **fmpq_poly.h** -- univariate polynomials over the rational numbers =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpq_poly_struct .. type:: fmpq_poly_t Description. 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 set 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_mpz(fmpq_poly_t poly, const mpz_t x) Sets ``poly`` to the integer `x`. .. function:: void fmpq_poly_set_mpq(fmpq_poly_t poly, const mpq_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:: void _fmpq_poly_set_array_mpq(fmpz * poly, fmpz_t den, const mpq_t * a, slong n) Sets ``(poly, den)`` to the polynomial given by the first `n \geq 1` coefficients in the array `a`, from lowest degree to highest degree. The result is only guaranteed to be in lowest terms if all input coefficients are given in lowest terms. .. function:: void fmpq_poly_set_array_mpq(fmpq_poly_t poly, const mpq_t * a, slong n) Sets ``poly`` to the polynomial with coefficients as given in the array `a` of length `n \geq 0`, from lowest degree to highest degree. The result is only guaranteed to be in canonical form if all input coefficients are given in lowest terms. .. 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_get_coeff_mpq(mpq_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`. .. function:: void fmpq_poly_set_coeff_mpz(fmpq_poly_t rop, slong n, const mpz_t x) Sets the `n`th coefficient in ``poly`` to the integer `x`. .. function:: void fmpq_poly_set_coeff_mpq(fmpq_poly_t rop, slong n, const mpq_t x) Sets the `n`th coefficient in ``poly`` to the rational~`x`, which is expected to be provided in lowest terms. 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) Return `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) Return `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, fmpq_poly poly1, fmpq_poly poly2) Sets ``res`` to the sum of ``poly1`` and ``poly2``, using Henrici's algorithm. .. function:: void fmpq_poly_add_can(fmpq_poly_t res, fmpq_poly poly1, fmpq_poly poly2, 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_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, fmpq_poly poly1, fmpq_poly 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, fmpq_poly poly1, fmpq_poly 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, fmpq_poly poly1, fmpq_poly poly2) Sets ``res`` to the difference of ``poly1`` and ``poly2``, using Henrici's algorithm. .. function:: void fmpq_poly_sub_can(fmpq_poly_t res, fmpq_poly poly1, fmpq_poly 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, fmpq_poly poly1, fmpq_poly 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, fmpq_poly poly1, fmpq_poly 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_si(fmpq_poly_t rop, const fmpq_poly_t op, slong c) Sets ``rop`` to `c` times ``op``. .. function:: 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_mul_fmpq(fmpq_poly_t rop, const fmpq_poly_t op, const mpq_t c) Sets ``rop`` to `c` times ``op``. .. function:: void fmpq_poly_scalar_mul_mpz(fmpq_poly_t rop, const fmpq_poly_t op, const mpz_t c) Sets ``rop`` to `c` times ``op``. .. function:: void fmpq_poly_scalar_mul_mpq(fmpq_poly_t rop, const fmpq_poly_t op, const fmpq_t c) Sets ``rop`` to `c` times ``op``. .. 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) void fmpq_poly_scalar_div_mpz(fmpq_poly_t rop, const fmpq_poly_t op, const mpz_t c) void fmpq_poly_scalar_div_mpq(fmpq_poly_t rop, const fmpq_poly_t op, const mpq_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``. .. 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``. .. 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``. .. 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, const 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*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 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 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, fmpz_poly_t S, fmpz_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, 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_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(fmpq * 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(fmpq * 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(fmpq * 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. .. function:: void fmpq_poly_evaluate_mpz(mpq_t res, const fmpq_poly_t poly, const mpz_t a) Evaluates the polynomial ``poly`` at the integer `a` of type ``mpz`` and sets ``res`` to the result. .. function:: void fmpq_poly_evaluate_mpq(mpq_t res, const fmpq_poly_t poly, const mpq_t a) Evaluates the polynomial ``poly`` at the rational `a` of type ``mpq`` 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(FILT * 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. flint2-2.8.4/doc/source/fmpq_vec.rst000066400000000000000000000051551414523752600173410ustar00rootroot00000000000000.. _fmpq-vec: **fmpq_vec.h** -- vectors over rational numbers =============================================================================== Description. 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)``. 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()`. flint2-2.8.4/doc/source/fmpz.rst000066400000000000000000001747401414523752600165240ustar00rootroot00000000000000.. _fmpz: **fmpz.h** -- integers =============================================================================== Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz 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`` work. .. 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``). .. function:: int COEFF_IS_MPZ(fmpz 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``. 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) Initialises `f` and sets it to the value of `g`. .. function:: void fmpz_init_set_ui(fmpz_t f, ulong g) Initialises `f` and sets it to the value of `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``. .. 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*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 MPIR. .. 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 MPIR. .. 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_print(fmpz_t x) Prints the value `x` to ``stdout``, without a carriage return(CR). 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. 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 ``flint_printf`` from the standard library and ``mpz_out_str`` from MPIR. .. function:: int fmpz_fprint(FILE * file, fmpz_t x) Prints the value `x` to ``file``, without a carriage return(CR). 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. 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 ``flint_printf`` from the standard library and ``mpz_out_str`` from MPIR. .. 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 >= 2, 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) Returns a negative value if `f < g`, positive value if `g < f`, otherwise returns `0`. .. function:: int fmpz_cmp_ui(const fmpz_t f, ulong g) Returns a negative value if `f < g`, positive value if `g < f`, otherwise returns `0`. .. 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) Returns `1` if `f` is equal to `g`, otherwise returns `0`. .. function:: int fmpz_equal_ui(const fmpz_t f, ulong g) Returns `1` if `f` is equal to `g`, otherwise returns `0`. .. 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`. .. 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) Sets `f` to the quotient of `g` by `h`, rounding up towards infinity and `s` to the remainder. If `h` is `0` an exception is raised. .. function:: void fmpz_cdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h) Sets `f` to the quotient of `g` by `h`, rounding up towards infinity. If `h` is `0` an exception is raised. .. function:: void fmpz_cdiv_q_si(fmpz_t f, const fmpz_t g, slong h) Sets `f` to the quotient of `g` by `h`, rounding up towards infinity. If `h` is `0` an exception is raised. .. function:: void fmpz_cdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) Sets `f` to the quotient of `g` by `h`, rounding up towards infinity. If `h` is `0` an exception is raised. .. function:: void fmpz_cdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp) Sets `f` to the quotient of `g` by ``2^exp``, rounding up towards infinity. .. function:: void fmpz_cdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp) Sets `f` to the remainder of `g` upon division by ``2^exp``, where the remainder is non-positive. .. function:: ulong fmpz_cdiv_ui(const fmpz_t g, ulong h) Returns the negative of the remainder from dividing `g` by `h`, rounding towards minus infinity. If `h` is `0` an exception is raised. .. function:: void fmpz_fdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp) Sets `f` to `g` divided by ``2^exp``, rounding down towards minus infinity. .. function:: void fmpz_fdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h) Sets `f` to the quotient of `g` by `h`, rounding down towards minus infinity. If `h` is `0` an exception is raised. .. function:: void fmpz_fdiv_q_si(fmpz_t f, const fmpz_t g, slong h) Set `f` to the quotient of `g` by `h`, rounding down towards minus infinity. If `h` is `0` an exception is raised. .. function:: void fmpz_fdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) Set `f` to the quotient of `g` by `h`, rounding down towards minus infinity. If `h` is `0` an exception is raised. .. function:: void fmpz_fdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) Sets `f` to the quotient of `g` by `h`, rounding down towards minus infinity and `s` to the remainder. If `h` is `0` an exception is raised. .. function:: void fmpz_fdiv_r(fmpz_t f, const fmpz_t g, const fmpz_t h) Sets `f` to the remainder from dividing `g` by `h` and rounding the quotient down towards minus infinity. If `h` is `0` an exception is raised. .. function:: void fmpz_fdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp) Sets `f` to the remainder of `g` upon division by ``2^exp``, where the remainder is non-negative. .. function:: ulong fmpz_fdiv_ui(const fmpz_t g, ulong x) Returns the remainder of `g` modulo `x` where `x` is an ``ulong``, without changing `g`. If `x` is `0` an exception will result. .. function:: void fmpz_tdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h) Sets `f` to the quotient of `g` by `h`, rounding down towards zero. If `h` is `0` an exception is raised. .. function:: void fmpz_tdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) Sets `f` to the quotient of `g` by `h`, rounding down towards zero and `s` to the remainder. If `h` is `0` an exception is raised. .. function:: void fmpz_tdiv_q_si(fmpz_t f, const fmpz_t g, slong h) Set `f` to the quotient of `g` by `h`, rounding down towards zero. If `h` is `0` an exception is raised. .. function:: void fmpz_tdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) Set `f` to the quotient of `g` by `h`, rounding down towards zero. If `h` is `0` an exception is raised. .. function:: void fmpz_tdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp) Sets `f` to the remainder of `g` upon division by ``2^exp``, where the remainder has the same sign as `g`. .. function:: ulong fmpz_tdiv_ui(const fmpz_t g, ulong h) Returns the absolute value of the remainder from dividing `g` by `h`, rounding towards zero. If `h` is `0` an exception is raised. .. function:: void fmpz_tdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp) Sets `f` to `g` divided by ``2^exp``, rounding down towards zero. .. function:: void fmpz_ndiv_qr(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b) Sets `q` to the quotient of `a` by `b`, rounding towards the nearest integer where ties rounds towards zero and sets `r` to the remainder. If `b` is `0` an exception is raised. .. function:: void fmpz_divexact(fmpz_t f, const fmpz_t g, const fmpz_t 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_divexact_si(fmpz_t f, const fmpz_t g, slong 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_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) Returns `1` if there is an integer `q` with `f = q g` and `0` if not. .. 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:: int fmpz_divisible_si(const fmpz_t f, slong g) Returns whether `f` is divisible by `g > 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`. The remainder is always taken to be positive. .. function:: ulong fmpz_mod_ui(fmpz_t f, const fmpz_t g, ulong x) Sets `f` to `g` reduced modulo `x` where `x` is an ``ulong``. If `x` is `0` an exception will result. .. 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) Sets `f` to `g^x` where `x` is an ``ulong``. If `x` is `0` and `g` is `0`, then `f` will be set to `1`. .. function:: int fmpz_pow_fmpz(fmpz_t f, const fmpz_t g, const fmpz_t x) Set `f` to `g^x`. 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) 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:: 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:: void 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. .. 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 `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 `g` and `x` divided by ``2^exp``, rounding down towards zero. Greatest common divisor -------------------------------------------------------------------------------- .. 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. values `a` and `b` such that `af + bg = d`, where `d = \gcd(f, g)`. 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 either one of these cases: .. 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 the cases above, the solution `(d, a, b)` will satisfy .. math :: |a| < \Bigl| \frac{g}{2 d} \Bigr|, \qquad \Bigl| |b| < \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 mod n` is exactly `\{xstart + xstride i | 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, 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:: int 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 small (word-size) 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, fmpz_t r1, 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 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 integers greater than `1` and coprime. 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, fmpz_t r2, 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 where `M = m_1 \times m_2`. It is assumed that `m_1` and `m_2` are positive integers greater than `1` and coprime. 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) int fmpz_multi_crt_precompute_p(fmpz_multi_crt_t CRT, const fmpz * 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:`fmpz_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) void fmpz_multi_crt_precomp_p(fmpz_t output, const fmpz_multi_crt_t P, const fmpz * const * inputs) Set ``output`` to an integer of smallest absolute value that is congruent to ``values + i`` modulo the ``moduli + i`` in :func:`fmpz_crt_precompute`. .. function:: int fmpz_multi_crt(fmpz_t output, const fmpz * moduli, const fmpz * values, slong len) 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``. .. function:: slong _nmod_poly_crt_local_size(const nmod_poly_crt_t CRT) Return the required length of the output for :func:`_nmod_poly_crt_run`. .. function:: void _fmpz_multi_crt_run(fmpz * outputs, const fmpz_multi_crt_t CRT, const fmpz * inputs) void _fmpz_multi_crt_run_p(fmpz * outputs, const fmpz_multi_crt_t CRT, const fmpz * const * inputs) Perform the same operation as fmpz::fmpz_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 ``_fmpz_multi_crt_local_size(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`. N.B: 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`. N.B: 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. Up to an including GMP 6.1.2 this used Miller-Rabin iterations, and thereafter 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, const fmpz_factor_t fac, ulong k) void fmpz_divisor_sigma(fmpz_t res, const fmpz_t n, ulong k) 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`. flint2-2.8.4/doc/source/fmpz_factor.rst000066400000000000000000000320011414523752600200410ustar00rootroot00000000000000.. _fmpz-factor: **fmpz_factor.h** -- integer factorisation =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_factor_struct .. type:: fmpz_factor_t Description. 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 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, 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. flint2-2.8.4/doc/source/fmpz_lll.rst000066400000000000000000000473311414523752600173620ustar00rootroot00000000000000 **fmpz_lll.h** -- LLL reduction ================================================================================================== Description. 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{``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{``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^{-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^{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 upto ``cur_kappa``, \textbf{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]_. .. 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 does 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]_. .. function:: int fmpz_lll_is_reduced_d(const fmpz_mat_t B, const fmpz_lll_t fl) Returns a non-zero value if the matrix ``B`` is LLL-reduced with factor (``fl->delta``, ``fl->eta``), and otherwise returns zero. The function is mainly intended to be used for testing purposes. It will not always work, but if it does the result is guaranteed. Uses the algorithm of Villard (see https://arxiv.org/abs/cs/0701183 ). .. function:: int fmpz_lll_is_reduced_mpfr(const fmpz_mat_t B, const fmpz_lll_t fl, flint_bitcnt_t prec) Returns a non-zero value if the matrix ``B`` is LLL-reduced with factor (``fl->delta``, ``fl->eta``), and otherwise returns zero. The ``mpfr`` variables used have their precision set to be exactly ``prec`` bits. The function is mainly intended to be used for testing purposes. It will not always work, but if it does the result is guaranteed. Uses the algorithm of Villard (see https://arxiv.org/abs/cs/0701183 ). .. function:: int fmpz_lll_is_reduced(const fmpz_mat_t B, const fmpz_lll_t fl, flint_bitcnt_t prec) Returns a non-zero value if the matrix ``B`` is LLL-reduced with factor (``fl->delta``, ``fl->eta``), and otherwise returns zero. The ``mpfr`` variables used, if any, have their precision set to be exactly ``prec`` bits. The function is mainly intended to be used for testing purposes. It first tests for LLL reducedness using :func:`fmpz_lll_is_reduced_d`, followed by :func:`fmpz_lll_is_reduced_mpfr` and finally calls :func:`fmpz_mat_is_reduced` or :func:`fmpz_mat_is_reduced_gram` (depending on the type of input as determined by ``fl->rt``), if required. .. function:: 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) Returns a non-zero value if the matrix ``B`` is LLL-reduced with factor (``fl->delta``, ``fl->eta``) and the squared Gram-Schmidt length of each `i`th vector (where `i` \ge ``newd``) is greater than ``gs_B``, and otherwise returns zero. The function is mainly intended to be used for testing purposes. It will not always work, but if it does the result is guaranteed. Uses the algorithm of Villard (see https://arxiv.org/abs/cs/0701183 ). .. function:: 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) Returns a non-zero value if the matrix ``B`` is LLL-reduced with factor (``fl->delta``, ``fl->eta``) and the squared Gram-Schmidt length of each `i`th vector (where `i` \ge ``newd``) is greater than ``gs_B``, and otherwise returns zero. The ``mpfr`` variables used have their precision set to be exactly ``prec`` bits. The function is mainly intended to be used for testing purposes. It will not always work, but if it does the result is guaranteed. Uses the algorithm of Villard (see https://arxiv.org/abs/cs/0701183 ). .. function:: 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) Returns a non-zero value if the matrix ``B`` is LLL-reduced with factor (``fl->delta``, ``fl->eta``) and the squared Gram-Schmidt length of each `i`th vector (where `i` \ge ``newd``) is greater than ``gs_B``, and otherwise returns zero. The ``mpfr`` variables used, if any, have their precision set to be exactly ``prec`` bits. The function is mainly intended to be used for testing purposes. It first tests for LLL reducedness using :func:`fmpz_lll_is_reduced_d_with_removal`, followed by :func:`fmpz_lll_is_reduced_mpfr_with_removal` and finally calls :func:`fmpz_mat_is_reduced_with_removal` or :func:`fmpz_mat_is_reduced_gram_with_removal` (depending on the type of input as determined by ``fl->rt``), if required. 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. 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 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. flint2-2.8.4/doc/source/fmpz_mat.rst000066400000000000000000001646341414523752600173660ustar00rootroot00000000000000.. _fmpz-mat: **fmpz_mat.h** -- matrices over the integers =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_mat_struct .. type:: fmpz_mat_t Description. 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:: 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(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_col_equal(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_row_equal(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, 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. .. 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, 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. .. 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_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_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:: int _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 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 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 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`. 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:: void 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 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 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. Modular gaussian elimination -------------------------------------------------------------------------------- .. function:: slong fmpz_mat_rref_mod(slong * perm, fmpz_mat_t A, const fmpz_t p) Uses fraction-free Gauss-Jordan elimination to set ``A`` to its reduced row echelon form and returns the rank of ``A``. All computations are done modulo p. 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``. 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(nmod_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 column 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. .. function:: void fmpz_mat_get_mpf_mat(mpf_mat_t B, const fmpz_mat_t A) Sets the entries of ``B`` as mpfs corresponding to the entries of ``A``. Cholesky Decomposition -------------------------------------------------------------------------------- .. 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) Returns a non-zero value if the basis ``A`` is LLL-reduced with factor (``delta``, ``eta``), and otherwise returns zero. The function is mainly intended to be used for testing purposes in the ``fmpz_lll`` module. .. function:: int fmpz_mat_is_reduced_gram(const fmpz_mat_t A, double delta, double eta) Returns a non-zero value if the basis with Gram matrix ``A`` is LLL-reduced with factor (``delta``, ``eta``), and otherwise returns zero. The function is mainly intended to be used for testing purposes in the ``fmpz_lll`` module. .. function:: int fmpz_mat_is_reduced_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``) and the squared Gram-Schmidt length of each `i`-th vector (where `i \ge` ``newd``) is greater than ``gs_B``, and otherwise returns zero. The function is mainly intended to be used for testing purposes in the ``fmpz_lll`` module. 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 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``). 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. flint2-2.8.4/doc/source/fmpz_mod.rst000066400000000000000000000131311414523752600173450ustar00rootroot00000000000000.. _fmpz-mod: **fmpz_mod.h** -- arithmetic modulo integers =============================================================================== Description. 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``. 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*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 maybe 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*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(const 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. flint2-2.8.4/doc/source/fmpz_mod_mat.rst000066400000000000000000000252331414523752600202140ustar00rootroot00000000000000.. _fmpz_mod_mat: **fmpz_mod_mat.h** -- matrices over integers mod n =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_mod_mat_struct .. type:: fmpz_mod_mat_t Description. .. type:: fmpz_mod_mat_struct .. type:: fmpz_mod_mat_t Description. 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) 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_t n) Initialise ``mat`` as a matrix with the given number of ``rows`` and ``cols`` and modulus ``n``. .. function:: void fmpz_mod_mat_init_set(fmpz_mod_mat_t mat, const fmpz_mod_mat_t src) 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) Clear ``mat`` and release any memory it used. Basic manipulation -------------------------------------------------------------------------------- .. function:: slong fmpz_mod_mat_nrows(const fmpz_mod_mat_t mat) Return the number of rows of ``mat``. .. function:: slong fmpz_mod_mat_ncols(const fmpz_mod_mat_t mat) Return the number of columns of ``mat``. .. function:: void _fmpz_mod_mat_set_mod(fmpz_mod_mat_t mat, const fmpz_t n) Set the modulus of the matrix ``mat`` to ``n``. .. function:: void fmpz_mod_mat_one(fmpz_mod_mat_t mat) Set ``mat`` to the identity matrix (ones down the diagonal). .. function:: void fmpz_mod_mat_zero(fmpz_mod_mat_t mat) Set ``mat`` to the zero matrix. .. function:: void fmpz_mod_mat_swap(fmpz_mod_mat_t mat1, fmpz_mod_mat_t mat2) Efficiently swap the matrices ``mat1`` and ``mat2``. .. function:: void fmpz_mod_mat_swap_entrywise(fmpz_mod_mat_t mat1, fmpz_mod_mat_t mat2) 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) Return `1` if ``mat`` has either zero rows or columns. .. function:: int fmpz_mod_mat_is_square(const fmpz_mod_mat_t mat) Return `1` if ``mat`` has the same number of rows and columns. .. function:: void _fmpz_mod_mat_reduce(fmpz_mod_mat_t mat) 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) 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) 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) 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) 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) 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) 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) 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) Set ``B`` to equal ``A``. .. function:: void fmpz_mod_mat_transpose(fmpz_mod_mat_t B, const fmpz_mod_mat_t A) 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) 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) 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) 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) Set ``C`` to `A - B`. .. function:: void fmpz_mod_mat_neg(fmpz_mod_mat_t B, const fmpz_mod_mat_t A) 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) 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, slong c) 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) 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) 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) 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) 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) 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) 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) void fmpz_mod_mat_mul_fmpz_vec_ptr(fmpz * const * c, const fmpz_mod_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 fmpz_mod_mat_fmpz_vec_mul(fmpz * c, const fmpz * a, slong alen, const fmpz_mod_mat_t B) void fmpz_mod_mat_fmpz_vec_mul_ptr(fmpz * const * c, const fmpz * const * a, slong alen, const fmpz_mod_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``. Trace --------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_trace(fmpz_t trace, const fmpz_mod_mat_t mat) Set ``trace`` to the trace of the matrix ``mat``. Gaussian elimination -------------------------------------------------------------------------------- .. function:: slong fmpz_mod_mat_rref(slong * perm, fmpz_mod_mat_t mat) Uses Gauss-Jordan elimination to set ``mat`` to its reduced row echelon form and returns the rank of ``mat``. If ``perm`` is non-``NULL``, the permutation of rows in the matrix will also be applied to ``perm``. Strong echelon form and Howell form -------------------------------------------------------------------------------- .. function:: void fmpz_mod_mat_strong_echelon_form(fmpz_mod_mat_t mat) 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) 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. flint2-2.8.4/doc/source/fmpz_mod_mpoly.rst000066400000000000000000001041651414523752600205750ustar00rootroot00000000000000.. _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(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``, ect. .. 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(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, 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 thows 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 thows 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, ulong const * 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, 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, ulong const * exp, fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_set_coeff_ui_ui(fmpz_mod_mpoly_t A, ulong c, ulong const * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_set_coeff_si_ui(fmpz_mod_mpoly_t A, slong c, ulong const * 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_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_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_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, 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, 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 cofficients of *A* when viewed as a polynomial in the variables *vars*. Return `1` for success and `0` for failure. Upon succcess, *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 vise 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. flint2-2.8.4/doc/source/fmpz_mod_mpoly_factor.rst000066400000000000000000000064551414523752600221360ustar00rootroot00000000000000.. _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 recommend 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. flint2-2.8.4/doc/source/fmpz_mod_poly.rst000066400000000000000000003004301414523752600204110ustar00rootroot00000000000000.. _fmpz-mod-poly: **fmpz_mod_poly.h** -- polynomials over integers mod n =============================================================================== Description. 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, const fmpz_mod_ctx_t ctx) 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, const fmpz_mod_ctx_t ctx) 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_t p) 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_t p) 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_t p) 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 -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_scalar_mul_fmpz(fmpz *res, const fmpz *poly, slong len, const fmpz_t x, const fmpz_t p) 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`. Scalar division -------------------------------------------------------------------------------- .. function:: void _fmpz_mod_poly_scalar_div_fmpz(fmpz *res, const fmpz *poly, slong len, const fmpz_t x, const fmpz_t p) 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_t p) 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, const fmpz_t p, 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_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_t p) 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_mulmod(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz * f, slong lenf, const fmpz_t p) 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_t p) 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, fmpz_t f) 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, fmpz_t f, 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_t p) 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_t p) 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_t p) 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_t p) 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_t p) 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_t p) 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_t p) 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_t p) 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_t p) 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_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_t p) 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_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 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_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_t p) 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)``. Requires temporary space ``(R, lenA)``. 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_div_basecase(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_div_newton_n_preinv (fmpz* Q, const fmpz* A, slong lenA, const fmpz* B, slong lenB, const fmpz* Binv, slong lenBinv, const fmpz_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 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_t p) 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_divrem_divconquer_recursive(fmpz * Q, fmpz * BQ, fmpz * W, const fmpz * A, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_t p) Computes ``(Q, lenB)``, ``(BQ, 2 lenB - 1)`` such that `BQ = B \times Q` and `A = B Q + R` where `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 `\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. .. function:: void _fmpz_mod_poly_divrem_divconquer(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_t p) 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 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_divconquer(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(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_t p) 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_t p) 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 *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p) 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, fmpz_mod_ctx_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 fmpz_mod_poly_divides_classical(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, 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, fmpz_mod_ctx_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 fmpz_mod_poly_divides(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, 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_newton(fmpz * Qinv, const fmpz * Q, slong n, const fmpz_t cinv, const fmpz_t p) 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_newton(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_newton_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`. .. function:: void _fmpz_mod_poly_inv_series(fmpz * Qinv, const fmpz * Q, slong n, const fmpz_t cinv, const fmpz_t p) 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, const fmpz_t p, slong n) 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_euclidean(fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p) 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_euclidean(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`. The algorithm used to compute `G` is the classical Euclidean algorithm. 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(fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p) 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_t p) 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_t p) 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_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 = \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_gcd_hgcd(fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_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 fmpz_mod_poly_gcd_hgcd(fmpz_mod_poly_t G, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) 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)` ring operations. For further details, see [ThullYap1990]_. .. function:: slong _fmpz_mod_poly_xgcd_euclidean(fmpz *G, fmpz *S, fmpz *T, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p) 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:: 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_t p) 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(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_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_hgcd(fmpz *G, fmpz *S, fmpz *T, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_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 fmpz_mod_poly_xgcd_hgcd(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:: 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_t p) 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 p) 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 p) 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_t p) 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_t p) 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_t p) 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_t p) 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_t p) 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_t p) 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_t p) 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_euclidean(fmpz_t res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t mod) Sets `r` to the resultant of ``(poly1, len1)`` and ``(poly2, len2)`` using the Euclidean algorithm. Assumes that ``len1 >= len2 > 0``. Assumes that the modulus is prime. .. function:: void fmpz_mod_poly_resultant_euclidean(fmpz_t r, 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` 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:: void _fmpz_mod_poly_resultant_hgcd(fmpz_t res, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t mod) Sets ``res`` to the resultant of ``(A, lenA)`` and ``(B, lenB)`` using the half-gcd algorithm. This algorithm computes the half-gcd as per :func:`_fmpz_mod_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 ``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 ``lenA >= lenB > 0``. Assumes that the modulus is prime. .. function:: void fmpz_mod_poly_resultant_hgcd(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` 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:: void _fmpz_mod_poly_resultant(fmpz_t res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t mod) Returns the resultant of ``(poly1, len1)`` and ``(poly2, len2)``. Assumes that ``len1 >= len2 > 0``. Assumes that 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$. 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_mod_poly_discriminant(fmpz_t d, const fmpz *poly, slong len, const fmpz_t mod) 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_t p) 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_t p) 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_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 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_t mod) 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_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 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_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. .. 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_horner(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p) Sets ``res`` to the composition of ``(poly1, len1)`` and ``(poly2, len2)`` using Horner's algorithm. 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_horner(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`` using Horner's algorithm. 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_mod_poly_compose_divconquer(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p) Sets ``res`` to the composition of ``(poly1, len1)`` and ``(poly2, len2)`` using a divide and conquer algorithm which takes out factors of ``poly2`` raised to `2^i` where possible. 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_divconquer(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`` using a divide and conquer algorithm which takes out factors of ``poly2`` raised to `2^i` where possible. 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_mod_poly_compose(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p) 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))`. 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_t p) 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_t p) 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_t p) 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_t p) 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_t p) 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_t p) 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_t p) 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_t p, 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_t mod) 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_t p) 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_t p) 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. 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``. flint2-2.8.4/doc/source/fmpz_mod_poly_factor.rst000066400000000000000000000232061414523752600217520ustar00rootroot00000000000000.. _fmpz-mod-poly-factor: **fmpz_mod_poly_factor.h** -- factorisation of polynomials over integers mod n ================================================================================================== Description. 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 return 1 if the polynomial ``f`` is irreducible or `0` otherwise, or set `r` to a nontrivial factor of `p`. This algorithm correctly determines whether `f` to 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_t p) 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_t p) 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. flint2-2.8.4/doc/source/fmpz_mpoly.rst000066400000000000000000001362521414523752600177400ustar00rootroot00000000000000.. _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_ctx_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_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(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 an 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 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_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 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_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``, ect. .. 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(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, 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 thows 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 thows 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, ulong const * exp, const fmpz_mpoly_ctx_t ctx) ulong fmpz_mpoly_get_coeff_ui_ui(const fmpz_mpoly_t A, ulong const * exp, const fmpz_mpoly_ctx_t ctx) slong fmpz_mpoly_get_coeff_si_ui(const fmpz_mpoly_t A, ulong const * 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, 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, ulong const * exp, fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_coeff_ui_ui(fmpz_mpoly_t A, ulong c, ulong const * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_set_coeff_si_ui(fmpz_mpoly_t A, slong c, ulong const * 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. 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_ui_fmpz(fmpz_mpoly_t A, ulong c, fmpz * const * 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_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, 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, 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 cofficients of *A* when viewed as a polynomial in the variables *vars*. Return `1` for success and `0` for failure. Upon succcess, *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*. 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 vise 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, slong bits, slong N) 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) .. 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, slong thread_limit) 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. The threaded version takes an upper limit on the number of threads to use, while the first version always uses one thread. .. 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) 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) 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) 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]``. flint2-2.8.4/doc/source/fmpz_mpoly_factor.rst000066400000000000000000000063271414523752600212750ustar00rootroot00000000000000.. _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 recommend 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. flint2-2.8.4/doc/source/fmpz_poly.rst000066400000000000000000004406271414523752600175670ustar00rootroot00000000000000.. _fmpz-poly: **fmpz_poly.h** -- univariate polynomials over the integers =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_poly_struct .. type:: fmpz_poly_t Description. 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, 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, 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:: void fmpz_poly_set_mpz(fmpz_poly_t poly, const mpz_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. One must call :func:`flint_randinit` before calling this function. .. 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. One must call :func:`flint_randinit` before calling this function. .. 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. One must call :func:`flint_randinit` before calling this function. .. 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. One must call :func:`flint_randinit` before calling this function. 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` is 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, ulong 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, ulong 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_mpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const mpz_t x) Sets ``poly1`` to ``poly2`` times the ``mpz_t`` `x`. .. function:: void fmpz_poly_scalar_mul_si(fmpz_poly_t poly1, 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, 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, fmpz_poly_t poly2, ulong exp) Sets ``poly1`` to ``poly2`` times ``2^exp``. .. 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_mpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const mpz_t x) Sets ``poly1`` to ``poly2`` divided by the ``mpz_t x``, rounding coefficients down toward `- \infty`. .. function:: void fmpz_poly_scalar_fdiv_si(fmpz_poly_t poly1, 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, 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, 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, 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, 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, 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_mpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const mpz_t x) Sets ``poly1`` to ``poly2`` divided by the ``mpz_t x``, assuming the coefficient is exact for every coefficient. .. function:: id fmpz_poly_scalar_divexact_si(fmpz_poly_t poly1, 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, 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_t 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\"{o}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. 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_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-oadded. .. 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 in [p. 461][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 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][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 GCD's 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][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`. 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 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 Qlen, 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 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``. .. 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``. .. 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][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``. .. 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. .. 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. .. 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``. 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:: void fmpz_poly_evaluate_mpq(mpq_t res, const fmpz_poly_t f, const mpq_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 of ``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_lagrange(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) Sets ``Qinv`` to the compositional inverse or reversion of ``(Q, Qlen)`` as a power series, i.e. computes `Q^{-1}` such that `Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n`. The arguments may not be aliased, and ``Qlen`` must be at least 2. It is required that `Q_0 = 0` and `Q_1 = \pm 1`. This implementation uses the Lagrange inversion formula. .. function:: void fmpz_poly_revert_series_lagrange(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`. This implementation uses the Lagrange inversion formula. .. function:: void _fmpz_poly_revert_series_lagrange_fast(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) Sets ``Qinv`` to the compositional inverse or reversion of ``(Q, Qlen)`` as a power series, i.e. computes `Q^{-1}` such that `Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n`. The arguments may not be aliased, and ``Qlen`` must be at least 2. It is required that `Q_0 = 0` and `Q_1 = \pm 1`. This implementation uses a reduced-complexity implementation of the Lagrange inversion formula. .. function:: void fmpz_poly_revert_series_lagrange_fast(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`. This implementation uses a reduced-complexity implementation of the Lagrange inversion formula. .. function:: void _fmpz_poly_revert_series_newton(fmpz * Qinv, const fmpz * Q, slong Qlen, 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`. The arguments may not be aliased, and ``Qlen`` must be at least 2. It is required that `Q_0 = 0` and `Q_1 = \pm 1`. This implementation uses Newton iteration [BrentKung1978]_. .. function:: void fmpz_poly_revert_series_newton(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`. This implementation uses Newton iteration [BrentKung1978]_. .. function:: void _fmpz_poly_revert_series(fmpz * Qinv, const fmpz * Q, slong Qlen, 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`. The arguments may not be aliased, and ``Qlen`` must be at least 2. It is required that `Q_0 = 0` and `Q_1 = \pm 1`. This implementation defaults to the fast version of Lagrange interpolation. .. function:: 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`. This implementation defaults to the fast version of Lagrange interpolation. 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`(```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`(```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][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 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 ``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 simple 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, 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, 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, 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 <= r < m_1 m_2` are computed, while if ``sign`` = 1, residues `-m_1 m_2/2 <= 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(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. .. 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. 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`. flint2-2.8.4/doc/source/fmpz_poly_factor.rst000066400000000000000000000132261414523752600211140ustar00rootroot00000000000000.. _fmpz-poly-factor: **fmpz_poly_factor.h** -- factorisation of polynomials over the integers =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_poly_factor_struct .. type:: fmpz_poly_factor_t Description. 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, 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, 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, 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 factorzation 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, 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``. flint2-2.8.4/doc/source/fmpz_poly_mat.rst000066400000000000000000000420211414523752600204120ustar00rootroot00000000000000.. _fmpz-poly-mat: **fmpz_poly_mat.h** -- matrices of polynomials over the integers =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_poly_mat_struct .. type:: fmpz_poly_mat_t Description. 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(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 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 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 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 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. flint2-2.8.4/doc/source/fmpz_poly_q.rst000066400000000000000000000223131414523752600200730ustar00rootroot00000000000000.. _fmpz-poly-q: **fmpz_poly_q.h** -- rational functions over the rational numbers =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fmpz_poly_q_struct .. type:: fmpz_poly_q_t Description. Memory management -------------------------------------------------------------------------------- We represent a rational function over `\mathbf{Q}` as the quotient of two coprime integer polynomials of type ``fmpz_poly_t``, enforcing that the leading coefficient of the denominator is positive. The zero function is represented as `0/1`. .. 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_mpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpz_t x) Sets ``rop`` to the product of the rational function ``op`` and the ``mpz_t`` integer `x`. .. function:: void fmpz_poly_q_scalar_mul_mpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpq_t x) Sets ``rop`` to the product of the rational function ``op`` and the ``mpq_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_mpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpz_t x) Sets ``rop`` to the quotient of the rational function ``op`` and the ``mpz_t`` integer `x`. .. function:: void fmpz_poly_q_scalar_div_mpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpq_t x) Sets ``rop`` to the quotient of the rational function ``op`` and the ``mpq_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(mpq_t rop, const fmpz_poly_q_t f, const mpq_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``. flint2-2.8.4/doc/source/fmpz_vec.rst000066400000000000000000000405551414523752600173550ustar00rootroot00000000000000.. _fmpz-vec: **fmpz_vec.h** -- vectors of integers ================================================================================================== Description. 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:: ulong _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 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:: slong _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 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. .. 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. .. function:: void _fmpz_vec_get_mpf_vec(mpf * appv, const fmpz * vec, slong len) Export the array of ``len`` entries starting at the pointer ``vec`` to an array of mpfs ``appv``. 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:: id _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, ulong 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_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t c) Adds ``(vec2, len2)`` times `c` to ``(vec1, len2)``, where `c` is a ``fmpz_t``. .. function:: void _fmpz_vec_scalar_addmul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c) Adds ``(vec2, len2)`` times `c` to ``(vec1, len2)``, where `c` is a ``slong``. .. 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(fmpz_t res, const fmpz * vec1, const fmpz * vec2, slong len2) Sets ``res`` to the dot product of ``(vec1, len2)`` and ``(vec2, len2)``. .. function:: void _fmpz_vec_dot_ptr(fmpz_t res, const fmpz * vec1, fmpz ** const vec2, slong offset, slong len) Sets ``res`` to the dot product of ``len`` values at ``vec1`` and the ``len`` values ``vec2[i] + offset`` for ``0 \leq i < len``. flint2-2.8.4/doc/source/fq.rst000066400000000000000000000425031414523752600161450ustar00rootroot00000000000000.. _fq: **fq.h** -- finite fields =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_ctx_struct .. type:: fq_ctx_t Description. .. type:: fq_struct .. type:: fq_t Description. 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_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:: long 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:: 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``. .. function:: void fq_ctx_randtest(fq_ctx_t ctx) Initializes ``ctx`` to a random finite field. Assumes that ``fq_ctx_init`` has not been called on ``ctx`` already. .. function:: void fq_ctx_randtest_reducible(fq_ctx_t ctx) Initializes ``ctx`` to a random extension of a prime field. The modulus may or may not be irreducible. Assumes that ``fq_ctx_init`` has not been called on ``ctx`` already. 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:: void 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:: 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_t 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``. flint2-2.8.4/doc/source/fq_default.rst000066400000000000000000000412061414523752600176500ustar00rootroot00000000000000.. _fq_default_default: **fq_default_default.h** -- unified finite fields =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_default_default_ctx_t Description. .. type:: fq_default_default_t Description. 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:: 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, const fq_default_t op1, const 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:: int 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:: void 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:: 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 fmpz_mod_ctx_t mod_ctx, 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 fmpz_mod_ctx_t mod_ctx, 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 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`. flint2-2.8.4/doc/source/fq_default_mat.rst000066400000000000000000000414471414523752600205200ustar00rootroot00000000000000.. _fq_default_mat: **fq_default_mat.h** -- matrices over finite fields =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_default_mat_t Description. 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, 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, 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, fq_default_mat_t mat, slong i, slong j) 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, 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(fq_default_mat_t mat, const fq_default_ctx_t ctx) Returns the number of rows in ``mat``. .. function:: slong fq_default_mat_ncols(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) 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) 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) 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) 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:: void 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:: void 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:: void fq_default_mat_randrank(fq_default_mat_t mat, slong rank, flint_rand_t state, 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, slong count, flint_rand_t state, 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(fq_default_mat_t mat1, 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, 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 A, const fq_default_ctx_t ctx) 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. 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, fq_default_mat_t A, 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, 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. flint2-2.8.4/doc/source/fq_default_poly.rst000066400000000000000000000542341414523752600207200ustar00rootroot00000000000000.. _fq_default_poly: **fq_default_poly.h** -- univariate polynomials over finite fields =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_default_poly_t Description. 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:: long fq_default_poly_degree(fq_default_poly_t poly, const fq_default_ctx_t ctx) Returns the degree of the polynomial ``poly``. .. function:: long fq_default_poly_length(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) 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, 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, 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:: long 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(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, slong n, 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``. 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. flint2-2.8.4/doc/source/fq_default_poly_factor.rst000066400000000000000000000155111414523752600222510ustar00rootroot00000000000000.. _fq-poly_factor: **fq_default_poly_factor.h** -- factorisation of univariate polynomials over finite fields ========================================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_default_poly_factor_t Description. 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 functions 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 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. flint2-2.8.4/doc/source/fq_embed.rst000066400000000000000000000105621414523752600173010ustar00rootroot00000000000000 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``. flint2-2.8.4/doc/source/fq_mat.rst000066400000000000000000000522771414523752600170170ustar00rootroot00000000000000.. _fq-mat: **fq_mat.h** -- matrices over finite fields =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_mat_struct .. type:: fq_mat_t Description. 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, 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, 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(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, 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(fq_mat_t mat, const fq_ctx_t ctx) Returns the number of rows in ``mat``. .. function:: slong fq_mat_ncols(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) 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) 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) 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) 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) 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:: void 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:: void 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, fq_struct * diag, slong n, flint_rand_t state, 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, slong rank, flint_rand_t state, 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, slong count, flint_rand_t state, 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(fq_mat_t mat1, 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) void fq_mat_mul_vec_ptr(fq_struct * const * c, const fq_mat_t A, const fq_struct * 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 fq_mat_vec_mul(fq_struct * c, const fq_struct * a, slong alen, const fq_mat_t B) void fq_mat_vec_mul_ptr(fq_struct * const * c, const fq_struct * const * a, slong alen, const fq_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``. Inverse -------------------------------------------------------------------------------- .. function:: int fq_mat_inv(fq_mat_t B, fq_mat_t A, 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 A, const fq_ctx_t ctx) 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 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, fq_mat_t A, 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, 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. flint2-2.8.4/doc/source/fq_nmod.rst000066400000000000000000000443701414523752600171660ustar00rootroot00000000000000.. _fq-nmod: **fq_nmod.h** -- finite fields (word-size characteristic) =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_nmod_ctx_struct .. type:: fq_nmod_ctx_t Description. .. type:: fq_nmod_struct .. type:: fq_nmod_t Description. Context Management -------------------------------------------------------------------------------- .. function:: void fq_nmod_ctx_init(fq_nmod_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_nmod_ctx_init_conway(fq_nmod_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_nmod_ctx_init_conway(fq_nmod_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_nmod_ctx_init_modulus(fq_nmod_ctx_t ctx, 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_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:: long 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:: fmpz * fq_nmod_ctx_prime(const fq_nmod_ctx_t ctx) Returns a pointer to the prime `p` in 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``. .. function:: void fq_nmod_ctx_randtest(fq_nmod_ctx_t ctx) Initializes ``ctx`` to a random finite field. Assumes that ``fq_nmod_ctx_init`` has not been called on ``ctx`` already. .. function:: void fq_nmod_ctx_randtest_reducible(fq_nmod_ctx_t ctx) Initializes ``ctx`` to a random extension of a word-sized prime field. The modulus may or may not be irreducible. Assumes that ``fq_nmod_ctx_init`` as not been called on ``ctx`` already. 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_ptr 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_ptr 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_ptr 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_ptr * rop, mp_srcptr * 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`` 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_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:: void 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^{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_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:: int 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:: void 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:: 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 of 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, mp_srcptr * 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, mp_srcptr * 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_ptr * rop, mp_srcptr * 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_t 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``. flint2-2.8.4/doc/source/fq_nmod_embed.rst000066400000000000000000000110011414523752600203030ustar00rootroot00000000000000 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``. flint2-2.8.4/doc/source/fq_nmod_mat.rst000066400000000000000000000546441414523752600200340ustar00rootroot00000000000000.. _fq-nmod-mat: **fq_nmod_mat.h** -- matrices over finite fields (word-size characteristic) =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_nmod_mat_struct .. type:: fq_nmod_mat_t Description. 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, 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, 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(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, 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(fq_nmod_mat_t mat, const fq_nmod_ctx_t ctx) Returns the number of rows in ``mat``. .. function:: slong fq_nmod_mat_ncols(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) 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) 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) 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) 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) 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:: void 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:: void 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, fq_nmod_struct * diag, slong n, flint_rand_t state, 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, slong rank, flint_rand_t state, 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, slong count, flint_rand_t state, 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(fq_nmod_mat_t mat1, 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) 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) 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) 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) 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, 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_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 A, const fq_nmod_ctx_t ctx) 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 fq_nmod_mat_reduce_row(fq_nmod_mat_t A, slong * P, slong * L, slong n, 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, fq_nmod_mat_t A, 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, 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, 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, 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, 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. flint2-2.8.4/doc/source/fq_nmod_mpoly.rst000066400000000000000000000705571414523752600204140ustar00rootroot00000000000000.. _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(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``, ect. .. 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(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 thows 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 thows 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_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, 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, 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 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 cofficients of *A* when viewed as a polynomial in the variables *vars*. Return `1` for success and `0` for failure. Upon succcess, *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 vise 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*. flint2-2.8.4/doc/source/fq_nmod_mpoly_factor.rst000066400000000000000000000064421414523752600217420ustar00rootroot00000000000000.. _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 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, 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 recommend 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. flint2-2.8.4/doc/source/fq_nmod_poly.rst000066400000000000000000002262311414523752600202270ustar00rootroot00000000000000.. _fq-nmod-poly: **fq_nmod_poly.h** -- univariate polynomials over finite fields (word-size characteristic) ========================================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_nmod_poly_struct .. type:: fq_nmod_poly_t Description. 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(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_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:: long fq_nmod_poly_degree(fq_nmod_poly_t poly, const fq_nmod_ctx_t ctx) Returns the degree of the polynomial ``poly``. .. function:: long fq_nmod_poly_length(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, 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, 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_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_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) 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_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_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_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_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, 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. .. 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, 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, 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, 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, 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, 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, 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, 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:: long _fq_nmod_poly_hamming_weight(const fq_nmod_poly *op, slong len, const fq_nmod_ctx_t ctx) Returns the number of non-zero entries in ``(op, len)``. .. function:: long 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_basecase(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_basecase(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(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_basecase(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) 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)``. Requires temporary space ``(R, lenA)``. If ``R`` is ``NULL``, then the temporary space will be allocated. 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. .. function:: void fq_nmod_poly_div_basecase(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_divrem_divconquer_recursive(fq_nmod_struct * Q, fq_nmod_struct * BQ, fq_nmod_struct * W, const fq_nmod_struct * A, const fq_nmod_struct * B, slong lenB, const fq_nmod_t invB, const fq_nmod_ctx_t ctx) Computes ``(Q, lenB)``, ``(BQ, 2 lenB - 1)`` such that `BQ = B \times Q` and `A = B Q + R` where `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible and that ``invB`` is the inverse. 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. .. function:: void _fq_nmod_poly_divrem_divconquer(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` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible 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 fq_nmod_poly_divrem_divconquer(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` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that `B` is non-zero and that the leading coefficient of `B` is invertible. .. 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_struct ctx_t) 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_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_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(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n, 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_nmod_poly_div_series(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, slong n, 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_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:: long _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:: void fq_nmod_poly_gcd_euclidean(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 Euclidean 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:: long _fq_nmod_poly_gcd_euclidean(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_hgcd(fq_nmod_struct **M, slong *lenM, fq_nmod_struct *A, slong *lenA, fq_nmod_struct *B, slong *lenB, const fq_nmod_struct * a, slong lena, const fq_nmod_struct *b, slong lenb, const fq_nmod_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:: void fq_nmod_poly_gcd_hgcd(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 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:: long _fq_nmod_poly_gcd_hgcd(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`` using the HGCD algorithm, 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_euclidean(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 fmpz_t invB, 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_euclidean(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(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 fmpz_t invB, 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 fmpz_t invB, 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``. 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_divconquer(fq_nmod_struct *rop, const fq_nmod_struct *op1, slong len1, const fq_nmod_struct *op2, slong len2, const fq_nmod_ctx_t ctx) Computes the composition of ``(op1, len1)`` and ``(op2, len2)`` using a divide and conquer approach and places the result into ``rop``, assuming ``rop`` can hold the output of length ``(len1 - 1) * (len2 - 1) + 1``. Assumes ``len1, len2 > 0``. Does not support aliasing between ``rop`` and any of ``(op1, len1)`` and ``(op2, len2)``. .. function:: void fq_nmod_poly_compose_divconquer(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_horner(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_horner(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 more precise, denoting ``rop``, ``op1``, and ``op2`` by `f`, `g`, and `h`, sets `f(t) = g(h(t))`. This implementation uses Horner's method. .. 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. flint2-2.8.4/doc/source/fq_nmod_poly_factor.rst000066400000000000000000000244351414523752600215670ustar00rootroot00000000000000.. _fq-nmod-poly-factor: **fq_nmod_poly_factor.h** -- factorisation of univariate polynomials over finite fields (word-size characteristic) ================================================================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_nmod_poly_factor_struct .. type:: fq_nmod_poly_factor_t Description. 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 functions 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 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) 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} mod v` for `0 <= 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. flint2-2.8.4/doc/source/fq_nmod_vec.rst000066400000000000000000000106401414523752600200140ustar00rootroot00000000000000.. _fq-nmod-vec: **fq_nmod_vec.h** -- vectors over finite fields (word-size characteristic) =============================================================================== Description. 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 * 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 ctx_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``). flint2-2.8.4/doc/source/fq_poly.rst000066400000000000000000002165531414523752600172200ustar00rootroot00000000000000.. _fq-poly: **fq_poly.h** -- univariate polynomials over finite fields =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_poly_struct .. type:: fq_poly_t Description. 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(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:: long fq_poly_degree(fq_poly_t poly, const fq_ctx_t ctx) Returns the degree of the polynomial ``poly``. .. function:: long fq_poly_length(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, 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, 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) 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, 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. .. 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, 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, 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, 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, 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, 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, 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, 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:: long _fq_poly_hamming_weight(const fq_poly *op, slong len, const fq_ctx_t ctx) Returns the number of non-zero entries in ``(op, len)``. .. function:: long 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_basecase(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_basecase(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(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_basecase(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) 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)``. Requires temporary space ``(R, lenA)``. If ``R`` is ``NULL``, then the temporary space will be allocated. 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. .. function:: void fq_poly_div_basecase(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_divrem_divconquer_recursive(fq_struct * Q, fq_struct * BQ, fq_struct * W, const fq_struct * A, const fq_struct * B, slong lenB, const fq_t invB, const fq_ctx_t ctx) Computes ``(Q, lenB)``, ``(BQ, 2 lenB - 1)`` such that `BQ = B \times Q` and `A = B Q + R` where `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible and that ``invB`` is the inverse. 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. .. function:: void _fq_poly_divrem_divconquer(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` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible 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 fq_poly_divrem_divconquer(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` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that `B` is non-zero and that the leading coefficient of `B` is invertible. .. 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_struct ctx_t) 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_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_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_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(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n, 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(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, slong n, 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:: long _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:: void fq_poly_gcd_euclidean(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 Euclidean 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:: long _fq_poly_gcd_euclidean(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_hgcd(fq_struct **M, slong *lenM, fq_struct *A, slong *lenA, fq_struct *B, slong *lenB, const fq_struct * a, slong lena, const fq_struct *b, slong lenb, const fq_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:: void fq_poly_gcd_hgcd(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 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:: long _fq_poly_gcd_hgcd(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`` using the HGCD algorithm, 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_euclidean(fq_struct *G, fq_struct *S, fq_struct *T, const fq_struct *A, slong lenA, const fq_struct *B, slong lenB, const fmpz_t invB, 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_euclidean(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(fq_struct *G, fq_struct *S, fq_struct *T, const fq_struct *A, slong lenA, const fq_struct *B, slong lenB, const fmpz_t invB, 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 fmpz_t invB, 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``. 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_divconquer(fq_struct *rop, const fq_struct *op1, slong len1, const fq_struct *op2, slong len2, const fq_ctx_t ctx) Computes the composition of ``(op1, len1)`` and ``(op2, len2)`` using a divide and conquer approach and places the result into ``rop``, assuming ``rop`` can hold the output of length ``(len1 - 1) * (len2 - 1) + 1``. Assumes ``len1, len2 > 0``. Does not support aliasing between ``rop`` and any of ``(op1, len1)`` and ``(op2, len2)``. .. function:: void fq_poly_compose_divconquer(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_horner(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_horner(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 more precise, denoting ``rop``, ``op1``, and ``op2`` by `f`, `g`, and `h`, sets `f(t) = g(h(t))`. This implementation uses Horner's method. .. 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. flint2-2.8.4/doc/source/fq_poly_factor.rst000066400000000000000000000232401414523752600205430ustar00rootroot00000000000000.. _fq-poly-factor: **fq_poly_factor.h** -- factorisation of univariate polynomials over finite fields ================================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_poly_factor_struct .. type:: fq_poly_factor_t Description. 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 functions 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 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) 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}\mod v` for `0 <= 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. flint2-2.8.4/doc/source/fq_vec.rst000066400000000000000000000100531414523752600167750ustar00rootroot00000000000000.. _fq-vec: **fq_vec.h** -- vectors over finite fields =============================================================================== Description. 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 * 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 ctx_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``). flint2-2.8.4/doc/source/fq_zech.rst000066400000000000000000000466431414523752600171670ustar00rootroot00000000000000.. _fq-zech: **fq_zech.h** -- finite fields (Zech logarithm representation) =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_zech_ctx_struct .. type:: fq_zech_ctx_t Description. .. type:: fq_zech_struct .. type:: fq_zech_t Description. Context Management -------------------------------------------------------------------------------- .. function:: void fq_zech_ctx_init(fq_zech_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 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(fq_zech_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 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(fq_zech_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 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(fq_zech_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 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, 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, 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_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:: long 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:: fmpz * fq_zech_ctx_prime(const fq_zech_ctx_t ctx) Returns a pointer to the prime `p` in 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}}. .. function:: void fq_zech_ctx_randtest(fq_zech_ctx_t ctx) Initializes ``ctx`` to a random finite field. Assumes that ``fq_zech_ctx_init`` has not been called on ``ctx`` already. .. function:: void fq_zech_ctx_randtest_reducible(fq_zech_ctx_t ctx) Since the Zech logarithm representation does not work with a non-irreducible modulus, does the same as ``fq_zech_ctx_randtest``. 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(mp_ptr *rop, mp_srcptr *op, slong len, const fmpz_t e, const fq_zech_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_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:: void 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:: int 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:: void 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:: 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_t 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``. flint2-2.8.4/doc/source/fq_zech_embed.rst000066400000000000000000000107761414523752600203210ustar00rootroot00000000000000 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``. flint2-2.8.4/doc/source/fq_zech_mat.rst000066400000000000000000000517611414523752600200250ustar00rootroot00000000000000.. _fq-zech-mat: **fq_zech_mat.h** -- matrices over finite fields (Zech logarithm representation) ================================================================================ Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_zech_mat_struct .. type:: fq_zech_mat_t Description. 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, 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, 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(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, 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(fq_zech_mat_t mat, const fq_zech_ctx_t ctx) Returns the number of rows in ``mat``. .. function:: slong fq_zech_mat_ncols(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) 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:: void 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:: void 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, fq_zech_struct * diag, slong n, flint_rand_t state, 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, slong rank, flint_rand_t state, 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, slong count, flint_rand_t state, 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(fq_zech_mat_t mat1, 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) 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) 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) 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) 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 A, const fq_zech_ctx_t ctx) 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 fq_zech_mat_reduce_row(fq_zech_mat_t A, slong * P, slong * L, slong n, 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, fq_zech_mat_t A, 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, 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, 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) 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, 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. flint2-2.8.4/doc/source/fq_zech_poly.rst000066400000000000000000002233601414523752600202230ustar00rootroot00000000000000.. _fq-zech-poly: **fq_zech_poly.h** -- univariate polynomials over finite fields (Zech logarithm representation) =============================================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_zech_poly_struct .. type:: fq_zech_poly_t Description. 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(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_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:: long fq_zech_poly_degree(fq_zech_poly_t poly, const fq_zech_ctx_t ctx) Returns the degree of the polynomial ``poly``. .. function:: long fq_zech_poly_length(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, 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, 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_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_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) 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_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_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_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_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(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(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, 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. .. 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, 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, 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, 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, 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, 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, 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, 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:: long _fq_zech_poly_hamming_weight(const fq_zech_poly *op, slong len, const fq_zech_ctx_t ctx) Returns the number of non-zero entries in ``(op, len)``. .. function:: long 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_basecase(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_basecase(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(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_basecase(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) 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)``. Requires temporary space ``(R, lenA)``. If ``R`` is ``NULL``, then the temporary space will be allocated. 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. .. function:: void fq_zech_poly_div_basecase(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_divrem_divconquer_recursive(fq_zech_struct * Q, fq_zech_struct * BQ, fq_zech_struct * W, const fq_zech_struct * A, const fq_zech_struct * B, slong lenB, const fq_zech_t invB, const fq_zech_ctx_t ctx) Computes ``(Q, lenB)``, ``(BQ, 2 lenB - 1)`` such that `BQ = B \times Q` and `A = B Q + R` where `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible and that ``invB`` is the inverse. 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. .. function:: void _fq_zech_poly_divrem_divconquer(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` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that the leading coefficient of `B` is invertible 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 fq_zech_poly_divrem_divconquer(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` and `0 \leq \operatorname{len}(R) < \operatorname{len}(B)`. Assumes that `B` is non-zero and that the leading coefficient of `B` is invertible. .. 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_struct ctx_t) 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_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_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(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n, 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_zech_poly_div_series(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, slong n, 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_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:: long _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:: void fq_zech_poly_gcd_euclidean(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 Euclidean 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:: long _fq_zech_poly_gcd_euclidean(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_hgcd(fq_zech_struct **M, slong *lenM, fq_zech_struct *A, slong *lenA, fq_zech_struct *B, slong *lenB, const fq_zech_struct * a, slong lena, const fq_zech_struct *b, slong lenb, const fq_zech_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:: void fq_zech_poly_gcd_hgcd(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 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:: long _fq_zech_poly_gcd_hgcd(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`` using the HGCD algorithm, 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_euclidean(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 fmpz_t invB, 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_euclidean(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(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 fmpz_t invB, 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 fmpz_t invB, 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``. 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_divconquer(fq_zech_struct *rop, const fq_zech_struct *op1, slong len1, const fq_zech_struct *op2, slong len2, const fq_zech_ctx_t ctx) Computes the composition of ``(op1, len1)`` and ``(op2, len2)`` using a divide and conquer approach and places the result into ``rop``, assuming ``rop`` can hold the output of length ``(len1 - 1) * (len2 - 1) + 1``. Assumes ``len1, len2 > 0``. Does not support aliasing between ``rop`` and any of ``(op1, len1)`` and ``(op2, len2)``. .. function:: void fq_zech_poly_compose_divconquer(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_horner(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_horner(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 more precise, denoting ``rop``, ``op1``, and ``op2`` by `f`, `g`, and `h`, sets `f(t) = g(h(t))`. This implementation uses Horner's method. .. 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. flint2-2.8.4/doc/source/fq_zech_poly_factor.rst000066400000000000000000000244411414523752600215600ustar00rootroot00000000000000.. _fq-zech-poly-factor: **fq_zech_poly_factor.h** -- factorisation of univariate polynomials over finite fields (Zech logarithm representation) ======================================================================================================================= Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: fq_zech_poly_factor_struct .. type:: fq_zech_poly_factor_t Description. 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 functions 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 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) 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} mod v` for `0 <= 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. flint2-2.8.4/doc/source/fq_zech_vec.rst000066400000000000000000000106451414523752600200150ustar00rootroot00000000000000.. _fq-zech-vec: **fq_zech_vec.h** -- vectors over finite fields (Zech logarithm representation) =============================================================================== Description. 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 * 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 ctx_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``). flint2-2.8.4/doc/source/index.rst000066400000000000000000000057631414523752600166550ustar00rootroot00000000000000.. 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, maintained by William Hart and Fredrik Johansson. * Source code on GitHub: https://github.com/wbhart/flint2 * Issue tracker: https://github.com/wbhart/flint2/issues * Mailing list: https://groups.google.com/group/flint-devel FLINT is free software distributed under the GNU Lesser General Public License (LGPL), version 2.1 or later. Introduction ------------ .. toctree:: :maxdepth: 1 introduction.rst building.rst bug_reporting.rst contributors.rst examples.rst macros.rst memory.rst portability.rst threading.rst General utilities ----------------- .. toctree:: :maxdepth: 1 flint.rst profiler.rst thread_pool.rst perm.rst mpoly.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 qsieve.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 Integers mod n --------------- .. toctree:: :maxdepth: 1 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_mat.rst fmpz_mod_poly.rst fmpz_mod_poly_factor.rst fmpz_mod_mpoly.rst fmpz_mod_mpoly_factor.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 d_vec.rst d_mat.rst mpf_vec.rst mpf_mat.rst mpfr_vec.rst mpfr_mat.rst C++ Interface ----------------------------------- .. toctree:: :maxdepth: 1 flintxx.rst References ---------------- .. toctree:: :maxdepth: 1 references.rst flint2-2.8.4/doc/source/introduction.rst000066400000000000000000000057621414523752600202660ustar00rootroot00000000000000.. _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 William Hart of Technische Universitaet in Kaiserslautern and 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 Hanson, 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 2 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 and ia64 machines. As of version 2.0, FLINT required GCC version 2.96 or later, either MPIR (2.6.0 or later) or GMP (5.1.1 or later), and MPFR 3.0.0 or later. 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 ``fmpz_poly/add.c`` has test code in the file ``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 LGPL License, version 2.1+. There is a copy of the license included in the repository and distribution tarballs. flint2-2.8.4/doc/source/long_extras.rst000066400000000000000000000033671414523752600200710ustar00rootroot00000000000000.. _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_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`. flint2-2.8.4/doc/source/longlong.rst000066400000000000000000000117651414523752600173640ustar00rootroot00000000000000.. _longlong: **longlong.h** -- support functions for multi-word arithmetic =============================================================================== Auxiliary asm macros -------------------------------------------------------------------------------- .. macro:: umul_ppmm(high_prod, low_prod, multipler, multiplicand) Multiplies two single limb integers ``MULTIPLER`` and ``MULTIPLICAND``, and generates a two limb product in ``HIGH_PROD`` and ``LOW_PROD``. .. macro:: smul_ppmm(high_prod, low_prod, multipler, 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:: count_leading_zeros(count, x) Counts 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 count is undefined. .. macro:: count_trailing_zeros(count, x) As for ``count_leading_zeros()``, but counts from the least significant end. If ``x`` is zero then count 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) 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. .. 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 flint2-2.8.4/doc/source/macros.rst000066400000000000000000000043001414523752600170140ustar00rootroot00000000000000.. _macros: **Macros** =============================================================================== Flint 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 function ``FLINT_BIT_COUNT(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. flint2-2.8.4/doc/source/memory.rst000066400000000000000000000046161414523752600170520ustar00rootroot00000000000000.. _memory: **Memory management** =============================================================================== Memory management in FLINT ------------------------------------------------------------------------------- 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. 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, cached data is kept in thread-local storage by default (unless configured otherwise). Cached data can be freed by calling the ``flint_cleanup()`` function. It is recommended to call ``flint_cleanup()`` right before exiting a thread, and at the end of the main program. 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()``. Flint also makes use of ``malloc``, ``realloc``, ``calloc`` and ``free`` by default to allocate memory internally. The user is able to 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). 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, as many small allocations on the stack can exhaust the stack causing a stack overflow. flint2-2.8.4/doc/source/mpf_mat.rst000066400000000000000000000114361414523752600171630ustar00rootroot00000000000000.. _mpf-mat: **mpf_mat.h** -- matrices of MPF floating-point numbers =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: void mpf_mat_init(mpf_mat_t mat, slong rows, slong cols, flint_bitcnt_t prec) Initialises a matrix with the given number of rows and columns and the given precision for use. The precision is at least the precision of the entries. .. function:: void mpf_mat_clear(mpf_mat_t mat) Clears the given matrix. Basic assignment and manipulation -------------------------------------------------------------------------------- .. function:: void mpf_mat_set(mpf_mat_t mat1, const mpf_mat_t mat2) Sets ``mat1`` to a copy of ``mat2``. The dimensions of ``mat1`` and ``mat2`` must be the same. .. function:: void mpf_mat_swap(mpf_mat_t mat1, mpf_mat_t mat2) Swaps two matrices. The dimensions of ``mat1`` and ``mat2`` are allowed to be different. .. function:: void mpf_mat_swap_entrywise(mpf_mat_t mat1, mpf_mat_t mat2) Swaps two matrices by swapping the individual entries rather than swapping the contents of the structs. .. function:: mpf * mpf_mat_entry(const mpf_mat_t * mat, slong i, slong j) Returns a reference to the entry of ``mat`` at row `i` and column `j`. Both `i` and `j` must not exceed the dimensions of the matrix. The return value can be used to either retrieve or set the given entry. .. function:: void mpf_mat_zero(mpf_mat_t mat) Sets all entries of ``mat`` to 0. .. function:: void mpf_mat_one(mpf_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. Random matrix generation -------------------------------------------------------------------------------- .. function:: void mpf_mat_randtest(mpf_mat_t mat, flint_ranmpf_t state, flint_bitcnt_t bits) Sets the entries of ``mat`` to random numbers in the interval `[0, 1)` with ``bits`` significant bits in the mantissa or less if their precision is smaller. Input and output -------------------------------------------------------------------------------- .. function:: void mpf_mat_print(const mpf_mat_t mat) Prints the given matrix to the stream ``stdout``. Comparison -------------------------------------------------------------------------------- .. function:: int mpf_mat_equal(const mpf_mat_t mat1, const mpf_mat_t mat2) Returns a non-zero value if ``mat1`` and ``mat2`` have the same dimensions and entries, and zero otherwise. .. function:: int mpf_mat_approx_equal(const mpf_mat_t mat1, const mpf_mat_t mat2, flint_bitcnt_t bits) Returns a non-zero value if ``mat1`` and ``mat2`` have the same dimensions and the first ``bits`` bits of their entries are equal, and zero otherwise. .. function:: int mpf_mat_is_zero(const mpf_mat_t mat) Returns a non-zero value if all entries ``mat`` are zero, and otherwise returns zero. .. function:: int mpf_mat_is_empty(const mpf_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 mpf_mat_is_square(const mpf_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. Matrix multiplication -------------------------------------------------------------------------------- .. function:: void mpf_mat_mul(mpf_mat_t C, const mpf_mat_t A, const mpf_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. Gram-Schmidt Orthogonalisation and QR Decomposition -------------------------------------------------------------------------------- .. function:: void mpf_mat_gso(mpf_mat_t B, const mpf_mat_t A) Takes a subset of `R^m` `S = {a_1, a_2, \ldots ,a_n}` (as the columns of a `m x n` matrix ``A``) and generates an orthonormal set `S' = {b_1, b_2, \ldots ,b_n}` (as the columns of the `m x n` matrix ``B``) that spans the same subspace of `R^m` as `S`. This uses an algorithm of Schwarz-Rutishauser. See pp. 9 of https://people.inf.ethz.ch/gander/papers/qrneu.pdf .. function:: void mpf_mat_qr(mpf_mat_t Q, mpf_mat_t R, const mpf_mat_t A) Computes the `QR` decomposition of a matrix ``A`` using the Gram-Schmidt process. (Sets ``Q`` and ``R`` such that `A = QR` where ``R`` is an upper triangular matrix and ``Q`` is an orthogonal matrix.) This uses an algorithm of Schwarz-Rutishauser. See pp. 9 of https://people.inf.ethz.ch/gander/papers/qrneu.pdf flint2-2.8.4/doc/source/mpf_vec.rst000066400000000000000000000076001414523752600171550ustar00rootroot00000000000000.. _mpf-vec: **mpf_vec.h** -- vectors of MPF floating-point numbers =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: mpf * _mpf_vec_init(slong len) Returns a vector of the given length of initialised ``mpf``'s with at least the given precision. .. function:: void _mpf_vec_clear(mpf * vec, slong len) Clears the given vector. Randomisation -------------------------------------------------------------------------------- .. function:: void _mpf_vec_randtest(mpf * f, flint_rand_t state, slong len, flint_bitcnt_t bits) Sets the entries of a vector of the given length to random numbers in the interval `[0, 1)` with ``bits`` significant bits in the mantissa or less if their precision is smaller. Assignment and basic manipulation -------------------------------------------------------------------------------- .. function:: void _mpf_vec_zero(mpf * vec, slong len) Zeros the vector ``(vec, len)``. .. function:: void _mpf_vec_set(mpf * vec1, const mpf * vec2, slong len2) Copies the vector ``vec2`` of the given length into ``vec1``. A check is made to ensure ``vec1`` and ``vec2`` are different. Comparison -------------------------------------------------------------------------------- .. function:: int _mpf_vec_equal(const mpf * vec1, const mpf * vec2, slong len) Compares two vectors of the given length and returns `1` if they are equal, otherwise returns `0`. .. function:: int _mpf_vec_is_zero(const mpf * vec, slong len) Returns `1` if ``(vec, len)`` is zero, and `0` otherwise. .. function:: int _mpf_vec_approx_equal(const mpf * vec1, const mpf * vec2, slong len, flint_bitcnt_t bits) Compares two vectors of the given length and returns `1` if the first ``bits`` bits of their entries are equal, otherwise returns `0`. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void _mpf_vec_add(mpf * res, const mpf * vec1, const mpf * vec2, slong len2) Adds the given vectors of the given length together and stores the result in ``res``. .. function:: void _mpf_vec_sub(mpf * res, const mpf * vec1, const mpf * vec2, slong len2) Sets ``(res, len2)`` to ``(vec1, len2)`` minus ``(vec2, len2)``. Scalar multiplication -------------------------------------------------------------------------------- .. function:: void _mpf_vec_scalar_mul_mpf(mpf * res, const mpf * vec, slong len, mpf_t c) Multiplies the vector with given length by the scalar `c` and sets ``res`` to the result. .. function:: void _mpf_vec_scalar_mul_2exp(mpf * res, const mpf * vec, slong len, flint_bitcnt_t exp) Multiplies the given vector of the given length by ``2^exp``. Dot product and norm -------------------------------------------------------------------------------- .. function:: void _mpf_vec_dot(mpf_t res, const mpf * vec1, const mpf * vec2, slong len2) Sets ``res`` to the dot product of ``(vec1, len2)`` with ``(vec2, len2)``. .. function:: void _mpf_vec_norm(mpf_t res, mpf * vec, slong len) Sets ``res`` to the square of the Euclidean norm of ``(vec, len)``. .. function:: int _mpf_vec_dot2(mpf_t res, const mpf * vec1, const mpf * vec2, slong len2, flint_bitcnt_t prec) Sets ``res`` to the dot product of ``(vec1, len2)`` with ``(vec2, len2)``. The temporary variable used has its precision set to be at least ``prec`` bits. Returns 0 if a probable cancellation is detected, and otherwise returns a non-zero value. .. function:: void _mpf_vec_norm2(mpf_t res, mpf * vec, slong len, flint_bitcnt_t prec) Sets ``res`` to the square of the Euclidean norm of ``(vec, len)``. The temporary variable used has its precision set to be at least ``prec`` bits. flint2-2.8.4/doc/source/mpfr_mat.rst000066400000000000000000000045141414523752600173440ustar00rootroot00000000000000.. _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. flint2-2.8.4/doc/source/mpfr_vec.rst000066400000000000000000000033641414523752600173420ustar00rootroot00000000000000.. _mpfr-vec: **mpfr_vec.h** -- vectors of MPFR floating-point numbers =============================================================================== Memory management -------------------------------------------------------------------------------- .. function:: flint_mpfr * _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(flint_mpfr * vec, slong len) Clears the given vector. Arithmetic -------------------------------------------------------------------------------- .. function:: void _mpfr_vec_zero(flint_mpfr * vec, slong len) Zeros the vector ``(vec, len)``. .. function:: void _mpfr_vec_set(flint_mpfr * vec1, const flint_mpfr * 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(flint_mpfr * res, const flint_mpfr * vec1, const flint_mpfr * 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(flint_mpfr * res, const flint_mpfr * 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(flint_mpfr * res, const flint_mpfr * 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, const flint_mpfr * vec1, const flint_mpfr * vec2, slong len) Sets ``res`` to the scalar product of ``(vec1, len)`` with ``(vec2, len)``. Assumes ``len > 0``. flint2-2.8.4/doc/source/mpn_extras.rst000066400000000000000000000232211414523752600177130ustar00rootroot00000000000000.. _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`. Multiplication -------------------------------------------------------------------------------- .. 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*x_1 - a_2*x_2`. Return the normalized length of `y` if `y \ge 0` and `y` fits into `n` limbs. Otherwise, return `-1`. `y` may alias `x1` but is not allowed to alias `x_2`. Divisibility -------------------------------------------------------------------------------- .. function:: int flint_mpn_divisible_1_p(x, xsize, 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 ``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 >= 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_ptr array1, mp_size_t limbs1, mp_ptr 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`` or ``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_ptr array1, mp_size_t limbs1, mp_ptr array2, mp_size_t limbs2) Sets ``(arrayg, retvalue)`` to the gcd of ``(array1, limbs1)`` and ``(array2, limbs2)``. The only assumption is that neither ``limbs1`` or ``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 ``n`` bits and stores it on ``rp``. flint2-2.8.4/doc/source/mpoly.rst000066400000000000000000000443011414523752600166750ustar00rootroot00000000000000.. _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*x^2*y+8*y*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 an 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 spaced 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(ordering_t ord) Return 1 if the given ordering is a degree ordering (deglex or degrevlex). .. function:: int mpoly_ordering_isrev(ordering_t ord) Return 1 if the given ordering 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 -------------------------------------------------------------------------------- .. 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 -------------------------------------------------------------------------------- .. 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, slong 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 and `-1` if it is less than, ``(exp3, N)``. Monomial divisibility -------------------------------------------------------------------------------- .. 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, slong 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, slong 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, return 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``, ``t1``, and ``t3`` of the size as ``a`` for workspace. The parameter ``e_ind`` is set to one of ``t1``, ``t1``, 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, slong 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, slong 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, slong 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, slong 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, slong 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, slong 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:: void mpoly_repack_monomials(ulong * exps1, slong bits1, const ulong * exps2, slong 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 unsure 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 extra, 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 extra, 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 * 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 * 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, ulong maskhi, ulong masklo) 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]``. flint2-2.8.4/doc/source/nmod_mat.rst000066400000000000000000000652141414523752600173410ustar00rootroot00000000000000.. _nmod-mat: **nmod_mat.h** -- matrices over integers mod n (word-size n) =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: nmod_mat_struct .. type:: nmod_mat_t Description. 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, 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, 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 -------------------------------------------------------------------------------- .. function:: MACRO nmod_mat_entry(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. 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(nmod_mat_t mat) Returns the number of rows in ``mat``. .. function:: slong nmod_mat_ncols(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(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(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] 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, mp_limb_t * diag, slong n, flint_rand_t state) 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, slong rank, flint_rand_t state) 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, slong count, flint_rand_t state) 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(nmod_mat_t mat1, 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. Transpose -------------------------------------------------------------------------------- .. function:: void nmod_mat_transpose(nmod_mat_t B, 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``. Addition and subtraction -------------------------------------------------------------------------------- .. function:: void nmod_mat_add(nmod_mat_t C, nmod_mat_t A, nmod_mat_t B) Computes `C = A + B`. Dimensions must be identical. .. function:: void nmod_mat_sub(nmod_mat_t C, nmod_mat_t A, nmod_mat_t B) Computes `C = A - B`. Dimensions must be identical. .. function:: void nmod_mat_neg(nmod_mat_t A, 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, 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, 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, nmod_mat_t A, 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, nmod_mat_t A, 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_limb_t * x, nmod_mat_t A, mp_limb_t * 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) 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 :func:`nmod_mat_lu_recursive`. .. function:: slong nmod_mat_lu_classical(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`. The behavior of this function is identical to that of :func:`nmod_mat_lu`. Uses Gaussian elimination. .. function:: 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`. The behavior of this function is identical to that of :func:`nmod_mat_lu`. Uses recursive block decomposition, switching to classical Gaussian elimination for sufficiently small blocks. 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. flint2-2.8.4/doc/source/nmod_mpoly.rst000066400000000000000000000772561414523752600177310ustar00rootroot00000000000000.. _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(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``, ect. .. 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(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 thows 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 thows 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, ulong const * 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, nmod_mpoly_ctx_t ctx) void nmod_mpoly_set_coeff_ui_ui(nmod_mpoly_t A, ulong c, ulong const * exp, 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_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, 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(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, ulong 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 a heap and multiple threads. This function should only be called once ``global_thread_pool`` has been initialized. 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 cofficients of *A* when viewed as a polynomial in the variables *vars*. Return `1` for success and `0` for failure. Upon succcess, *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 vise 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]``. flint2-2.8.4/doc/source/nmod_mpoly_factor.rst000066400000000000000000000061471414523752600212560ustar00rootroot00000000000000.. _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:: void 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 recommend 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. flint2-2.8.4/doc/source/nmod_poly.rst000066400000000000000000003676341414523752600175560ustar00rootroot00000000000000.. _nmod-poly: **nmod_poly.h** -- univariate polynomials over integers mod n (word-size n) =============================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: nmod_poly_struct .. type:: nmod_poly_t Description. 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``. 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 n) Notionally truncate ``poly`` to length `n` 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_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`. 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 throws 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, len)`` multiplied by~`c`, where~`c` is reduced modulo 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_mpz_binexp(mp_ptr res, mp_srcptr poly, mpz_srcptr 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_mpz_binexp(nmod_poly_t res, const nmod_poly_t poly, mpz_srcptr 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_mpz_binexp_preinv (mp_ptr res, mp_srcptr poly, mpz_srcptr 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_mpz_binexp_preinv(nmod_poly_t res, const nmod_poly_t poly, mpz_srcptr 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_ptr W, 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_div_basecase(mp_ptr Q, mp_ptr W, mp_srcptr A, slong A_len, mp_srcptr B, slong B_len, nmod_t mod) 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. We require that ``W`` is temporary space of ``NMOD_DIV_BC_ITCH(A_len, B_len, mod)`` coefficients. .. function:: void nmod_poly_div_basecase(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) 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 _nmod_poly_divrem_divconquer_recursive(mp_ptr Q, mp_ptr BQ, mp_ptr W, mp_ptr V, mp_srcptr A, 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 ``2 * lenB - 1`` and ``B`` is of length ``lenB``. Sets ``BQ`` to the low ``lenB - 1`` coefficients of ``B * Q``. We require that ``Q`` have space for ``lenB`` coefficients, that ``W`` be temporary space of size ``lenB - 1`` and ``V`` be temporary space for a number of coefficients computed by ``NMOD_DIVREM_DC_ITCH(lenB, mod)``. .. function:: void _nmod_poly_divrem_divconquer(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_divconquer(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_divrem_q0(mp_ptr Q, mp_ptr R, mp_srcptr A, mp_srcptr B, slong lenA, nmod_t mod) Computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`, where `\operatorname{len}(A) = \operatorname{len}(B) > 0`. Requires that `Q` and `R` have space for `1` and `\operatorname{len}(B) - 1` coefficients, respectively. Does not support aliasing or zero-padding. .. function:: void _nmod_poly_divrem_q1(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) < \operatorname{len}(B)`, where `\operatorname{len}(A) = \operatorname{len}(B) + 1 \geq \operatorname{len}(B) > 0`. Requires that `Q` and `R` have space for `\operatorname{len}(A) - \operatorname{len}(B) + 1` and `\operatorname{len}(B) - 1` coefficients, respectively. Does not support aliasing or zero-padding. .. 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_divconquer_recursive(mp_ptr Q, mp_ptr W, mp_ptr V, mp_srcptr A, 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 ``2 * lenB - 1`` and ``B`` is of length ``lenB``. We require that ``Q`` have space for ``lenB`` coefficients and that ``W`` be temporary space of size ``lenB - 1`` and ``V`` be temporary space for a number of coefficients computed by ``NMOD_DIV_DC_ITCH(lenB, mod)``. .. function:: void _nmod_poly_div_divconquer(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_divconquer(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) Notionally computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`, but returns only `Q`. .. 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_basecase(mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) void nmod_poly_rem_basecase(nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B) void _nmod_poly_rem_q1(mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) Notationally, computes `Q` and `R` such that `A = BQ + R` with `\operatorname{len}(R) < \operatorname{len}(B)`, where `\operatorname{len}(A) = \operatorname{len}(B) + 1 \geq \operatorname{len}(B) > 0`, but returns only the remainder. Requires that `R` has space for `\operatorname{len}(B) - 1` coefficients, respectively. Does not support aliasing or zero-padding. .. 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_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(mp_ptr Q, mp_srcptr A, slong Alen, mp_srcptr B, slong Blen, 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. The algorithm used is to reverse the polynomials and divide the resulting power series, then reverse the result. .. function:: void nmod_poly_div_newton(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) 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. 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 (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(mp_ptr Q, mp_ptr R, mp_srcptr A, slong Alen, mp_srcptr B, slong Blen, 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. The algorithm used is to call :func:`div_newton` and then multiply out and compute the remainder. .. function:: void nmod_poly_divrem_newton(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)`. The algorithm used is to call :func:`div_newton` and then multiply out and compute the remainder. .. 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. 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(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_ptr G, mp_ptr S, mp_srcptr A, slong lenA, mp_srcptr 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_ptr A, mp_srcptr B, slong lenB, mp_srcptr 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. Power series composition -------------------------------------------------------------------------------- .. 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_horner(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr 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 nmod_poly_compose_series_horner(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. This implementation uses the Horner scheme. .. function:: void _nmod_poly_compose_series_brent_kung(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr 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 nmod_poly_compose_series_brent_kung(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. This implementation uses Brent-Kung algorithm 2.1 [BrentKung1978]_. .. function:: void _nmod_poly_compose_series_divconquer(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong N, nmod_t mod) Composes ``poly1`` of length `\ell_1` with ``poly2`` of length `\ell_2` modulo `x^N` and sets ``res`` to the result, i.e.\ evaluates ``poly1`` at ``poly2``. Writes `\min\{(\ell_1 - 1)(\ell_2 - 2) + 1, N\}` coefficients to the vector ``res``. The algorithm used is the divide and conquer algorithm. It is assumed that `0 < \ell_1` and `0 < \ell_2 \leq N`. Does not support aliasing between the inputs and the output. .. function:: void nmod_poly_compose_series_divconquer(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong N) Composes ``poly1`` with ``poly2`` modulo `x^N` 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_series(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr 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 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. 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 _nmod_poly_revert_series_lagrange(mp_ptr Qinv, mp_srcptr Q, slong n, nmod_t mod) 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`. The arguments must both have length ``n`` and may not be aliased. 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. This implementation uses the Lagrange inversion formula. .. function:: void nmod_poly_revert_series_lagrange(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. This implementation uses the Lagrange inversion formula. .. function:: void _nmod_poly_revert_series_lagrange_fast(mp_ptr Qinv, mp_srcptr Q, slong n, nmod_t mod) 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`. The arguments must both have length ``n`` and may not be aliased. 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. This implementation uses a reduced-complexity implementation of the Lagrange inversion formula. .. function:: void nmod_poly_revert_series_lagrange_fast(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. This implementation uses a reduced-complexity implementation of the Lagrange inversion formula. .. function:: void _nmod_poly_revert_series_newton(mp_ptr Qinv, mp_srcptr Q, slong n, nmod_t mod) 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`. The arguments must both have length ``n`` and may not be aliased. 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. This implementation uses Newton iteration [BrentKung1978]_. .. function:: void nmod_poly_revert_series_newton(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. This implementation uses Newton iteration [BrentKung1978]_. .. function:: void _nmod_poly_revert_series(mp_ptr Qinv, mp_srcptr Q, slong n, nmod_t mod) 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`. The arguments must both have length ``n`` and may not be aliased. 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. This implementation automatically chooses between the Lagrange inversion formula and Newton iteration based on the size of the input. .. function:: 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. This implementation automatically chooses between the Lagrange inversion formula and Newton iteration based on the size of the input. 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 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 and that `h` is zero-padded as necessary to length `n`. 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 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 and that `h` is zero-padded as necessary to length `n`. 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_monomial_ui(mp_ptr g, mp_limb_t c, ulong r, slong n, nmod_t mod) Set `g = \log(1+cx^r) + O(x^n)`. Assumes `n > 0`, `r > 0`, and that the coefficient is reduced by the modulus. Works efficiently in linear time. .. function:: void nmod_poly_log_series_monomial_ui(nmod_poly_t g, mp_limb_t c, ulong r, slong n) Set `g = \log(1+cx^r) + O(x^n)`. Works efficiently in linear time. .. 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_monomial_ui(mp_ptr g, mp_limb_t c, ulong r, slong n, nmod_t mod) Set `g = \exp(cx^r) + O(x^n)`. Assumes `n > 0`, `r > 0`, and that the coefficient is reduced by the modulus. Works efficiently in linear time. .. function:: void nmod_poly_exp_series_monomial_ui(nmod_poly_t g, mp_limb_t c, ulong r, slong n) Set `g = \exp(cx^r) + O(x^n)`. Works efficiently in linear time. .. function:: void _nmod_poly_exp_series_basecase(mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) Set `g = \exp(h) + O(x^n)` using a simple `O(n^2)` algorithm. Assumes `n > 0` and `\operatorname{hlen} > 0`. Only the first `\operatorname{hlen}` coefficients of `h` will be read. Aliasing of `f` and `h` is allowed. .. function:: void nmod_poly_exp_series_basecase(nmod_poly_t g, const nmod_poly_t h, slong n) Set `g = \exp(h) + O(x^n)` using a simple `O(n^2)` algorithm. .. 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 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 n, nmod_t mod) Set `g = \operatorname{atan}(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. .. 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 n, nmod_t mod) Set `g = \operatorname{atanh}(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. .. 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 n, nmod_t mod) Set `g = \operatorname{asin}(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 modulus must be less than `n` and not equal to `2`. .. 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)`. The modulus must be less than `n` and not equal to `2`. .. function:: void _nmod_poly_asinh_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod) Set `g = \operatorname{asinh}(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 modulus must be less than `n` and not equal to `2`. .. 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)`. The modulus must be less than `n` and not equal to `2`. .. 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 modulus must be less than `n` and not equal to `2`. 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)`. The modulus must be less than `n` and not equal to `2`. .. 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 modulus must be less than `n` and not equal to `2`. 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)`. The modulus must be less than `n` and not equal to `2`. .. function:: void _nmod_poly_tan_series(mp_ptr g, mp_srcptr h, 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. The modulus must be less than `n`. 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)`. The modulus must be less than `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. The modulus must be less than `n` and not equal to `2`. 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)`. The modulus must be less than `n` and not equal to `2`. .. 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. The modulus must be less than `n` and not equal to `2`. 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)`. The modulus must be less than `n` and not equal to `2`. .. 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`. The modulus must be less than `n` and not equal to `2`. 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)`. The modulus must be less than `n` and not equal to `2`. 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``. flint2-2.8.4/doc/source/nmod_poly_factor.rst000066400000000000000000000205561414523752600211010ustar00rootroot00000000000000.. _nmod-poly-factor: **nmod_poly_factor.h** -- factorisation of univariate polynomials over integers mod n (word-size n) =================================================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: nmod_poly_factor_struct .. type:: nmod_poly_factor_t Description. 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 functions 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:: 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. .. 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``. flint2-2.8.4/doc/source/nmod_poly_mat.rst000066400000000000000000000405641414523752600204050ustar00rootroot00000000000000.. _nmod-poly-mat: **nmod_poly_mat.h** -- matrices of univariate polynomials over integers mod n (word-size n) =========================================================================================== Description. Types, macros and constants ------------------------------------------------------------------------------- .. type:: nmod_poly_mat_struct .. type:: nmod_poly_mat_t Description. 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. 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_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_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. 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``. 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. flint2-2.8.4/doc/source/nmod_vec.rst000066400000000000000000000234521414523752600173330ustar00rootroot00000000000000.. _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. 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_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_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_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:: 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. 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`. 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``. .. function:: 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. .. 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. 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. flint2-2.8.4/doc/source/padic.rst000066400000000000000000000530011414523752600166120ustar00rootroot00000000000000.. _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 MPIR integer ``op``. .. function:: void padic_set_mpq(padic_t rop, const mpq_t op, const padic_ctx_t ctx) Sets ``rop`` to the MPIR 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 MPIR 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 MPIR 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_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)"``. flint2-2.8.4/doc/source/padic_mat.rst000066400000000000000000000241611414523752600174600ustar00rootroot00000000000000.. _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 fmpz_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) 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. flint2-2.8.4/doc/source/padic_poly.rst000066400000000000000000000516251414523752600176670ustar00rootroot00000000000000.. _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(padic_poly_t poly) Returns the degree of the polynomial ``poly``. .. function:: slong padic_poly_length(padic_poly_t poly) Returns the length of the polynomial ``poly``. .. function:: slong padic_poly_val(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, const padic_ctx_t ctx) 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, const fmpz *op1, slong val1, slong len1, const fmpz *op2, slong val2, slong len2, 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, 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) 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(FILE *file, 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) flint2-2.8.4/doc/source/perm.rst000066400000000000000000000042101414523752600164730ustar00rootroot00000000000000.. _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_set_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. Input and output -------------------------------------------------------------------------------- .. function:: int _perm_print(const slong * vec, slong n) Prints the permutation vector of length `n` to ``stdout``. flint2-2.8.4/doc/source/portability.rst000066400000000000000000000027451414523752600201050ustar00rootroot00000000000000.. _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. flint2-2.8.4/doc/source/profiler.rst000066400000000000000000000114631414523752600173620ustar00rootroot00000000000000.. _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`` are ``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. flint2-2.8.4/doc/source/qadic.rst000066400000000000000000000507421414523752600166240ustar00rootroot00000000000000.. _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) Sets ``rop`` to ``op``. .. function:: void qadic_zero(qadic_t rop) Sets ``rop`` to zero. .. function:: void qadic_one(qadic_t rop, const qadic_ctx_t ctx) 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, const qadic_ctx_t ctx) 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 reduces 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`. 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) 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 padic_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\"uller 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\"uller 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. flint2-2.8.4/doc/source/qsieve.rst000066400000000000000000000150301414523752600170260ustar00rootroot00000000000000.. _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) 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(qs_t qs_inf) Given `A` and `B`, calculate `C = (B ^2 - A) / N`. .. function:: void qsieve_do_sieving(qs_t qs_inf, unsigned char * sieve) 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) 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, slong i, unsigned char * sieve) 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) 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, fmpz_t Y) Write a relation to the file. Format is as follows, first write large prime, in case of full relation it is 1, then write exponent of small primes, then write number of factor followed by offset of factor in factor base and their exponent and at last value of `Q(x)` for particular relation. each relation is written in new line. .. 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:: void 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. flint2-2.8.4/doc/source/references.rst000066400000000000000000000135251414523752600176620ustar00rootroot00000000000000References ------------ .. [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) .. [ArnoldMonagan2011] Arnold, Andrew and Monagan, Michael : Calculating cyclotomic polynomials, Mathematics of Computation 80:276 (2011) 2359--2379 .. [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 .. [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 .. [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 .. [Chen2003] Zhuo Chen and John Greene : Some Comments on {Baillie--PSW} Pseudoprimes, The Fibonacci Quaterly 41:4 (2003) 334--344 .. [Coh1996] Cohen, Henri : A course in computational algebraic number theory, Springer, 1996 .. [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. .. [DelegliseNicolasZimmermann2009] Deleglise, Marc and Niclas, Jean-Louis and Zimmermann, Paul : Landau's function for one million billions, J. Th\'eor. 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 .. [Dus1999] P. Dusart, "The kth prime is greater than k(ln k+ln ln k-1) for k> 2," Math. Comp., 68:225 (January 1999) 411--415. .. [FieHof2014] Fieker C. and Hofmann T.: "Computing in quotients of rings of integers" LMS Journal of Computation and Mathematics, 17(A), 349-365 .. [GraMol2010] Torbjorn Granlund and Niels Moller : Improved Division by Invariant Integers https://gmplib.org/~tege/division-paper.pdf .. [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 .. [HanZim2004] Guillaume Hanrot and Paul Zimmermann : Newton Iteration Revisited (2004) https://www.loria.fr/~zimmerma/papers/fastnewton.ps.gz .. [Har2012] Hart, William B.. (2012) A one line factoring algorithm. Journal of the Australian Mathematical Society, Volume 92 (Number 1). pp. 61-69. .. [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 .. [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 .. [Kahan1991] Kahan, William: Computing a Real Cube Root. https://csclub.uwaterloo.ca/~pbarfuss/qbrt.pdf .. [LukPatWil1996] R. F. Lukes and C. D. Patterson and H. C. Williams "Some results on pseudosquares" Math. Comp. 1996, no. 65, 361--372 .. [MasRob1996] J. Massias and G. Robin, "Bornes effectives pour certaines fonctions concernant les nombres premiers," J. Theorie Nombres Bordeaux, 8 (1996) 215-242. .. [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 .. [Mul2000] Thom Mulders : On Short Multiplications and Divisions, AAECC vol. 11 (2000) 69--88 .. [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 .. [Rademacher1937] Rademacher, Hans : On the partition function `p(n)` Proc. London Math. Soc vol. 43 (1937) 241--254 .. [RosSch1962] Rosser, J. Barkley; Schoenfeld, Lowell: Approximate formulas for some functions of prime numbers. Illinois J. Math. 6 (1962), no. 1, 64--94. .. [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 .. [Stehle2010] Stehl\'e, Damien : Floating-Point LLL: Theoretical and Practical Aspects, in Nguyen, Phong Q. and Vall\'ee, 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 .. [ThullYap1990] Thull, K. and Yap, C. : A Unified Approach to {HGCD} Algorithms for Polynomials and Integers, (1990) .. [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 .. [Whiteman1956] Whiteman, A. L. : A sum connected with the series for the partition function, Pacific Journal of Mathematics 6:1 (1956) 159--176 flint2-2.8.4/doc/source/thread_pool.rst000066400000000000000000000041731414523752600200400ustar00rootroot00000000000000.. _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. flint2-2.8.4/doc/source/threading.rst000066400000000000000000000021361414523752600175020ustar00rootroot00000000000000.. _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. Please refer to `code_conventions.txt` for some preliminary guidance on how to write threaded functions in FLINT. flint2-2.8.4/doc/source/ulong_extras.rst000066400000000000000000001730011414523752600202470ustar00rootroot00000000000000.. _ulong-extras: **ulong_extras.h** -- arithmetic and number-theoretic functions for single-word integers ======================================================================================== 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(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\"oller [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\"oller [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\"oller [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\"oller [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\"oller [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 use is that of Granlund and M\"oller [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`. The algorithm is a slight embellishment of the Euclidean algorithm which uses some branches to avoid most divisions. One wishes to compute the quotient and remainder of `u_3 / v_3` without division where possible. This is accomplished when `u_3 < 4 v_3`, i.e. the quotient is either `1`, `2` or `3`. We first compute `s = u_3 - v_3`. If `s < v_3`, i.e.\ `u_3 < 2 v_3`, we know the quotient is `1`, else if `s < 2 v_3`, i.e.\ `u_3 < 3 v_3` we know the quotient is `2`. In the remaining cases, the quotient must be `3`. When the quotient is `4` or above, we use division. However this happens rarely for generic inputs. .. function:: ulong n_gcd_full(ulong x, ulong y) Returns the greatest common divisor `g` of `x` and `y`. No assumptions are made about `x` and `y`. This function is deprecated. .. 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 * 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 return ``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 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` (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 set 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 sqare 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*x*x - a)*x/(2*x*x*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, http://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:: 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 that 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 that 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. N.B: 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 an 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. flint2-2.8.4/double_extras.h000066400000000000000000000027101414523752600157450ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define DOUBLE_EXTRAS_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include #include "flint.h" #define ulong mp_limb_t #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) FLINT_DLL double d_randtest(flint_rand_t state); FLINT_DLL double d_randtest_signed(flint_rand_t state, slong minexp, slong maxexp); FLINT_DLL 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; } FLINT_DLL double d_lambertw(double x); FLINT_DLL int d_is_nan(double x); FLINT_DLL double d_log2(double x); #ifdef __cplusplus } #endif #endif flint2-2.8.4/double_extras/000077500000000000000000000000001414523752600155745ustar00rootroot00000000000000flint2-2.8.4/double_extras/inlines.c000066400000000000000000000010721414523752600174010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define DOUBLE_EXTRAS_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "double_extras.h" flint2-2.8.4/double_extras/is_nan.c000066400000000000000000000010311414523752600172020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "double_extras.h" int d_is_nan(double x) { if (x != x) return 1; else return 0; } flint2-2.8.4/double_extras/lambertw.c000066400000000000000000000113501414523752600175550ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/double_extras/log2.c000066400000000000000000000010461414523752600166040ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/double_extras/randtest.c000066400000000000000000000017651414523752600175750ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/double_extras/randtest_signed.c000066400000000000000000000015021414523752600211130ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/double_extras/randtest_special.c000066400000000000000000000020661414523752600212700ustar00rootroot00000000000000/* 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 2.1 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; } } } flint2-2.8.4/double_extras/test/000077500000000000000000000000001414523752600165535ustar00rootroot00000000000000flint2-2.8.4/double_extras/test/t-is_nan.c000066400000000000000000000026211414523752600204300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "ulong_extras.h" #include "double_extras.h" int main(void) { double x; slong iter; FLINT_TEST_INIT(state); flint_printf("is_nan...."); fflush(stdout); /* check non-zero value returned if x == NaN */ x = D_NAN; if (!d_is_nan(x)) { flint_printf("FAIL\n"); flint_printf("0 returned for %g\n", x); abort(); } /* check 0 returned if x != NaN */ x = D_INF; if (d_is_nan(x)) { flint_printf("FAIL\n"); flint_printf("Non-zero returned for %g\n", x); abort(); } for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++) { x = d_randtest_signed(state, 0, 0); if (d_is_nan(x)) { flint_printf("FAIL\n"); flint_printf("Non-zero returned for %g\n", x); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/double_extras/test/t-lambertw.c000066400000000000000000000073331414523752600210030ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "ulong_extras.h" #include "double_extras.h" #define ONE_OVER_E ldexp(6627126856707895.0, -54) int main() { double x, w, tol; slong iter, prec = 70; mpfr_t xx, ww, wnew, t, u, v, p, q, max_err; FLINT_TEST_INIT(state); flint_printf("lambertw...."); fflush(stdout); 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) { flint_printf("FAIL\n"); flint_printf("x = %.17g, w = %.17g, error = %g\n", x, w, mpfr_get_d(t, MPFR_RNDA)); abort(); } #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(); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/double_extras/test/t-log2.c000066400000000000000000000023151414523752600200240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "ulong_extras.h" #include "double_extras.h" int main(void) { double x, res1, res2; slong iter; FLINT_TEST_INIT(state); flint_printf("log2...."); fflush(stdout); /* 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) { flint_printf("FAIL\n"); flint_printf("x = %.20g\n", x); flint_printf("res1 = %.20g\n", res1); flint_printf("res2 = %.20g\n", res2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/double_extras/test/t-randtest.c000066400000000000000000000020431414523752600210030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "ulong_extras.h" #include "double_extras.h" int main(void) { double x; slong iter; FLINT_TEST_INIT(state); flint_printf("randtest...."); fflush(stdout); /* 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) { flint_printf("FAIL\n"); flint_printf("x = %.17g\n", x); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/double_extras/test/t-randtest_signed.c000066400000000000000000000021551414523752600223400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "ulong_extras.h" #include "double_extras.h" int main(void) { double x; slong iter; FLINT_TEST_INIT(state); flint_printf("randtest_signed...."); fflush(stdout); /* 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) { flint_printf("FAIL\n"); flint_printf("x = %.17g\n", x); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/examples/000077500000000000000000000000001414523752600145525ustar00rootroot00000000000000flint2-2.8.4/examples/crt.c000066400000000000000000000026701414523752600155130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 i, 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; for (i = 0; fmpz_bits(prod) < bit_bound; i++) { 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 EXIT_SUCCESS; } flint2-2.8.4/examples/crt.cpp000066400000000000000000000024051414523752600160470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Tom Bachmann (C++ adaptation) This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 "fmpzxx.h" #include "ulong_extras.h" using namespace flint; int main(int argc, char* argv[]) { if (argc != 2) { flint_printf("Syntax: crt \n"); return EXIT_FAILURE; } fmpzxx x(argv[1]); slong bit_bound = bits(x) + 2; fmpzxx y(0); fmpzxx prod(1); mp_limb_t prime = 0; for (unsigned i = 0; bits(prod) < bit_bound; i++) { prime = n_nextprime(prime, 0); ulong res = (x % prime).to(); y = y.CRT(prod, res, prime, true); std::cout << "residue mod " << prime << " = " << res; std::cout << "; reconstruction = " << y << '\n'; prod *= prime; } return 0; } flint2-2.8.4/examples/delta_qexp.c000066400000000000000000000023001414523752600170370ustar00rootroot00000000000000/* 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 2.1 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 EXIT_SUCCESS; } flint2-2.8.4/examples/delta_qexp.cpp000066400000000000000000000021421414523752600174030ustar00rootroot00000000000000/* Copyright (C) 2007 David Harvey, William Hart Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2013 Tom Bachmann (C++ adaptation) This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 "fmpzxx.h" #include "arithxx.h" using namespace flint; using namespace std; int main(int argc, char* argv[]) { 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 1; } std::cout << "Coefficient of q^" << N << " is " << ramanujan_tau(fmpzxx(N)) << '\n'; return 0; } flint2-2.8.4/examples/fmpq_poly.c000066400000000000000000000021221414523752600167210ustar00rootroot00000000000000/* 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 2.1 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 EXIT_SUCCESS; } flint2-2.8.4/examples/fmpq_poly.cpp000066400000000000000000000014761414523752600172740ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Tom Bachmann (C++ adaptation) This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ /* Simple example demonstrating the use of the fmpq_polyxx module. */ #include "fmpq_polyxx.h" #include using namespace flint; int main(int argc, char* argv[]) { fmpq_polyxx f("2 1/2 3/5"); fmpq_polyxx g("4 1/3 2 3/2 -1/2"); std::cout << '(' << f.pretty("t") << ") * (" << g.pretty("t") << " = " << (f*g).pretty("t") << '\n'; return 0; } flint2-2.8.4/examples/fmpz_mod_poly.c000066400000000000000000000021711414523752600175750ustar00rootroot00000000000000/* 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 2.1 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_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 EXIT_SUCCESS; } flint2-2.8.4/examples/fmpz_mod_poly.cpp000066400000000000000000000014441414523752600201370ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Tom Bachmann (C++ adaptation) This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ /* Example program for the fmpz_mod_poly module. */ #include #include using namespace std; using namespace flint; int main(int argc, char* argv[]) { fmpzxx n(7); fmpz_mod_polyxx x(n); x.set_coeff(3, 5); x.set_coeff(0, 6); print(x);flint_printf("\n"); print(x.sqr());flint_printf("\n"); return 0; } flint2-2.8.4/examples/fmpz_poly_factor_zassenhaus.c000066400000000000000000000030111414523752600225320ustar00rootroot00000000000000/* 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 2.1 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 "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 EXIT_SUCCESS; } flint2-2.8.4/examples/fmpz_poly_factor_zassenhaus.cpp000066400000000000000000000024701414523752600231020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ /* Example program demonstrating the Zassenhaus factoring algorithm. */ #include #include "fmpz_polyxx.h" using namespace flint; using namespace std; int main() { fmpz_polyxx f; if (0) { // NB: this does not seem to work in the C version FILE *polyfile; polyfile = fopen("examples/fmpz_poly_hensel_P1", "r"); if (!polyfile) { flint_printf("Error. Could not read P1 from file.\n"); abort(); } read(polyfile, f); } else 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"; flint_printf("Polynomial:\n");print(f); flint_printf("\nFactorisation:\n");print(factor_zassenhaus(f)); return 0; } flint2-2.8.4/examples/fmpz_poly_hensel_P1000066400000000000000000000144241414523752600204170ustar00rootroot00000000000000157 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 flint2-2.8.4/examples/fmpz_poly_q.c000066400000000000000000000022601414523752600172550ustar00rootroot00000000000000/* 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 2.1 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 EXIT_SUCCESS; } flint2-2.8.4/examples/fmpz_poly_q.cpp000066400000000000000000000014701414523752600176170ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Tom Bachmann (C++ adaptation) This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ /* Simple example demonstrating the use of the fmpz_poly_q module. */ #include #include "fmpz_poly_qxx.h" using namespace flint; using namespace std; int main(int argc, char* argv[]) { fmpz_poly_qxx f("2 1 3/1 2"), g("1 3/2 2 7"); std::cout << f.pretty("t") << " * " << g.pretty("t") << " = " << (f*g).pretty("t") << '\n'; return 0; } flint2-2.8.4/examples/fooxx.cpp000066400000000000000000000316431414523752600164300ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ /* Demo FLINTXX header to illustrate flintxx extension. */ /////////////////////////////////////////////////////////////////////////////// // FAKE C DATA TYPE // (This would normally reside in foo.h.) /////////////////////////////////////////////////////////////////////////////// #ifndef FOO_H #define FOO_H #include extern "C" { // usually only #ifdef __cplusplus etc typedef slong foo; typedef slong foo_t[1]; static __inline__ void foo_init(foo_t f) { *f = 0l; } static __inline__ void foo_clear(foo_t f) { } static __inline__ void foo_set(foo_t to, const foo_t from) { *to = *from; } static __inline__ void foo_set_si(foo_t f, slong e) { *f = e; } static __inline__ void foo_add(foo_t to, const foo_t e1, const foo_t e2) { *to = *e1 + *e2; } static __inline__ void foo_add_si(foo_t to, const foo_t e1, slong e2) { *to = *e1 + e2; } static __inline__ int foo_cmp(const foo_t e1, const foo_t e2) { if(*e1 == *e2) return 0; return *e1 > *e2 ? 1 : -1; } static __inline__ int foo_is_zero(const foo_t f) { return *f == 0; } static __inline__ void foo_magic(foo_t to, const foo_t from) { *to = 2 * (*from) + 1; } } #endif /////////////////////////////////////////////////////////////////////////////// // C++ wrapper // (This would normally reside in fooxx.h.) /////////////////////////////////////////////////////////////////////////////// #ifndef FOOXX_H #define FOOXX_H #include #include "flintxx/expression.h" #include "flintxx/flint_classes.h" namespace flint { // fooxx_expression is an "all-purpose" expression template class. In // principle, both Operation and Data can be arbitrary types (Data has to be // copy constructible), but in this generality the objects will be not much // use. In practice, Operation is an empty type, which is just used as a "tag", // and Data is a rather primitive type holding essentially just some payload. // Even more practically speaking, the only instantiations the FLINT developer // should have have to make explicitly are when Operation is // operations::immediate. // The flintxx library will create other instantiations automatically, with // more complicated Data arguments, and different Operation-s. template class fooxx_expression // In order for the flintxx library to do its work, your class must derive from // flint::expression. If your class has just two template parameters Operation // and Data, then the following line is sufficient. : public expression, Operation, Data> { public: // This line is formulaic, and just makes the base class available. // The typedef is used by the FLINTXX_DEFINE_* macros below, and is // necessary because of namespace injection bugs in gcc<4.5. typedef expression, Operation, Data> base_t; // The next two lines are formulaic, and most likely required in any // concrete class. FLINTXX_DEFINE_BASICS(fooxx_expression) FLINTXX_DEFINE_CTORS(fooxx_expression) // This line enables reference types for your class. The second argument is // the underlying C type (note this is foo, not foo_t). The third argument // is the name under which to make the underlying C type available. // All of fooxx, fooxx_ref and fooxx_srcref will have methods _foo() which // can be used to manipulate the underlying C data type. FLINTXX_DEFINE_C_REF(fooxx_expression, foo, _foo) // Now custom methods can be added. The typical pattern is to call a C // function with argument this->evaluate()._foo(). The evaluate() method is // inherited from the expression class (this is why it needs to be // qualified by "this"). It obtains a reference to self if self is an // immediate object, and otherwise evaluates self into a temporary // immediate object. // If you leave out the evaluate() step, then the method will only work // on immediates (which may be desirable). bool is_zero() const {return foo_is_zero(this->evaluate()._foo());} }; // This is formulaic. The class fooxx will be an instantiation of // fooxx_expression, with Operation operations::immediate and Data // detail::foo_data. We need to forward-declare this because of cyclic // dependencies among the immediate types (e.g. fooxx_srcref can be // constructed from fooxx, and vice versa). namespace detail { struct foo_data; } // This line just carries out the plan of definition of fooxx explained above. typedef fooxx_expression fooxx; // If you want reference types (i.e. if you had FLINTXX_DEFINE_C_REF above), // these lines are again formulaic. typedef fooxx_expression > fooxx_ref; typedef fooxx_expression > fooxx_srcref; namespace detail { // We now define the actual immediate Data type. This is not just foo_t (the // underlying C data type), because want it to behave nicely "in a C++ world". struct foo_data { // In general, your data type can contain members and member types in any // way you want. However, to work with the automatic reference type system, // the following three lines are necessary. foo_t inner; typedef foo_t& data_ref_t; typedef const foo_t& data_srcref_t; // Default constructor. If this is not provided, fooxx will not be default // constructible (this is OK but requires some additional care, see e.g. // padicxx). foo_data() {foo_init(inner);} // Destructor. You most likely want this. ~foo_data() {foo_clear(inner);} // Copy constructor. You must provide this. foo_data(const foo_data& o) { foo_init(inner); foo_set(inner, o.inner); } // Instantiation from srcref. This is basically the same as the copy, // constructor, but unfortunately has to be repeated. This also takes care // of instantiation from ref, since ref->srcref is an implicit conversion // path. foo_data(fooxx_srcref r) { foo_init(inner); foo_set(inner, r._foo()); } // Now you can add more constructors, or in fact any methods you like. // This one allows constructing fooxx directly from long, int, // unsigned short etc. template foo_data(T t, typename mp::enable_if >::type* = 0) { foo_init(inner); foo_set_si(inner, t); } }; } // detail // By now our data type is instantiable, but nothing can be done with it. // The flintxx library would be able to create expression templates involving // fooxx, but will not do so because it has no way of evaluating them. We // need to provides evaluation (and other) *rules* to the library. These // (have to) live in namespace flint::rules. // // All possible rules are defined in flintxx/rules.h. namespace rules { // These two lines are convenient, are not formulaic except that they are used // in all code below. #define FOOXX_COND_S FLINTXX_COND_S(fooxx) #define FOOXX_COND_T FLINTXX_COND_T(fooxx) // Define a conditional assignment rule. The general pattern is // // FLINT_DEFINE_DOIT_COND2(name, cond1, cond2, eval). // // This will define a "doit" rule for "name", which takes one input and // one output argument. The result looks something like // // template // struct assignment and cond2 are satisfied> // { // static void doit(T& to, const U& from) // eval; // }; // // In our case, we are defining an assignment rule, i.e. an explanation on // how to execute operator=. If the right hand side is an expression template, // flintxx will automatically evaluate it first. Thus we need only treat the // case where the LHS is fmpzxx or fmpzxx_ref, and the RHS is fmpzxx, fmpzxx_ref // or fmpzxx_srcref. This is precisely what the conditions FOOXX_COND_T // and FOOXX_COND_S (conditions "fooxx target" and "fooxx source") mean. FLINT_DEFINE_DOIT_COND2(assignment, FOOXX_COND_T, FOOXX_COND_S, foo_set(to._foo(), from._foo())) // This line defines assignment of integral PODs to fooxx. Since the underlying // C library only defines fooxx_set_si, we can only safely allow this if the // right hand side can always be losslessly converted into a signed long, // so we use the condition traits::fits_into_slong. Traits are defined all // throughout flintxx, but the most general purpose ones (like fits_into_slong, // is_unsigned_integer etc) can be found in flintxx/traits.h FLINT_DEFINE_DOIT_COND2(assignment, FOOXX_COND_T, traits::fits_into_slong, foo_set_si(to._foo(), from, 1)) // We now define evaluation rules. In full generality, the rule evaluation<...> // can be used to define how to evaluate any kind of expression. But this is // difficult to use. Moreover, much evaluation logic is shared among most // data types. For example, to evaluate an expression like a + b + c, // one typically first has to evaluate (say) a + b into a temporary t, and then // evaluate t + c. The only step that is specific to fooxx here is how to // add two immediates. // For this reason, flintxx has special convenience forms of the evaluation // rule, called binary and unary expressions. Defining a binary expression // f(x, y) tells flintxx how to evaluate operation "f" on types "x" and "y", // typically immediates. Then flintxx will figure out how to evaluate the // arguments into temporaries first etc. // There is a common special case, when f(x, y) is always the same as f(y, x), // even though x and y may be of different types. Letting flintxx know of this // avoids defining the rule both ways round. // // Here we define a commutative binary expression rule, for operation "plus", // to be executed on to objects of types T and U, both satisfying FOOXX_COND_S. // The result is to be of type foooxx (the second argument). // In this case the types are fully symmetric, so we could have used // FLINT_DEFINE_BINARY_EXPR_COND2 without adverse effects. // // The eval statement should have the effect of to = e1 + e2. FLINT_DEFINE_CBINARY_EXPR_COND2(plus, fooxx, FOOXX_COND_S, FOOXX_COND_S, foo_add(to._foo(), e1._foo(), e2._foo())) // Addation of fooxx and PODs. This time CBINARY instead of BINARY is vital. FLINT_DEFINE_CBINARY_EXPR_COND2(plus, fooxx, FOOXX_COND_S, traits::fits_into_slong, foo_add_si(to._foo(), e1._foo(), e2)) // Next we define relational operators. A convenient way of doing so is using // a "cmp" function, which is handily provided by the underlying C library. // This has a somewhat peculiar signature, so cannot be defined using one of // the standard macros. However, it comes up with many actual FLINT data types, // so we have a special FLINTXX macro just for defining cmp. FLINTXX_DEFINE_CMP(fooxx, foo_cmp(e1._foo(), e2._foo())) // Now we define a rule how to print fooxx. There is no macro for this, because // normally instead we define conversion to string, and flintxx takes care of // printing. However, the C library for fooxx provides neither printing nor // conversion to string, so we have to do our own implementation. template struct print >::type> { static void doit(const T& i, std::ostream& o) { o << *i._foo(); } }; } // rules // By now fooxx is a pretty passable wrapper type. In fact the only thing left // to do is to expose foo_magic. This is a special function which can be // executed on instances of foo, and yields another instance of foo. It is // essentially just another unary expression, just with an unusual name, so // this is how we treat it. // This line introduces a new type of unary operation, called "magic_op", // together with a function flint::magic(T), which creates expression templates // with this new operation. In principle, any expression template data type is // now allowed to define rules how to performa magic on itself. FLINT_DEFINE_UNOP(magic) // Finally, we need to explain how to perform magic on flintxx. This is again // a rule. namespace rules { // The pattern should be familiar by now. FLINT_DEFINE_UNARY_EXPR_COND(magic_op, fooxx, FOOXX_COND_S, foo_magic(to._foo(), from._foo())) } // rules } // flint #endif /////////////////////////////////////////////////////////////////////////////// // Example program /////////////////////////////////////////////////////////////////////////////// using namespace flint; int main() { fooxx a, b(4); fooxx_ref ar(a); fooxx_srcref br(b); ar = 1 + br + 1; // a=6 std::cout << magic(a + (-1)) << '\n'; // 2*(6-1)+1 = 11 return 0; } flint2-2.8.4/examples/fq_poly.c000066400000000000000000000073621414523752600163770ustar00rootroot00000000000000/* 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 2.1 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 "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); fq_poly_init(f, ctx); fq_poly_init(g, ctx); fq_poly_init(h, ctx); 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_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_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_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_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_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_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 EXIT_SUCCESS; } flint2-2.8.4/examples/multi_crt.c000066400000000000000000000040141414523752600167170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 EXIT_SUCCESS; } flint2-2.8.4/examples/multi_crt.cpp000066400000000000000000000027301414523752600172620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Tom Bachmann (C++ adaptation) This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 "fmpzxx.h" #include "ulong_extras.h" using namespace flint; int main(int argc, char* argv[]) { if (argc != 3) { std::cerr << "Syntax: crt \n"; return 1; } slong num_primes = atoi(argv[2]); if (num_primes < 1) { std::cerr << "Requires num_primes >= 1\n"; return 2; } fmpzxx x(argv[1]); std::vector primes(num_primes), residues(num_primes); primes[0] = 2; for (unsigned i = 1; i < num_primes; i++) primes[i] = n_nextprime(primes[i-1], 0); fmpz_combxx comb(primes); multi_mod(residues, x, comb); for (unsigned i = 0; i < num_primes; i++) std::cout << "residue mod " << primes[i] << " = " << residues[i] << '\n'; std::cout << "reconstruction = " << multi_CRT(residues, comb, true) << '\n'; return 0; } flint2-2.8.4/examples/padic.c000066400000000000000000000071661414523752600160100ustar00rootroot00000000000000/* 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 2.1 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 EXIT_SUCCESS; } flint2-2.8.4/examples/padic.cpp000066400000000000000000000057311414523752600163440ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Tom Bachmann (C++ adaptation) This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ /* Demo FLINT program to demonstrate some use of the padic module. */ #include #include "padicxx.h" using namespace flint; using namespace std; int main() { std::cout << "Output:\n\n"; // Case 1 { std::cout << "Positive integer: x = 127 mod 7^10\n"; fmpzxx p(7); padicxx_ctx ctx(p, 8, 12, PADIC_TERSE); padicxx x = padicxx::from_QQ(127, ctx, 10); ctx.mode() = PADIC_TERSE; std::cout << "print: ";print(x);std::cout << '\n'; std::cout << "get_str: " << x.to_string() << '\n'; ctx.mode() = PADIC_SERIES; std::cout << "print: ";print(x);std::cout << '\n'; std::cout << "get_str: " << x.to_string() << '\n'; ctx.mode() = PADIC_VAL_UNIT; std::cout << "print: ";print(x);std::cout << '\n'; std::cout << "get_str: " << x.to_string() << '\n'; } // Case 2 { std::cout << "Positive integer larger than p^N: x = 1057 mod 2^10\n"; fmpzxx p(2); padicxx_ctx ctx(p, 10, 12, PADIC_TERSE); padicxx x = padicxx::from_QQ(1057, ctx, 10); ctx.mode() = PADIC_TERSE; std::cout << "print: ";print(x);std::cout << '\n'; std::cout << "get_str: " << x.to_string() << '\n'; ctx.mode() = PADIC_SERIES; std::cout << "print: ";print(x);std::cout << '\n'; std::cout << "get_str: " << x.to_string() << '\n'; ctx.mode() = PADIC_VAL_UNIT; std::cout << "print: ";print(x);std::cout << '\n'; std::cout << "get_str: " << x.to_string() << '\n'; } // Case 3 { std::cout << "Negative integer: x = -127 mod 3^10\n"; fmpzxx p(3); padicxx_ctx ctx(p, 10, 12, PADIC_TERSE); padicxx x = padicxx::from_QQ(-127, ctx, 10); ctx.mode() = PADIC_TERSE; std::cout << "print: ";print(x);std::cout << '\n'; std::cout << "get_str: " << x.to_string() << '\n'; ctx.mode() = PADIC_SERIES; std::cout << "print: ";print(x);std::cout << '\n'; std::cout << "get_str: " << x.to_string() << '\n'; ctx.mode() = PADIC_VAL_UNIT; std::cout << "print: ";print(x);std::cout << '\n'; std::cout << "get_str: " << x.to_string() << '\n'; } // Log { std::cout << "Log of 7380996 mod 5^20\n"; fmpzxx p(5); padicxx_ctx ctx(p, 10, 25, PADIC_SERIES); padicxx x = padicxx::from_QQ(7380996, ctx); padicxx y(log(x)); std::cout << "x = " << x << '\n'; std::cout << "y = " << y << '\n'; } return 0; } flint2-2.8.4/examples/partitions.c000066400000000000000000000016351414523752600171170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ /* FLINT program for demonstrating the Integer Partition function. */ #include #include #include "flint.h" #include "fmpz.h" #include "arith.h" int main(int argc, char * argv[]) { fmpz_t x; ulong n; if (argc != 2) { flint_printf("usage: partitions n\n"); return 1; } flint_sscanf(argv[1], "%wu", &n); flint_printf("p(%wu) = \n", n); fmpz_init(x); arith_number_of_partitions(x, n); fmpz_print(x); flint_printf("\n"); fmpz_clear(x); return 0; } flint2-2.8.4/examples/partitions.cpp000066400000000000000000000015351414523752600174560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ /* FLINT program for demonstrating the Integer Partition function. */ #include #include #include "arithxx.h" #include "fmpzxx.h" using namespace flint; using namespace std; int main(int argc, char * argv[]) { if (argc != 2) { std::cerr << "usage: partitions n\n"; return 1; } ulong n; flint_sscanf(argv[1], "%wu", &n); std::cout << "p(" << n << ") =\n" << number_of_partitions(n) << '\n'; return 0; } flint2-2.8.4/examples/primegen.c000066400000000000000000000025331414523752600165270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 EXIT_SUCCESS; } flint2-2.8.4/examples/qadic.c000066400000000000000000000076341414523752600160110ustar00rootroot00000000000000/* 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 2.1 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 EXIT_SUCCESS; } flint2-2.8.4/examples/radix.c000066400000000000000000000064651414523752600160400ustar00rootroot00000000000000/* 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 2.1 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_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 EXIT_SUCCESS; } flint2-2.8.4/examples/radix.cpp000066400000000000000000000037301414523752600163700ustar00rootroot00000000000000/* Copyright (C) 2012 Sebastian Pancratz Copyright (C) 2013 Tom Bachmann (C++ adaptation) This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 "fmpz_mod_polyxx.h" using namespace std; using namespace flint; int main(void) { const slong n = 12376; const slong N = n / 26; frandxx state; fmpzxx m(17); m = m.pow(26u); fmpz_mod_polyxx A(m), B(m); A.set_coeff(3, 5); A.set_coeff(4, 4); B.set_coeff(0, 1); B.set_coeff(2, 1); B.set_coeff(3, 5); B.set_coeff(4, 1); B.set_coeff(5, 5); B.set_coeff(8, 8); B.set_coeff(9, 8); B.set_coeff(10, 5); B.set_coeff(12, 6); B.set_coeff(13, 1); fmpz_mod_polyxx r(A.pow(3u) * fmpzxx(4) + B.pow(2u) * fmpzxx(27)); fmpz_mod_poly_vecxx b(N + 1, m); fmpz_mod_polyxx t = fmpz_mod_polyxx::randtest(m, state, n + 1); flint_printf("Radix conversion\n"); flint_printf("----------------\n"); flint_printf(" Degree of the radix: %wd\n", r.degree()); flint_printf(" Bit size of the modulus: %wd\n", (slong) bits(r.modulus())); flint_printf(" Degree of the input: %wd\n", t.degree()); clock_t c0 = clock(); fmpz_mod_poly_radixxx S(r, n + 1); clock_t c1 = clock(); double c = (double) (c1 - c0) / CLOCKS_PER_SEC; flint_printf(" Precomputation: %fs\n", c); c0 = clock(); b = t.radix(S); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; flint_printf(" Conversion: %fs\n", c); return 0; } flint2-2.8.4/examples/stirling_matrix.c000066400000000000000000000026151414523752600201410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 EXIT_SUCCESS; } flint2-2.8.4/examples/stirling_matrix.cpp000066400000000000000000000023111414523752600204720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2013 Tom Bachmann (C++ adaptation) This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ /* Demo FLINT program for generating Stirling number matrices and inverting them. */ #include #include "fmpz_matxx.h" #include "fmpzxx.h" #include "arithxx.h" using namespace std; using namespace flint; int main(int argc, char* argv[]) { if (argc != 2) { flint_printf("Syntax: stirling_matrix \n"); return 1; } slong n = atoi(argv[1]); fmpz_matxx S1(stirling_matrix_1(n, n)), S2(stirling_matrix_2(n, n)); flint_printf("S1 [Stirling numbers of 1st kind]:\n"); print_pretty(S1); flint_printf("\n\n"); flint_printf("S2 [Stirling numbers of 2nd kind]:\n"); print_pretty(S2); flint_printf("\n\n"); flint_printf("S1 * S2:\n"); print_pretty(S1*S2); flint_printf("\n\n"); return 0; } flint2-2.8.4/exception.c000066400000000000000000000035421414523752600151020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #if FLINT_REENTRANT && !FLINT_USES_TLS #include static pthread_once_t abort_func_init = PTHREAD_ONCE_INIT; pthread_mutex_t abort_func_lock; void __flint_set_abort_init() { pthread_mutex_init(&abort_func_lock, NULL); } #endif FLINT_NORETURN void (*abort_func)(void) = abort; void flint_set_abort(FLINT_NORETURN void (*func)(void)) { #if FLINT_REENTRANT && !FLINT_USES_TLS pthread_once(&abort_func_init, __flint_set_abort_init); pthread_mutex_lock(&abort_func_lock); #endif abort_func = func; #if FLINT_REENTRANT && !FLINT_USES_TLS pthread_mutex_unlock(&abort_func_lock); #endif } FLINT_NORETURN void flint_abort() { (*abort_func)(); } void flint_throw(flint_err_t exc, const char * msg, ...) { va_list ap; va_start(ap, msg); flint_printf("Flint exception ("); switch (exc) { case FLINT_ERROR: flint_printf("General error"); break; case FLINT_IMPINV: flint_printf("Impossible inverse"); break; case FLINT_DOMERR: flint_printf("Domain error"); break; case FLINT_DIVZERO: flint_printf("Divide by zero"); break; case FLINT_INEXACT: flint_printf("Inexact"); break; default: flint_printf("Unknown exception"); } printf("):\n "); flint_vprintf(msg, ap); va_end(ap); flint_abort(); } flint2-2.8.4/exception.h000066400000000000000000000013711414523752600151050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef EXCEPTION_H #define EXCEPTION_H typedef enum { FLINT_ERROR, /* general error */ FLINT_IMPINV, /* impossible inverse */ FLINT_DOMERR, /* domain error */ FLINT_DIVZERO, /* divide by zero */ FLINT_EXPOF, /* exponent overflow */ FLINT_INEXACT /* inexact error */ } flint_err_t; FLINT_DLL void flint_throw(flint_err_t exc, const char * msg, ...); #endif flint2-2.8.4/fft.h000066400000000000000000000256301414523752600136720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef FFT_H #define FFT_H #ifdef FFT_INLINES_C #define FFT_INLINE FLINT_DLL #else #define FFT_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "mpn_extras.h" #if HAVE_OPENMP #include /* must come after flint.h */ #endif #ifdef __cplusplus extern "C" { #endif #if defined(__MPIR_VERSION) #if !defined(__MPIR_RELEASE ) || __MPIR_RELEASE < 20600 #define mpn_sumdiff_n __MPN(sumdiff_n) extern mp_limb_t mpn_sumdiff_n(mp_ptr, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); #endif #else FFT_INLINE mp_limb_t 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; } #endif #define fft_sumdiff(t, u, r, s, n) \ (n == 0 ? 0 : mpn_sumdiff_n(t, u, r, s, n)) #define SWAP_PTRS(xx, yy) \ do { \ mp_limb_t * __ptr = xx; \ xx = yy; \ yy = __ptr; \ } while (0) /* used for generating random values mod p in test code */ #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); } } FLINT_DLL 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); FLINT_DLL 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_DLL 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); FLINT_DLL 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); FLINT_DLL void fermat_to_mpz(mpz_t m, mp_limb_t * i, mp_size_t limbs); FLINT_DLL void mpn_normmod_2expp1(mp_limb_t * t, mp_size_t limbs); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void mpn_mul_2expmod_2expp1(mp_limb_t * t, mp_limb_t * i1, mp_size_t limbs, flint_bitcnt_t d); FLINT_DLL void mpn_div_2expmod_2expp1(mp_limb_t * t, mp_limb_t * i1, mp_size_t limbs, flint_bitcnt_t d); FLINT_DLL void fft_adjust(mp_limb_t * r, mp_limb_t * i1, mp_size_t i, mp_size_t limbs, flint_bitcnt_t w); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fft_radix2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void ifft_radix2(mp_limb_t ** ii, mp_size_t n, flint_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_DLL 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_DLL 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fft_naive_convolution_1(mp_limb_t * r, mp_limb_t * ii, mp_limb_t * jj, mp_size_t m); FLINT_DLL 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); FLINT_DLL slong fft_adjust_limbs(mp_size_t limbs); FLINT_DLL 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); FLINT_DLL void flint_mpn_mul_fft_main(mp_ptr r1, mp_srcptr i1, mp_size_t n1, mp_srcptr i2, mp_size_t n2); FLINT_DLL 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); FLINT_DLL 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 *****/ FLINT_DLL 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); FLINT_DLL 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 flint2-2.8.4/fft/000077500000000000000000000000001414523752600135135ustar00rootroot00000000000000flint2-2.8.4/fft/README000066400000000000000000000313221414523752600143740ustar00rootroot00000000000000FFT Integer Multiplication code =============================== License: BSD (Note the FLINT library of which this is a part is overall LGPL v2.1+ and the latest version of GMP/MPIR 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/MPIR, 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 MPIR's 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 somtimes 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. flint2-2.8.4/fft/adjust.c000066400000000000000000000017471414523752600151620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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_n(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); } flint2-2.8.4/fft/adjust_sqrt2.c000066400000000000000000000034141414523752600163060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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_n(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_n(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); } flint2-2.8.4/fft/butterfly_lshB.c000066400000000000000000000070071414523752600166530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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_n(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_n(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_n(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_n(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_n(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); } } flint2-2.8.4/fft/butterfly_rshB.c000066400000000000000000000065501414523752600166630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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_n(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_n(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_n(t + limbs - y, t + limbs - y, y); t[limbs] = -(cy>>1) - cy3; u[limbs] = -(cy&1); cy3 = mpn_neg_n(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_n(t + limbs - x, t + limbs - x, x); t[limbs] = -(cy>>1) - cy3; u[limbs] = -(cy&1); cy3 = mpn_neg_n(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]); } } flint2-2.8.4/fft/combine_bits.c000066400000000000000000000052171414523752600163210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "stdlib.h" #include "gmp.h" #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); } flint2-2.8.4/fft/convolution.c000066400000000000000000000077561414523752600162550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.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 #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.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 "gmp.h" #include "flint.h" #include "fft.h" #include "longlong.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); } } flint2-2.8.4/fft/fermat_to_mpz.c000066400000000000000000000017311414523752600165270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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_n(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--; } } flint2-2.8.4/fft/fft_mfa_truncate_sqrt2.c000066400000000000000000000304341414523752600203250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #include "flint.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_n(u, u, limbs + 1); mpn_mul_2expmod_2expp1(v, v, limbs, b2); if (negate1) mpn_neg_n(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 "gmp.h" #include "flint.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 "gmp.h" #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); } flint2-2.8.4/fft/fft_radix2.c000066400000000000000000000025411414523752600157110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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); } flint2-2.8.4/fft/fft_truncate.c000066400000000000000000000036541414523752600163530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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); } } flint2-2.8.4/fft/fft_truncate_sqrt2.c000066400000000000000000000050421414523752600174770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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_n(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); } flint2-2.8.4/fft/ifft_mfa_truncate_sqrt2.c000066400000000000000000000336511414523752600205020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #include "flint.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_n(s, s, limbs + 1); mpn_div_2expmod_2expp1(s, s, limbs, b1); if (negate2) mpn_neg_n(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 "gmp.h" #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_n(*t1, *t1, limbs + 1); SWAP_PTRS(ii[i], *t1); fft_adjust(*t2, ii[n+i], n - (n+i)/2, limbs, w); mpn_neg_n(*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_n(*t1, *t1, limbs + 1); SWAP_PTRS(ii[i], *t1); fft_adjust_sqrt2(*t2, ii[n+i], n-i, limbs, w, *temp); mpn_neg_n(*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_n(*t1, *t1, limbs + 1); SWAP_PTRS(ii[i], *t1); fft_adjust(*t2, ii[n+i], n-i, limbs, w/2); mpn_neg_n(*t2, *t2, limbs + 1); SWAP_PTRS(ii[n+i], *t2); } } } flint2-2.8.4/fft/ifft_radix2.c000066400000000000000000000025671414523752600160720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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); } } flint2-2.8.4/fft/ifft_truncate.c000066400000000000000000000054121414523752600165160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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); } } flint2-2.8.4/fft/ifft_truncate_sqrt2.c000066400000000000000000000052601414523752600176520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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_n(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); } flint2-2.8.4/fft/inlines.c000066400000000000000000000010461414523752600153210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FFT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "fft.h" flint2-2.8.4/fft/mul_2expmod_2expp1.c000066400000000000000000000017401414523752600173130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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); } } flint2-2.8.4/fft/mul_fft_main.c000066400000000000000000000041221414523752600163160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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); } } flint2-2.8.4/fft/mul_mfa_truncate_sqrt2.c000066400000000000000000000055171414523752600203470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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 "gmp.h" #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 "gmp.h" #include "flint.h" #include "fft.h" #include "longlong.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 "gmp.h" #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); } } } } flint2-2.8.4/fft/profile/000077500000000000000000000000001414523752600151535ustar00rootroot00000000000000flint2-2.8.4/fft/profile/p-mul_fft_main.c000066400000000000000000000026301414523752600202150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { mp_size_t iters; FLINT_TEST_INIT(state); flint_printf("mul_fft_main...."); fflush(stdout); _flint_rand_init_gmp(state); iters = 1; { mp_size_t int_limbs = 1000000; mp_size_t j; mp_limb_t * i1, *i2, *r1, *r2; flint_printf("bits = %wd\n", int_limbs*FLINT_BITS); i1 = flint_malloc(6*int_limbs*sizeof(mp_limb_t)); i2 = i1 + int_limbs; r1 = i2 + int_limbs; r2 = r1 + 2*int_limbs; flint_mpn_urandomb(i1, state->gmp_state, int_limbs*FLINT_BITS); flint_mpn_urandomb(i2, state->gmp_state, int_limbs*FLINT_BITS); for (j = 0; j < iters; j++) //mpn_mul(r2, i1, int_limbs, i2, int_limbs); flint_mpn_mul_fft_main(r1, i1, int_limbs, i2, int_limbs); flint_free(i1); } flint_randclear(state); flint_printf("done\n"); return 0; } flint2-2.8.4/fft/profile/p-mul_mfa_truncate_sqrt2.c000066400000000000000000000032611414523752600222360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; mp_size_t iters, j; 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; } flint2-2.8.4/fft/profile/p-mul_truncate_sqrt2.c000066400000000000000000000032371414523752600214160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; mp_size_t iters, j; 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; } flint2-2.8.4/fft/split_bits.c000066400000000000000000000171061414523752600160400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #include "flint.h" #include "fft.h" #include "thread_support.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 #include "flint.h" #include "ulong_extras.h" #include "fft.h" /* 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); } 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); } int main(void) { mp_size_t c, bits, j, k, n, w, limbs; mpz_t p, m2a, m2b, mn1; mp_limb_t * nn1, * r1; FLINT_TEST_INIT(state); flint_printf("adjust...."); fflush(stdout); _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++) { 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); abort(); } flint_free(nn1); flint_free(r1); } } } } mpz_clear(p); mpz_clear(m2a); mpz_clear(m2b); mpz_clear(mn1); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fft/test/t-adjust_sqrt2.c000066400000000000000000000061721414523752600175320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fft.h" /* 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); } 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); } int main(void) { mp_size_t c, bits, j, k, n, w, limbs; mpz_t p, m2a, m2b, mn1; mp_limb_t * nn1, * r1, * temp; FLINT_TEST_INIT(state); flint_printf("adjust_sqrt2...."); fflush(stdout); _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) { 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); abort(); } flint_free(temp); flint_free(nn1); flint_free(r1); } } } } mpz_clear(p); mpz_clear(m2a); mpz_clear(m2b); mpz_clear(mn1); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fft/test/t-butterfly.c000066400000000000000000000151701414523752600171230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fft.h" /* 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); } 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); } int main(void) { 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_TEST_INIT(state); flint_printf("fft/ifft_butterfly...."); fflush(stdout); _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++) { 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); 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); 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++) { 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); 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); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fft/test/t-butterfly_lshB.c000066400000000000000000000103541414523752600200720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fft.h" /* 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); } 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); } int main(void) { 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_TEST_INIT(state); flint_printf("butterfly_lshB...."); fflush(stdout); _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++) { 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); 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); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fft/test/t-butterfly_rshB.c000066400000000000000000000110501414523752600200720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fft.h" /* 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); } 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); } int main(void) { 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_TEST_INIT(state); flint_printf("butterfly_rshB...."); fflush(stdout); _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++) { 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); 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); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fft/test/t-butterfly_sqrt2.c000066400000000000000000000165101414523752600202550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fft.h" /* 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); } 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); } int main(void) { 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_TEST_INIT(state); flint_printf("fft/ifft_butterfly_sqrt2...."); fflush(stdout); _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) { 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); 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); 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) { 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); 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); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fft/test/t-butterfly_twiddle.c000066400000000000000000000160101414523752600206310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" /* 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); } 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); } int main(void) { 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_TEST_INIT(state); flint_printf("fft/ifft_butterfly_twiddle...."); fflush(stdout); _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++) { 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); 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); 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++) { 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); 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); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fft/test/t-convolution.c000066400000000000000000000066741414523752600174730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; FLINT_TEST_INIT(state); flint_printf("convolution...."); fflush(stdout); _flint_rand_init_gmp(state); for (depth = 6; depth <= 13; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; FLINT_TEST_INIT(state); flint_printf("convolution_precache...."); fflush(stdout); _flint_rand_init_gmp(state); for (depth = 6; depth <= 13; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" /* 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); } int main(void) { 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_TEST_INIT(state); flint_printf("div_2expmod_2expp1...."); fflush(stdout); _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); abort(); } flint_free(nn); flint_free(r); } } } } mpz_clear(mn2); mpz_clear(mn1); mpz_clear(m2); mpz_clear(m1); mpz_clear(p); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fft/test/t-fft_ifft_mfa_truncate_sqrt2.c000066400000000000000000000053121414523752600225520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; FLINT_TEST_INIT(state); flint_printf("fft/ifft_mfa_truncate_sqrt2...."); fflush(stdout); _flint_rand_init_gmp(state); for (depth = 6; depth <= 13; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; FLINT_TEST_INIT(state); flint_printf("fft/ifft_negacyclic...."); fflush(stdout); _flint_rand_init_gmp(state); for (depth = 6; depth <= 12; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; FLINT_TEST_INIT(state); flint_printf("fft/ifft_radix2...."); fflush(stdout); _flint_rand_init_gmp(state); for (depth = 6; depth <= 12; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; FLINT_TEST_INIT(state); flint_printf("fft/ifft_truncate...."); fflush(stdout); _flint_rand_init_gmp(state); for (depth = 6; depth <= 12; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; FLINT_TEST_INIT(state); flint_printf("fft/ifft_truncate_sqrt2...."); fflush(stdout); _flint_rand_init_gmp(state); for (depth = 6; depth <= 12; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" /* 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); } int main(void) { 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_TEST_INIT(state); flint_printf("mul_2expmod_2expp1...."); fflush(stdout); _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); abort(); } flint_free(nn); flint_free(r); } } } } mpz_clear(mn2); mpz_clear(mn1); mpz_clear(m2); mpz_clear(m1); mpz_clear(p); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fft/test/t-mul_fft_main.c000066400000000000000000000052241414523752600175420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; FLINT_TEST_INIT(state); flint_printf("mul_fft_main...."); fflush(stdout); _flint_rand_init_gmp(state); for (depth = 6; depth <= 12; 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]); abort(); } } flint_free(i1); } } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fft/test/t-mul_mfa_truncate_sqrt2.c000066400000000000000000000061111414523752600215560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; FLINT_TEST_INIT(state); flint_printf("mul_mfa_truncate_sqrt2...."); fflush(stdout); _flint_rand_init_gmp(state); for (depth = 6; depth <= 13; depth++) { for (w = 1; w <= 3 - (depth >= 12); w++) { mp_size_t n = (UWORD(1)<= 12); w++) { mp_size_t n = (UWORD(1)<. */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; FLINT_TEST_INIT(state); flint_printf("mul_truncate_sqrt2...."); fflush(stdout); _flint_rand_init_gmp(state); for (depth = 6; depth <= 12; depth++) { for (w = 1; w <= 5; w++) { mp_size_t n = (UWORD(1)<. */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { flint_bitcnt_t depth, w; int iters; FLINT_TEST_INIT(state); flint_printf("mulmod_2expp1...."); fflush(stdout); _flint_rand_init_gmp(state); for (iters = 0; iters < 100; iters++) { for (depth = 6; depth <= 18; depth++) { for (w = 1; w <= 2; w++) { mp_size_t n = (UWORD(1)<. */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" /* 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); } int main(void) { flint_bitcnt_t bits; mp_size_t j, k, n, w, limbs; mp_limb_t * nn; mpz_t p, m1, m2; FLINT_TEST_INIT(state); flint_printf("normmod_2expp1...."); fflush(stdout); _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); abort(); } flint_free(nn); } } } mpz_clear(m2); mpz_clear(m1); mpz_clear(p); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fft/test/t-split_combine_bits.c000066400000000000000000000037411414523752600207540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.h" int main(void) { int i; mp_size_t j; FLINT_TEST_INIT(state); flint_printf("split/combine_bits...."); fflush(stdout); _flint_rand_init_gmp(state); for (i = 0; i < 10000; 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]); abort(); } } flint_free(in); flint_free(out); for (j = 0; j < length; j++) flint_free(poly[j]); flint_free(poly); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fft/tune/000077500000000000000000000000001414523752600144665ustar00rootroot00000000000000flint2-2.8.4/fft/tune/tune-fft.c000066400000000000000000000125711414523752600163700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fft.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; } flint2-2.8.4/fft_tuning32.in000066400000000000000000000005061414523752600155750ustar00rootroot00000000000000/* 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 flint2-2.8.4/fft_tuning64.in000066400000000000000000000005221414523752600156000ustar00rootroot00000000000000/* 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 flint2-2.8.4/flint.h000066400000000000000000000304601414523752600142240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef FLINT_H #define FLINT_H #undef ulong #define ulong ulongxx /* ensure vendor doesn't typedef ulong */ #if !defined(_MSC_VER) #include /* for BSD define */ #endif #include #include #include #include #include /* for alloca on FreeBSD */ #if (!defined(BSD) && !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(_MSC_VER)) || defined(__GNU__) /* MinGW and FreeBSD have alloca, but not alloca.h */ #include #endif #if defined(__MINGW32__) #include /* for alloca on MinGW */ #endif #include "limits.h" #include "longlong.h" #include "flint-config.h" #undef ulong #ifdef FLINT_INLINES_C #define FLINT_INLINE FLINT_DLL #else #define FLINT_INLINE static __inline__ #endif #if FLINT_USES_GC #include "gc.h" #endif #if FLINT_WANT_ASSERT #include #endif #ifdef __cplusplus extern "C" { #endif /* flint version number */ #define __FLINT_VERSION 2 #define __FLINT_VERSION_MINOR 8 #define __FLINT_VERSION_PATCHLEVEL 0 #define FLINT_VERSION "2.8.0" #define __FLINT_RELEASE (__FLINT_VERSION * 10000 + \ __FLINT_VERSION_MINOR * 100 + \ __FLINT_VERSION_PATCHLEVEL) /* Check mpir and mpfr version numbers */ #if __GNU_MP_VERSION < 5 #error GMP 5.0.0 or MPIR 2.6.0 or later are required #endif #if MPFR_VERSION_MAJOR < 3 #error MPFR 3.0.0 or later is required #endif /* We define alternative key words for "asm" and "inline", allowing the code to be compiled with the "-ansi" flag under GCC */ #ifndef __GNUC__ #define __asm__ asm #define __inline__ inline #endif extern char flint_version[]; #define ulong mp_limb_t #define slong mp_limb_signed_t FLINT_DLL void * flint_malloc(size_t size); FLINT_DLL void * flint_realloc(void * ptr, size_t size); FLINT_DLL void * flint_calloc(size_t num, size_t size); FLINT_DLL void flint_free(void * ptr); typedef void (*flint_cleanup_function_t)(void); FLINT_DLL void flint_register_cleanup_function(flint_cleanup_function_t cleanup_function); FLINT_DLL void flint_cleanup(void); FLINT_DLL void flint_cleanup_master(void); FLINT_DLL 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 *)); #ifdef __GNUC__ #define FLINT_NORETURN __attribute__ ((noreturn)) #else #define FLINT_NORETURN #endif FLINT_DLL FLINT_NORETURN void flint_abort(void); FLINT_DLL void flint_set_abort(FLINT_NORETURN void (*func)(void)); /* flint_abort is calling abort by default * if flint_set_abort is used, then instead of abort this function * is called. EXPERIMENTALLY use at your own risk! * May disappear in future versions. */ #if defined(_WIN64) || defined(__mips64) #if defined(__MINGW64__) #define WORD_FMT "%I64" #define WORD_WIDTH_FMT "%*I64" #else #define WORD_FMT "%ll" #define WORD_WIDTH_FMT "%*ll" #endif #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_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 #define flint_bitcnt_t ulong #if FLINT_USES_TLS #if __STDC_VERSION__ >= 201112L #define FLINT_TLS_PREFIX _Thread_local #elif defined(_MSC_VER) #define FLINT_TLS_PREFIX __declspec(thread) #elif defined(__GNUC__) #define FLINT_TLS_PREFIX __thread #else #error "thread local prefix defined in C11 or later" #endif #else #define FLINT_TLS_PREFIX #endif FLINT_DLL int flint_get_num_threads(void); FLINT_DLL void flint_set_num_threads(int num_threads); FLINT_DLL void _flint_set_num_workers(int num_workers); FLINT_DLL int flint_set_num_workers(int num_workers); FLINT_DLL void flint_reset_num_workers(int max_workers); FLINT_DLL int flint_set_thread_affinity(int * cpus, slong length); FLINT_DLL int flint_restore_thread_affinity(); int 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); } #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(); /* We define this here as there is no mpfr.h */ typedef __mpfr_struct flint_mpfr; #if FLINT_WANT_ASSERT #define FLINT_ASSERT(param) assert(param) #else #define FLINT_ASSERT(param) #endif #if defined(__GNUC__) #define FLINT_UNUSED(x) UNUSED_ ## x __attribute__((unused)) #define FLINT_SET_BUT_UNUSED(x) x __attribute__((unused)) #if __GNUC__ >= 4 #define FLINT_WARN_UNUSED __attribute__((warn_unused_result)) #else #define FLINT_WARN_UNUSED #endif #else #define __attribute__(x) #define FLINT_UNUSED(x) x #define FLINT_SET_BUT_UNUSED(x) x #define FLINT_WARN_UNUSED #endif #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 MP_PTR_SWAP(x, y) \ do { \ mp_limb_t * __txxx; \ __txxx = x; \ x = y; \ y = __txxx; \ } while (0) #define SLONG_SWAP(A, B) \ do { \ slong __t_m_p_ = A; \ A = B; \ B = __t_m_p_; \ } while (0) #define ULONG_SWAP(A, B) \ do { \ ulong __t_m_p_ = A; \ A = B; \ B = __t_m_p_; \ } while (0) #define MP_LIMB_SWAP(A, B) \ do { \ mp_limb_t __t_m_p_ = A; \ A = B; \ B = __t_m_p_; \ } while (0) #define DOUBLE_SWAP(A, B) \ do { \ double __t_m_p_ = A; \ A = B; \ B = __t_m_p_; \ } 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))) #ifdef NEED_CLZ_TAB FLINT_DLL extern const unsigned char __flint_clz_tab[128]; #endif /* 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) count_leading_zeros(zeros, x); return FLINT_BITS - zeros; } #define FLINT_FLOG2(k) (FLINT_BIT_COUNT(k) - 1) #define FLINT_CLOG2(k) FLINT_BIT_COUNT((k) - 1) #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) /* common usage of flint_malloc */ #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)) /* temporary allocation */ #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 #if 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; \ } /* compatibility between gmp and mpir */ #ifndef mpn_com_n #define mpn_com_n mpn_com #endif #ifndef mpn_neg_n #define mpn_neg_n mpn_neg #endif #ifndef mpn_tdiv_q /* substitute for mpir's mpn_tdiv_q */ 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; } #endif /* 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 } FLINT_DLL int parse_fmt(int * floating, const char * fmt); FLINT_DLL int flint_printf(const char * str, ...); /* flint version of printf */ FLINT_DLL int flint_vprintf(const char * str, va_list ap); /* va_list version of flint_printf */ FLINT_DLL int flint_fprintf(FILE * f, const char * str, ...); /* flint version of fprintf */ FLINT_DLL int flint_sprintf(char * s, const char * str, ...); /* flint version of sprintf */ FLINT_DLL int flint_scanf(const char * str, ...); /* flint version of scanf */ FLINT_DLL int flint_fscanf(FILE * f, const char * str, ...); /* flint version of fscanf */ FLINT_DLL int flint_sscanf(const char * s, const char * str, ...); /* flint version of sscanf */ 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_printf("Exception (flint). Overflow creating size %wd x %wd object.\n", x, y); flint_abort(); } return lo; } #include "gmpcompat.h" #include "exception.h" #ifdef __cplusplus } #endif #endif flint2-2.8.4/flint.supp000066400000000000000000000003101414523752600147530ustar00rootroot00000000000000{ MPIR_MUL Memcheck:Addr8 fun:__gmpn_copyi fun:__gmpn_mul fun:_fmpz_poly_mul_KS } { MPIR_MUL_N Memcheck:Addr8 fun:__gmpn_copyi fun:__gmpn_mul_n fun:_fmpz_poly_mul_KS } flint2-2.8.4/flintxx.h000066400000000000000000000006621414523752600146050ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // empty and only here to make the build system happy flint2-2.8.4/flintxx/000077500000000000000000000000001414523752600144305ustar00rootroot00000000000000flint2-2.8.4/flintxx/default_rules.h000066400000000000000000000356721414523752600174540ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // This file contains default rule implementations #ifndef CXX_DEFAULT_RULES_H #define CXX_DEFAULT_RULES_H #include "mp.h" #include "expression.h" // because we want to reuse binary_op_helper etc #include "expression_traits.h" #include "evaluation_tools.h" namespace flint { namespace rules { // Composite binary operators // These rules implement binary operators by implementing both arguments // separately, then performing the operation on the evaluated types by // instantiating the appropriate rule again. // // Hence to evaluate expressions like a + (b + c), it suffices to write // rules for composition of two immediates. namespace rdetail { template struct can_evaluate_tuple : traits::is_implemented< typename mp::find_evaluation::type, true>::type> { }; template struct should_evaluate_tuple : can_evaluate_tuple { }; template struct should_evaluate_tuple >::type> : mp::false_ { }; template struct binary_should_enable { typedef mp::enable_if::type> > enable; }; } template struct evaluation >::type> { typedef tools::evaluate_n evn_t; typedef typename evn_t::evtup_t evtup_t; typedef typename evn_t::temporaries_t temporaries_t; typedef typename mp::find_evaluation< Op, evtup_t, result_is_temporary>::type rule_t; typedef typename rule_t::return_t return_t; template static void doit(const Data& input, temporaries_t temps, Return* output) { evn_t ev(input, temps); rule_t::doit(ev.gettuple(), empty_tuple(), output); } }; // Automatically invoke binary_expression or commutative_binary_expression namespace rdetail { template struct inverted_binary_expression { typedef commutative_binary_expression wrapped_t; typedef typename wrapped_t::return_t return_t; template static void doit(Return& to, const Expr1& e1, const Expr2& e2) { return wrapped_t::doit(to, e2, e1); } }; template class BE, class Data1, class Op, class Data2> struct binary_expr_helper { typedef typename traits::basetype::type data1_t; typedef typename traits::basetype::type data2_t; typedef BE wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, input.first(), input.second()); } }; } // rdetail template struct evaluation< Op, tuple >, result_is_temporary, 0, typename mp::enable_if< mp::and_< traits::is_immediate::type>, mp::and_< traits::is_immediate::type>, mp::or_< traits::is_implemented::type, Op, typename traits::basetype::type > >, mp::or_< traits::is_implemented::type, Op, typename traits::basetype::type > >, traits::is_implemented::type, Op, typename traits::basetype::type > > > > > > >::type> : mp::if_< traits::is_implemented::type, Op, typename traits::basetype::type > >, rdetail::binary_expr_helper, typename mp::if_< traits::is_implemented::type, Op, typename traits::basetype::type > >, rdetail::binary_expr_helper< commutative_binary_expression, Data1, Op, Data2>, rdetail::binary_expr_helper< rdetail::inverted_binary_expression, Data1, Op, Data2> >::type >::type { }; // Automatically invoke unary_expression template struct evaluation, result_is_temporary, 0, typename mp::enable_if< traits::is_implemented< unary_expression::type> > >::type> { typedef unary_expression::type> wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, input.head); } }; // Automatically invoke threeary_expression template struct evaluation > >, result_is_temporary, 0, typename mp::enable_if< traits::is_implemented< threeary_expression::type, typename traits::basetype::type, typename traits::basetype::type> > >::type> { typedef threeary_expression::type, typename traits::basetype::type, typename traits::basetype::type> wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input)); } }; // Automatically invoke fourary_expression template struct evaluation > > >, result_is_temporary, 0, typename mp::enable_if< traits::is_implemented< fourary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> > >::type> { typedef fourary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input)); } }; // Automatically invoke fiveary_expression template struct evaluation > > > >, result_is_temporary, 0, typename mp::enable_if< traits::is_implemented< fiveary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> > >::type> { typedef fiveary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input)); } }; // Automatically invoke sixary_expression template struct evaluation > > > > >, result_is_temporary, 0, typename mp::enable_if< traits::is_implemented< sixary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> > >::type> { typedef sixary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input)); } }; // Automatically invoke sevenary_expression template struct evaluation > > > > > >, result_is_temporary, 0, typename mp::enable_if< traits::is_implemented< sevenary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> > >::type> { typedef sevenary_expression::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type, typename traits::basetype::type> wrapped_t; typedef typename wrapped_t::return_t return_t; typedef empty_tuple temporaries_t; typedef typename mp::make_tuple::type data_t; template static void doit(const data_t& input, temporaries_t temps, Return* output) { wrapped_t::doit(*output, mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input), mp::tuple_get::get(input)); } }; // Instantiating temporaries namespace rdetail { template struct evaluated_type_pred { template struct type : mp::equal_types< typename tools::evaluation_helper::type, T> { }; }; } template struct use_default_temporary_instantiation : mp::true_ { }; template struct instantiate_temporaries { static T get(const Expr& e) { return T(); } }; template struct instantiate_temporaries, traits::is_expression, tools::has_subexpr, Expr> > >::type> { static T get(const Expr& e) { return tools::find_subexpr >(e) .create_temporary(); } }; } // rules } // flint #endif flint2-2.8.4/flintxx/doc/000077500000000000000000000000001414523752600151755ustar00rootroot00000000000000flint2-2.8.4/flintxx/doc/Makefile000066400000000000000000000000601414523752600166310ustar00rootroot00000000000000include LaTeX.mk design: design.pdf evince $< flint2-2.8.4/flintxx/doc/design.tex000066400000000000000000000336371414523752600172040ustar00rootroot00000000000000% vim:spell spelllang=en_us textwidth=75 \documentclass{scrartcl} \usepackage[utf8]{inputenc} \usepackage{amsfonts} \title{A generic expression template library for arithmetic data types} \author{Tom Bachmann\footnote{\texttt{e\_mc\_h2@web.de}}} \begin{document} \maketitle \section*{Introduction} This note describes the design I plan to implement this summer for a c++ wrapper for the FLINT library\footnote{\texttt{www.flintlib.org}}. Any kinds of comments are appreciated. \emph{Added after the summer}: this document turned out to be reasonably accurate. I updated it slightly to reflect what was actually done. \paragraph{Overview} In first approximation, FLINT implements arithmetic operations on and representations of elements of specific rings, \emph{with unlimited precision}. The implemented rings include $\mathbf{Z}, \mathbf{Q}, \mathbf{Z}[X], \mathbf{Z}[X_{ij}], \mathbf{F}_q[X], \mathbf{Z}/n\mathbf{Z}$ and similar ones. FLINT is written in C, so arithmetic operations look like \texttt{fmpz\_add(target, source1, source2)}. In crude terms, this note describes how to write a C++ wrapper, allowing us to turn the above expression into \texttt{target = source1 + source2}. \section*{Objectives} The wrapper library has to satisfy a number of competing objectives: \begin{description} \item[Performance] Whenever feasible, the C++ code should compile down into equivalent C code which is as close in performance to hand-written code as possible. \item[Portability] The library should be usable on as many different compilers and compiler versions as possible. \item[Easy extensibility] It should be straightforward for FLINT developers (which may only know C) to extend the wrapper library to add a new data type. \item[Completeness] The wrapper library should expose all FLINT C functions. \end{description} There are also the following secondary objectives: \begin{itemize} \item If possible, the library should be sufficiently generic to be used by other open source projects seeking to create a C++ wrapper. \item If possible, the wrapper should anticipate and/or facilitate generics. \item The wrapper should allow for further layers of abstraction, e.g. to provide an NTL-compatible interface. \end{itemize} \section*{Design} In order to meet the above goals, we have made the following decisions. Performance will be achieved using expression templates, following the C++98 standard. To improve diagnostics, we will use static assert frequently (in C++98 mode we use standard implementations, in C++11 mode we use the language internal one). There will be no automatic casts. The wrapper library will be split clearly into FLINT-specific and generic parts. \subsection*{Overview} Consider an expression like \texttt{fmpz a = b + c * d}. In an expression template library, this consists of two stages. The first is expression template \emph{parsing}, and the second is \emph{execution}. The expression \texttt{b + c * d} results in a temporary object, the type of which encodes the operations performed, and the state of which consists of references to the arguments \texttt{b}, \texttt{c} and \texttt{d}. The assignment then triggers the execution. This means the library figures out how to most efficiently evaluate the expression. In general, this may require the allocation of a temporary \texttt{t}, and then executing \texttt{t = c * d}, \texttt{a = b + t}. In the case of a newly initialized \texttt{a} as here, we can avoid \texttt{t} and use \texttt{a} as a temporary. Additionally, for some data types the C library may support addmul-type operations, so we can compile down to a single C call. \subsection*{Expression template representation and execution} In order to facilitate reuse and extensibility, we decouple and modularize the steps explained above. The main expression template class has declaration as follows: \begin{verbatim} template class Expression ... \end{verbatim} The template argument \texttt{Operation} specifies which operation is to be executed (for example ``plus'', ``times'' or even ``exp''), whereas \texttt{Data} encodes the actual data required to perform the operation. Part of the body of the class could look like this: \begin{verbatim} { protected: Data data; public: typedef Operation op_t; typedef Data data_t; explicit Expression(Data d) : data (d) {}; template typename Derived::template type > operator+(const Right& r) { return Derived::template type >( Pair(*this, r); } }; \end{verbatim} There are a few peculiarities to note. Firstly \texttt{Plus} is just an empty type, which simply serves as a tag. Secondly \texttt{Pair} is just what it sounds like (essentially \texttt{std::pair}). But more importantly, the template parameter \texttt{Derived} is used to automatically wrap expression templates into a convenience derived class. It could look like this: \begin{verbatim} template struct derived { template struct type : Expression { template explicit type(const T& t) : Expression(t) {} void foo() {Policy();} }; }; \end{verbatim} We still have not reached the type the user is actually going to instantiate. For this, we can use a special type of operation that signifies an immediate data. For example: \begin{verbatim} typedef derived::type Fmpz; \end{verbatim} All the indirection allows us to have instances of \texttt{Fmpz} come with a member function \texttt{foo} which is customised by the ``StandardPolicy''. Note that currently there are no non-trivial constructors or destructors for Fmpz. These can be injected either via traits (see below), or via member template enabling. Next, we describe the execution stage. For this, we extend the \texttt{Expression} class by an assignment operator, which uses a traits library to run the execution. A simple version might look like this: \begin{verbatim} template<...> class Expression { ... template typename Derived::template type& operator=(const Other& o) { typedef traits::evaluate evaluator; traits::assign::doit( *this, evaluator::doit(o)); } }; namespace traits { template struct evaluate; template struct evaluate_helper; template struct evaluate::type > { typedef evaluate_helper helper; typedef typename helper::return_type return_type; template return_type doit(const T& t){return helper::doit(t.data());} }; template<> struct evaluate_helper > { typedef Fmpz return_type; Fmpz doit(const Pair& data) { ... } }; template struct evaluate_helper > { typedef evaluate leval_t; typedef evaluate reval_t; typedef evaluate_helper > eh_t; typedef typename eh_t::return_type return_type; return_type doit(const Pair& data) { leval_t::return_type t1 = leval_t::doit(data.left.data()); reval_t::return_type t2 = reval_t::doit(data.right.data()); return eh_t::doit(make_pair(t1, t2)); } }; } \end{verbatim} This code can evaluate arbitrary additions of Fmpz. It should be extended to use three argument add, etc. \subsection*{Temporary allocation} The above design is functional, but results in unnecessarily many temporaries. Instead, ... \subsection*{Conflict resolution for traits} A common problem with partial template specialisation is that instantiation can fail completely if no partial order can be established. I propose two ways around this: conditional template enabling, and a priority system. By conditional template enabling I mean the equivalent of \texttt{boost.enable\_if}. By a priority system, I mean adding an additional integer template parameter \texttt{priority}, and having most traits only enable themselves if the priority is a certain fixed number. Then, using SFINAE techniques, we can iterate through the priorities and use the highest-priority match. This latter technique has the desirable property of being easy to understand and use by non-experts. \section*{Future plans} The following sections contain deliberations about things which I did not manage to work on this summer. \subsection*{Class structure for (FLINT) generics} Corresponding to any ring (or sometimes module), there will be two classes: the \emph{context} representing the ring itself, and the \emph{element} representing elements of the ring. Contexts are immutable, but elements are usually not. Often the context will be essentially empty (e.g. for $\mathbf{Z}$), but sometimes it may hold data common to all elements, e.g. the modulus $n$ of $\mathbf{Z}/n\mathbf{Z}.$ Every element instance holds a reference to a context. In general arithmetic operations are only supported if the contexts agree, but this is not usually checked. We also differentiate between \emph{primitive types}, \emph{compound types} and \emph{specialised types}. The primitive types such as $\mathbf{Z}, \mathbf{Q}_p$ are the building blocks and are atomic from the point of view of this wrapper. Compound types such as $A[T]$ (for any ring $A$) or $Frac(A)$ (for domains $A$) are built from primitive and compound types. They have implementations of arithmetic operations in terms of operations in $A,$ and so are generic. Finally the specialised types are versions of compound types with particular arithmetic implementations tailored to the particular type, e.g. $\mathbf{Z}[T]$ (where multiplication can be implemented using polynomial reconstruction and multiplication in $\mathbf{Z}$). For the initial implementation, the generic types will not come with arithmetic implementations. Instead I will focus on wrapping all the particular implementations in FLINT. Tables \ref{tab:primitive-types}, \ref{tab:compound-types} and \ref{tab:specialised-types} list the primitive, compound, and specialised types of the FLINT wrapper. \begin{table}[h] \begin{center} \begin{tabular}{cc} FLINT name & representing \\ \hline fmpz & $\mathbf{Z}$ \\ padic & $\mathbf{Q}_p$ (to fixed accuracy) \\ ulong & $\mathbf{Z}/2^{s}\mathbf{Z}$ (where $s$ is the machine wordsize) \\ \end{tabular} \end{center} \caption{Primitive types for the FLINT wrapper.} \label{tab:primitive-types} \end{table} \begin{table}[h] \begin{center} \begin{tabular}{cc} wrapper name & representing \\ \hline poly & $A[T]$ \\ fraction & $Frac(A)$ ($A$ a domain) \\ PIquotient & $A/aA$ \\ vector (not actually a ring) & $A^n$ (with $n$ large) \\ matrix (not always a ring) & $n \times m$ matrices over $A$ (with $m, n$ large) \\ \end{tabular} \end{center} \caption{Compound types for the FLINT wrapper.} \label{tab:compound-types} \end{table} A potential later addition could be fixed-size vectors and matrices with automatically unrolled operations. \begin{table}[h] \begin{center} \begin{tabular}{cc} FLINT name & specialising compound type \\ \hline fmpq & \texttt{fraction} \\ fmpz\_poly\_q & \texttt{fraction>} \\ \\ ``mod'' & \texttt{PIquotient} \\ nmod & \texttt{PIquotient} \\ \\ fmpz\_poly & \texttt{poly} \\ fmpq\_poly & \texttt{poly} \\ nmod\_poly & \texttt{poly} \\ fmpz\_mod\_poly & \texttt{poly } \\ \\ fmpz\_vec & \texttt{vector} \\ nmod\_vec & \texttt{vector>} \\ \\ fmpz\_mat & \texttt{matrix} \\ fmpq\_mat & \texttt{matrix>} \\ fmpz\_poly\_mat & \texttt{matrix>} \\ nmod\_mat & \texttt{matrix>} \\ nmod\_poly\_mat & \texttt{matrix>>} \end{tabular} \end{center} \caption{Specialised types for the FLINT wrapper.} \label{tab:specialised-types} \end{table} \subsection*{Wrapper class with additional member functions} The above design already allows for members on every type. But suppose I want to add a class \texttt{Tmpz} which behaves much like \texttt{Fmpz}, except that it has different member functions. That is, suppose I want to create a drop-in replacement for some other library, leveraging the flint backend. This can be done as follows (in the simplified notation without temporary avoidance): \begin{verbatim} struct derived2 { template struct type : Expression { template explicit type(const T& t) : Expression(t) {} void bar() {} } }; typedef derived2::type Tmpz; namespace traits { template struct convert; template struct convert { typedef derived::template type::return_type> return_type; template return_type doit(const T& t) { return return_type(convert::doit(t.data())); } }; template<> struct convert { typedef Fmpz return_type; template return_type doit(const T& t) { return t.data(); } } template struct evaluate > { typedef convert > eh2_t; typedef evaluate::return_type ev_t; typedef ev_t::return_type return_type; template return_type doit(const T& t) { return ev_t::doit(eh2_t::doit(t)); } }; } \end{verbatim} That is to say, evaluation of Tmpz first converts the expression template into the Fmpz equivalent (this does not incur any cost), then evaluates the Fmpz, and then (using the implementation of assign not shown) wraps into Tmpz again. The beauty of this approach is that the underlying type is never leaked accidentally to the user, yet still all the optimizations for FLINT expression templates apply. \end{document} flint2-2.8.4/flintxx/doc/flintxx.txt000066400000000000000000005461051414523752600174450ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ ******************************************************************************* flint\_exception This is the main exception type used by the flintxx library. It derives from \code{std::domain_error}. As such its main method is \code{what()}, yielding an English language description of the problem encountered. ******************************************************************************* ******************************************************************************* frandxx The type \code{frandxx} wraps \code{flint_rand_t} and takes care of initialising and clearing random states. It is defined in \code{flintxx/frandxx.h}. Note that this type is not copyable. ******************************************************************************* frandxx::frandxx() Initialize random state. flint_rand_t& frandxx::_data() const flint_rand_t& frandxx::_data() const Obtain a reference to the underlying C random state. ******************************************************************************* ltuple Lazy tuples are implemented in \code{flintxx/ltuple.h}. They are used throughout flintxx to emulate functions with several return values. This header automatically creates a static instance of \code{flint::detail::IGNORED_TYPE}. It is accessible in namespace flint, under the name \code{FLINT_LTUPLE_PLACEHOLDER_NAME}, which defaults to \code{_}. See \code{ltupleref} documentation for how to use this. ******************************************************************************* Ltuple ltupleref(T1& t1, ..., Tn& tn) Construct an ltuple of references, binding to the arguments \code{t1}, \dots, \code{tn}. Instances of \code{flint::detail::IGNORED_TYPE} can be used as placeholders. Currently $n \le 4$. Ltuple ltuple(const T1& t1, ..., const Tn& tn) Construct an ltuple containing copies of \code{t1}, \dots, \code{tn}. Currently \code{n \le 4}. Tk_expr Ltuple_expr::get() const If \code{Tk} is an expression template type, then the \code{get()} method returns a lazy expression evaluating to the kth element of the (potentially lazy) ltuple. If \code{Tk} is not an expression template type, this method evaluates the ltuple, and returns the kth entry. On ltuple immediates, reference versions are also available, which can be used to manipulate the entries. ******************************************************************************* permxx Permutations are mostly used by row reduction algorithms. Even though we support limited arithmetic on them (e.g. composition), permutations are not implemented as expression templates. \code{permxx} wraps the C interface \code{perm} operating on \code{slong*}. ******************************************************************************* permxx::permxx(slong n) static permxx permxx::one(slong n) Initialize an identity permutation on the set $[n] = \{0, 1, \dots, n-1\}$. static permxx permxx::randtest(slong n) Generate a random permutation on $[n]$. See \code{_perm_randtest}. bool permxx::operator==(const permxx&) bool permxx::operator!=(const permxx&) slong permxx::size() const Return the size of the set being permuted ($n$ in the constructors). slong& operator[](slong i) slong operator[](slong i) const Return the image of $i$ under the permutation. permxx permxx::operator*(const permxx&) permxx compose(const permxx& p1, const permxx& p2) Compute the composition of two permutations. See \code{_perm_compose}. void permxx::set_inv(const permxx& o) Set self to the inverse permutation of \code{o}. permxx permxx::inv() const permxx inv(const permxx&) Return the inverse permutation. int print(const permxx&) ******************************************************************************* fmpzxx ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ C++ particulars +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr::unary operation() const The following unary functions are made available as member functions: \code{sqrt}, \code{abs}. Fmpz_expr::binary operation(??) const The following binary functions are made available as member functions: \code{cdiv_q}, \code{divexact}, \code{fdiv_qr}, \code{fdiv_r}, \code{fdiv_r_2exp}, \code{gcd}, \code{gcdinv}, \code{invmod}, \code{lcm}, \code{negmod}, \code{pow}, \code{rfac}, \code{root}, \code{sqrtmod}, \code{tdiv_q}, \code{tdiv_q_2exp}, \code{tdiv_qr}, \code{xgcd}. Fmpz_expr::ternary operation(??, ??) const The following ternary functions are made available as member functions: \code{divexact2}, \code{mul2}, \code{mul_tdiv_q_2exp}, \code{powm}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmpzxx::fmpzxx() Initialize to zero. fmpzxx::fmpzxx(const char*) fmpzxx::fmpzxx(T:is_integer) Initialize from a primitive data type. See \code{fmpz_set_str}, \code{fmpz_set_si} and \code{fmpz_set_ui}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Random generation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static fmpzxx fmpzxx::randbits(frandxx& state) static fmpzxx fmpzxx::randtest(frandxx& state) static fmpzxx fmpzxx::randtest_unsigned(frandxx& state) static fmpzxx fmpzxx::randtest_not_zero(frandxx& state) static fmpzxx fmpzxx::randm(frandxx& state, Fmpz_expr m) static fmpzxx fmpzxx::randtest_mod(frandxx& state, Fmpz_expr m) static fmpzxx fmpzxx::randtest_mod_signed(frandxx& state, Fmpz_expr m) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Conversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ std::string Fmpz_expr::to_string(int base = 10) const Convert self into a \code{string}. See \code{fmpz_get_str}. slong Fmpz_expr::to() const Convert self to \code{slong}. See \code{fmpz_get_si}. ulong Fmpz_expr::to() const Convert self to \code{ulong}. See \code{fmpz_get_ui}. double Fmpz_expr::to() const Convert self to \code{double}. See \code{fmpz_get_d}. double Fmpz_expr::get_d_2exp(long& exp) const Fmpz_target Fmpz_target::operator=(const char*) Fmpz_target Fmpz_target::operator=(T:is_integer) See \code{fmpz_set_str}, \code{fmpz_set_ui} and \code{fmpz_set_si}. void Fmpz_target::set_ui_smod(mp_limb_t x, mv_limb_t m) void Fmpz_target::set_uiui(mp_limb_t x, mv_limb_t m) void Fmpz_target::neg_uiui(mp_limb_t x, mv_limb_t m) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int print(Fmpz_expr) int print(FILE*, Fmpz_expr) int read(Fmpz_target) int read(FILE*, Fmpz_target) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic properties and manipulation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ size_t Fmpz_expr::sizeinbase(int) const size_t sizeinbase(Fmpz_expr, int) mp_bitcnt_t Fmpz_expr::bits() const mp_bitcnt_t bits(Fmpz_expr) mp_bitcnt_t Fmpz_expr::size() const mp_bitcnt_t size(Fmpz_expr) mp_bitcnt_t Fmpz_expr::val2() const mp_bitcnt_t val2(Fmpz_expr) int Fmpz_expr::sign() const int sign(Fmpz_expr) void Fmpz_target::set_zero() void Fmpz_target::set_one() bool Fmpz_expr::abs_fits_ui() const bool Fmpz_expr::fits_si() const void Fmpz_target::setbit(ulong) bool Fmpz_expr::tstbit(ulong) const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparison Relational operators \code{<=}, \code{>} etc are overloaded, where \code{e1} and \code{e2} can be any combination of \code{Fmpz_expr} and \code{T:is_integer}. See \code{fmpz_cmp}, \code{fmpz_cmp_si} and \code{fmpz_cmp_ui}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpz_expr::is_zero() const Return if this expression evaluates to zero. bool Fmpz_expr::is_one() const Return if this expression evaluates to one. bool Fmpz_expr::is_pm1() const Return if this expression evaluates to $\pm 1$. bool Fmpz_expr::is_even() const Return if this expression evaluates to an even integer. bool Fmpz_expr::is_odd() const Return if the expression evaluates to an odd integer. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic arithmetic Arithmetic operators \code{+}, \code{-}, \code{*}, \code{/}, \code{%}, \code{<<} and \code{>>} are overloaded. See the \code{fmpz} documentation for which argument types are allowed. Symmetric operators with asymmetric type arguments can be used in either order, even if this is not exposed in the C interface. The shift operators wrap \code{fmpz_fdiv_q_2exp} and \code{fmpz_mul_2exp}. The division operators use \code{fmpz_fdiv}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr abs(Fmpz_expr) Fmpz_expr mul2_uiui(Fmpz_expr g, ulong x, ulong y) Fmpz_expr cdiv_q(Fmpz_expr, Fmpz_expr) Fmpz_expr cdiv_q(Fmpz_expr, T:is_integer) Fmpz_expr tdiv_q(Fmpz_expr, Fmpz_expr) Fmpz_expr tdiv_q(Fmpz_expr, T:is_integer) Fmpz_expr divexact(Fmpz_expr, Fmpz_expr) Fmpz_expr divexact(Fmpz_expr, T:is_integer) Fmpz_expr fdiv_r(Fmpz_expr, Fmpz_expr) Fmpz_expr tdiv_q_2exp(Fmpz_expr, T:is_unsigned_integer) Fmpz_expr fdiv_r_2exp(Fmpz_expr, T:is_unsigned_integer) Fmpz_expr divexact2(Fmpz_expr g, ulong x, ulong y) Fmpz_expr mul_tdiv_q_2exp(Fmpz_expr g, Fmpz_expr x, ulong exp) Fmpz_expr mul_tdiv_q_2exp(Fmpz_expr g, long x, ulong exp) Ltuple_expr fdiv_qr(Fmpz_expr g, Fmpz_expr h) Ltuple_expr tdiv_qr(Fmpz_expr g, Fmpz_expr h) bool Fmpz_expr::divisible(Fmpz_expr) const bool Fmpz_expr::divisible(T:fits_into_slong) const bool divisible(Fmpz_expr n, Fmpz_expr d) bool divisible(Fmpz_expr n, T:fits_into_slong d) Return if $d$ divides $n$. See \code{fmpz_divisible}. Fmpz_expr powm(Fmpz_expr g, ulong e, Fmpz_expr m) Fmpz_expr powm(Fmpz_expr g, Fmpz_expr e, Fmpz_expr m) Fmpz_expr pow(Fmpz_expr, T:is_unsigned_integer) long clog(Fmpz_expr x, Fmpz_expr b) long clog(Fmpz_expr x, ulong b) long flog(Fmpz_expr x, Fmpz_expr b) long flog(Fmpz_expr x, ulong b) double dlog(Fmpz_expr x) long Fmpz_expr::clog(Fmpz_expr) const long Fmpz_expr::clog(T:is_unsigned_integer) const long Fmpz_expr::flog(Fmpz_expr) const long Fmpz_expr::flog(T:is_unsigned_integer) const double Fmpz_expr::dlog() const Ltuple_expr sqrtmod(Fmpz_expr a, Fmpz_expr b) \code{ltupleref(b, N) = sqrtmod(A, B)} has the same effect as \code{b = fmpz_sqrtmod(n, a, b)}, where \code{n, a, b} are the underlying \code{fmpz_t} of \code{N, A, B}. Ltuple_expr sqrtrem(Fmpz_expr g) Fmpz_expr sqrt(Fmpz_expr) bool Fmpz_expr::is_square() const Return if this expression evaluates to a square integer. Fmpz_expr root(Fmpz_expr, T:fits_into_slong) Fmpz_expr rfac(Fmpz_expr, T:is_unsigned_integer) Fmpz_expr fac(T:is_unsigned_integer) Fmpz_expr fib(T:is_unsigned_integer) Fmpz_expr bin(T:is_unsigned_integer, U:is_unsigned_integer) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Greatest common divisor +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr gcdinv(Fmpz_expr f, Fmpz_expr g) Ltuple_expr xgcd(Fmpz_expr f, Fmpz_expr g) Fmpz_expr gcd(Fmpz_expr, Fmpz_expr) Fmpz_expr lcm(Fmpz_expr, Fmpz_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Modular arithmetic +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr remove(Fmpzxx a, Fmpzxx b) int jacobi(Fmpz_expr a, Fmpz_expr p) int Fmpz_expr::jacobi(Fmpz_expr) const Fmpz_expr invmod(Fmpz_expr, Fmpz_expr) Fmpz_expr negmod(Fmpz_expr, Fmpz_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Bit packing and unpacking Beware that argument orders are different relative to the C interface, to facilitate default arguments. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static Fmpz_expr fmpzxx::bit_unpack(const vector& v, mp_bitcnt_t bits, mp_bitcnt_t shift = 0, int negate = 0, bool borrow = false) static Fmpz_expr fmpzxx::bit_unpack_unsigned(const vector& v, mp_bitcnt_t bits, mp_bitcnt_t shift = 0) Unpack an \code{fmpzxx} from \code{v}. bool bit_pack(std::vector& v, mp_bitcnt_t bits, Fmpz_expr, mp_bitcnt_t shift = 0, int negate = 0, bool borrow = false) Pack an \code{fmpzxx} to \code{v}. The vector \code{v} is required to be of sufficient size. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Logic operations Binary logic operators \code{& | ^} (and, or, xor) are also overloaded (implemented when both arguments are \code{Fmpz_expr}). +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Fmpz_target::clrbit(ulong i) void Fmpz_target::combit(ulong i) int Fmpz_expr::popcnt() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Chinese remaindering +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr Fmpz_expr::CRT(Fmpz_expr, T:is_unsigned_integer, T:is_unsigned_integer, bool) const Fmpz_expr CRT(Fmpz_expr, Fmpz_expr, T:is_unsigned_integer, T:is_unsigned_integer, bool) See \code{fmpz_CRT_ui}. fmpz_combxx::fmpz_combxx(const std::vector& primes) The class \code{fmpz_combxx} wraps both \code{fmpz_comb_t} and \code{fmpz_comb_temp_t}. The argument \code{primes} is the vector of moduli to use, and must not be deallocated before the newly constructed \code{fmpz_combxx}. Note that the internal \code{fmpz_comb_temp_t} structure may be modified even on constant instances of \code{fmpz_combxx}. void multi_mod(std::vector& out, Fmpz_expr in, const fmpz_combxx& comb) Reduce \code{in} modulo the primes stored in \code{comb}, and store the results in \code{out}. The vector \code{out} must have sufficient size, and its size will not be changed. Fmpz_expr multi_CRT(const std::vector& residues, const fmpz_combxx comb, bool sign) Reconstruct an integer from its residues. See \code{fmpz_multi_CRT_ui}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Primality testing +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpz_expr::is_probabprime() const bool Fmpz_expr::is_prime_pseudosquare() const ******************************************************************************* fmpz\_factorxx ******************************************************************************* fmpz_factorxx::fmpz_factorxx() Initialise an empty factorisation. fmpz_factorxx::fmpz_factorxx(const fmpz_factorxx& o) Copy a factorisation. bool fmpz_factorxx::operator==(const fmpz_factorxx&) Compare two factorisations. ulong fmpz_factorxx::size() const Return the number of stored factors. ulong fmpz_factorxx::exp(slong i) const ulong& fmpz_factorxx::exp(slong i) Obtain the exponent of the ith factor. fmpzxx_srcref fmpz_factorxx::p(slong i) const fmpzxx_ref fmpz_factorxx::p(slong i) Obtain the ith factor. int fmpz_factorxx::sign() const int& fmpz_factorxx::sign() Obtain the sign of the factored expression. void fmpz_factorxx::set_factor(Fmpz_expr) void fmpz_factorxx::set_factor(T:fits_into_slong) bool fmpz_factorxx::set_factor_trial_range(Fmpz_expr, ulong, ulong) bool fmpz_factorxx::set_factor_pp1(Fmpz_expr, ulong, ulong, ulong) Factorise an integer and store its factors. See \code{fmpz_factor} etc. Fmpz_expr fmpz_factorxx::expand() const Fmpz_expr fmpz_factorxx::expand_iterative() const Fmpz_expr fmpz_factorxx::expand_multiexp() const fmpz_factorxx factor(Fmpz_expr) fmpz_factorxx factor(T:fits_into_slong) Ltuple_expr factor_trial_range(Fmpz_expr) fmpz_factorxx factor_pp1(Fmpz_expr) void print(const fmpz_factorxx&) ******************************************************************************* fmpz\_matxx The class \code{fmpz_matxx} wraps \code{fmpz_mat_t}, and so represents matrices with coefficients in $\mathbf{Z}$. Owing to the design of \code{fmpz_mat_t}, the use of \code{fmpz_matxx} has a number of peculiarities. \begin{itemize} \item Matrix assignment does not automatically resize. This also includes assigning (and thus evaluating) a lazy expression to an ordinary matrix. As a consequence, the evaluation code cannot use temporary merging, and may thus create more temporaries than a similar expression involving non-matrices. \item Several functions operating on \code{fmpz_mat_t} do not allow aliasing. The flintxx layer just passes expressions on to the C layer, so it is the responsibility of the user to avoid aliasing where it is disallowed. Note that since no temporary merging is used with matrices, aliases are never introduced by the evaluation code. \end{itemize} ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Not yet split into subsections +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong Fmpz_mat_expr::rank() const Fmpz_expr Fmpz_mat_expr::det_modular_given_divisor( Fmpz_mat_expr, Fmpz_expr) const See \code{fmpz_mat_det_modular_given_divisor}. Fmpz_mat_target Fmpz_mat_target::operator=(T:fits_into_slong) Fmpz_mat_target Fmpz_mat_target::operator=(const char*) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ C++ particulars +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong Fmpz_mat_expr::rows() const slong Fmpz_mat_expr::cols() const Obtain the number of rows/columns in this matrix. These functions never cause evaluation (the matrix size is computed from the operations in the expression template and the size of the input matrices). Fmpz_mat_expr::unary operation() const The following unary functions are made available as member functions: \code{sqr}, \code{charpoly}, \code{det}, \code{det_bareiss}, \code{det_bound}, \code{det_cofactor}, \code{det_divisor}, \code{trace}, \code{transpose}. Fmpz_mat_expr::binary operation(??) const The following binary functions are made available as member functions: \code{det_modular}, \code{det_modular_accelerated}, \code{divexact}, \code{mul_classical}, \code{mul_multi_mod}, \code{pow}, code{solve}, \code{solve_bound}, \code{solve_cramer}, \code{solve_dixon}, \code{solve_fflu}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmpz_matxx::fmpz_matxx(slong i, slong j) Allocate a matrix of size $i \times j$. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic assignment and manipulation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ?? Fmpz_mat_expr::at(T:fits_into_slong, U:fits_into_slong) const Unified coefficient access to the matrix entries. void Fmpq_mat_target::set_zero() void Fmpq_mat_target::set_one() static fmpq_matxx fmpq_matxx::zero(slong rows, slong cols) static fmpq_matxx fmpq_matxx::one(slong rows, slong cols) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ print(Fmpz_mat_expr) print(FILE*, Fmpz_mat_expr) print_pretty(Fmpz_mat_expr) print_pretty(FILE*, Fmpz_mat_expr) read(Fmpz_mat_target) read(FILE*, Fmpz_mat_target) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparison The overloaded operator \code{==} can be used for equality testing. Additionally, we have the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpz_mat_expr::is_zero() const bool Fmpz_mat_expr::is_empty() const bool Fmpz_mat_expr::is_quare() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Conversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static fmpz_matxx fmpz_matxx::lift(Nmod_mat_expr) static fmpz_matxx fmpz_matxx::lift_unsigned(Nmod_mat_expr) See \code{fmpz_mat_set_nmod_mat} and \code{fmpz_mat_set_nmod_mat_unsigned}. static fmpz_matxx fmpz_matxx::reduce(Fmpq_mat_expr, Fmz_expr) See \code{fmpq_mat_get_fmpz_mat_mod_fmpz}. static fmpz_matxx fmpz_matxx::from_integral_fraction(Fmpq_mat_expr) void Fmpz_mat_target::set_integral_fraction(Fmpq_mat_expr) See \code{fmpq_mat_get_fmpz_mat}. Raises \code{flint_exception} if the argument has non-integer entries. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Randomisation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Fmpz_mat_target::set_randbits(frandxx& state, mp_bitcnt_t bits) void Fmpz_mat_target::set_randtest(frandxx& state, mp_bitcnt_t bits) void Fmpz_mat_target::set_randintrel(frandxx& state, mp_bitcnt_t bits) void Fmpz_mat_target::set_randsimdioph(frandxx& state, mp_bitcnt_t bits, mp_bitcount_t bits2) void Fmpz_mat_target::set_randtrulike(frandxx& state, mp_bitcnt_t bits, ulong q) void Fmpz_mat_target::set_randtrulike2(frandxx& state, mp_bitcnt_t bits, ulong q) void Fmpz_mat_target::set_randajtai(frandxx& state, mp_bitcnt_t bits, double alpha) void Fmpz_mat_target::set_randrank(frandxx& state, slong rank, mp_bitcnt_t bits) void Fmpz_mat_target::set_randdet(frandxx& state, Fmpz_expr d) See \code{fmpz_mat_randbits} etc. static fmpz_matxx fmpz_matxx::randbits(slong r, slong c, frandxx& state, mp_bitcnt_t bits) static fmpz_matxx fmpz_matxx::randtest(slong r, slong c, frandxx& state, mp_bitcnt_t bits) static fmpz_matxx fmpz_matxx::randintrel(slong r, slong c, frandxx& state, mp_bitcnt_t bits) static fmpz_matxx fmpz_matxx::randsimdioph(slong r, slong c, frandxx& state, mp_bitcnt_t bits, mp_bitcount_t bits2) static fmpz_matxx fmpz_matxx::randtrulike(slong r, slong c, frandxx& state, mp_bitcnt_t bits, ulong q) static fmpz_matxx fmpz_matxx::randtrulike2(slong r, slong c, frandxx& state, mp_bitcnt_t bits, ulong q) static fmpz_matxx fmpz_matxx::randajtai(slong r, slong c, frandxx& state, mp_bitcnt_t bits, double alpha) static fmpz_matxx fmpz_matxx::randrank(slong r, slong c, frandxx& state, slong rank, mp_bitcnt_t bits) static fmpz_matxx fmpz_matxx::randdet(slong r, slong c, frandxx& state, Fmpz_expr d) Static versions of the above, where the first two arguments specify the dimensions of the matrix. int Fmpz_mat_target::set_randpermdiag(frandxx& state, Vec v) See \code{fmpz_mat_randpermdiag}. The type \code{vec} must have methods \code{_array()} and \code{size()} similar to \code{fmpz_vecxx}. void Fmpz_mat_target::apply_randops(frandxx& state, slong count) See \code{fmpz_mat_randops}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Transpose +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr transpose(Fmpz_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Modular reduction and reconstruction To reduce a single matrix modulo a word-sized modulus, see \code{nmod_matxx::reduce}. We use a special class \code{nmod_mat_vector} to represent a vector of matrices reduced with respect to differing moduli. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mat_expr Fmpz_mat_expr::CRT(Fmpz_expr, Nmod_mat_expr, bool) Fmpz_mat_expr CRT(Fmpz_mat_expr, Fmpz_expr, Nmod_mat_expr, bool) See \code{fmpz_mat_CRT_ui}. nmod_mat_vector::nmod_mat_vector(slong rows, slong cols, const std::vector& primes) Initialize a vector of matrices with dimensions given by \code{rows}, \code{cols} and moduli given by \code{primes}. nmod_matxx_ref nmod_mat_vector::operator[](std::size_t idx) nmod_matxx_srcref nmod_mat_vector::operator[](std::size_t idx) const Obtain a reference to one of the stored matrices. std::size_t nmod_mat_vector::size() const Obtain the number of stored matrices. void nmod_mat_vector::set_multi_mod(Fmpz_mat_expr m) Reduce \code{m} modulo each of the primes stored in this vector, and store the results. See \code{fmpz_mat_multi_mod_ui}. void nmod_mat_vector::set_multi_mod_precomp(Fmpz_mat_expr m, const fmpz_combxx& comb) Reduce \code{m} modulo each of the primes stored in this vector, and store the results. Use precomputed data in \code{comp}. See \code{fmpz_mat_multi_mod_ui_precomp}. nmod_mat_vector multi_mod(Fmpz_mat_expr m, const std::vector& primes) nmod_mat_vector multi_mod_precomp(Fmpz_mat_expr m, const std::vector& primes, const fmpz_combxx& comb) Convenience functions combining the allocation of memory and modular reduction. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Arithmetic The overloaded operators \code{+ - *} can be used for ordinary matrix-matrix and matrix-scalar arithmetic. Additionally, we provide the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mat_expr divexact(Fmpz_mat_expr, Fmpz_expr) Fmpz_mat_expr divexact(Fmpz_mat_expr, T:is_integer) Fmpz_mat_expr mul_classical(Fmpz_mat_expr, Fmpz_mat_expr) Fmpz_mat_expr mul_multi_mod(Fmpz_mat_expr, Fmpz_mat_expr) Fmpz_expr sqr(Fmpz_mat_expr) Fmpz_mat_expr pow(Fmpz_mat_expr, T:is_unsigned_integer) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Inverse +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr inv(Fmpz_mat_expr) \code{ltupleref(b, M, D) = inv(A)} has the same effect as \code{b = fmpz_mat_inv(m, d, a)}, where \code{m, d, a} are the underlying C objects corresponding to \code{M, D, A}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Trace +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mat_expr trace(Fmpz_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Determinant +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr det(Fmpz_mat_expr) Fmpz_expr det_cofactor(Fmpz_mat_expr) Fmpz_expr det_bareiss(Fmpz_mat_expr) Fmpz_expr det_divisor(Fmpz_mat_expr) Fmpz_expr det_bound(Fmpz_mat_expr) Fmpz_expr det_modular(Fmpz_mat_expr, bool proved) Fmpz_expr det_modular_accelerated(Fmpz_mat_expr, bool proved) Fmpz_expr det_modular_given_divisor(Fmpz_mat_expr, Fmpz_expr, bool proved) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Characteristic polynomial +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr charpoly(Fmpz_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Rank +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong rank(Fmpz_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Non-singular solving +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr solve( Fmpz_mat_expr B, Fmpz_mat_expr X) Ltuple_expr solve_dixon( Fmpz_mat_expr B, Fmpz_mat_expr X) Ltuple_expr solve_cramer( Fmpz_mat_expr B, Fmpz_mat_expr X) Ltuple_expr solve_fflu( Fmpz_mat_expr B, Fmpz_mat_expr X) \code{ltupleref(w, M, D) = solve(B, X)} has the same effect as \code{w = fmpz_mat_solve(m, d, b, x)}, where \code{m, d, b, x} are the underlying C objects corresponding to \code{M, D, B, X}. Similarly for the other functions. Ltuple_expr solve_bound( Fmpz_mat_expr B, Fmpz_mat_expr X) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Row reduction Beware that compared to the C interface, the flintxx row reduction interface changes some argument orders. This is to facilitate default arguments. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong find_pivot_any(Fmpz_mat_expr, slong, slong, slong) See \code{fmpz_mat_find_pivot_any}. Ltuple_expr fflu(Fmpz_mat_expr A, permxx* perm = 0, bool rankcheck = false) See \code{fmpz_mat_fflu}. Ltuple_expr rref(Fmpz_mat_expr A) See \code{fmpz_mat_rref}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Modular gaussian elimination +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong Fmpz_mat_target::set_rref_mod(Fmpz_expr n, permxx* perm = 0) See \code{fmpz_mat_rref_mod}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nullspace +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr nullspace(Fmpz_mat_expr A) \code{ltupleref(n, B) = nullspace(A)} has the same effect as \code{n = fmpz_mat_nullspace(b, a)}, where \code{b, a} are the underlying \code{fmpz_mat_t} corresponding to \code{B, A}. ******************************************************************************* fmpz\_polyxx ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ C++ particulars +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr::unary operation() const The following unary functions are made available as member functions: \code{derivative}, \code{primitive_part}, \code{sqr}, \code{sqr_classical}, \code{sqr_karatsuba}, \code{sqr_KS}, \code{sqrt}, \code{sqrt_classical}, \code{content}, \code{height}, \code{bound_roots}, \code{twonorm}. Fmpz_poly_expr::binary operation(??) const The following binary functions are made available as member functions: \code{compose_divconquer}, \code{compose_horner}, \code{div_basecase}, \code{div_divconquer}, \code{divexact}, \code{divrem}, \code{divrem_basecase}, \code{divrem_divconquer}, \code{div_root}, \code{evaluate_divconquer}, \code{evaluate_horner}, \code{fdiv_2exp}, \code{gcd}, \code{gcd_heuristic}, \code{gcd_modular}, \code{gcd_subresultant}, \code{inv_series}, \code{inv_series_newton}, \code{lcm}, \code{mul_2exp}, \code{mul_classical}, \code{mul_karatsuba}, \code{mul_KS}, \code{mulmid_classical}, \code{mul_SS}, \code{shift_left}, \code{shift_right}, \code{pow}, \code{pow_addchains}, \code{pow_binexp}, \code{pow_binomial}, \code{pow_multinomial}, \code{pseudo_div}, \code{pseudo_divrem}, \code{pseudo_divrem_basecase}, \code{pseudo_divrem_cohen}, \code{pseudo_divrem_divconquer}, \code{pseudo_rem}, \code{pseudo_rem_cohen}, \code{resultant}, \code{reverse}, \code{revert_series}, \code{revert_series_lagrange}, \code{revert_series_lagrange_fast}, \code{revert_series_newton}, \code{smod}, \code{sqrlow}, \code{sqrlow_classical}, \code{sqrlow_karatsuba_n}, \code{sqrlow_KS}, \code{taylor_shift}, \code{taylor_shift_horner}, \code{taylor_shift_divconquer}, \code{tdiv}, \code{tdiv_2exp}, \code{xgcd}, \code{xgcd_modular}, \code{divides}. Fmpz_poly_expr::ternary operation(??, ??) const The following ternary functions are made available as member functions: \code{compose_series}, \code{compose_series_brent_kung}, \code{compose_horner}, \code{div_series}, \code{mulhigh_classical}, \code{mulhigh_karatsuba_n}, \code{mulhigh_n}, \code{mullow}, \code{mullow_classical}, \code{mullow_karatsuba_n}, \code{mullow_KS}, \code{mullow_SS}, \code{pow_trunc}. Fmpz_poly_expr Fmpz_poly_expr::operator()(Fmpz_poly_expr) const Fmpz_poly_expr Fmpz_poly_expr::operator()(Fmpz_expr) const Overloaded \code{operator()} for evaluation or composition. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmpz_polyxx::fmpz_polyxx() fmpz_polyxx::fmpz_polyxx(slong alloc) See \code{fmpz_poly_init2}. fmpz_polyxx::fmpz_polyxx(const char* str) See \code{fmpz_poly_set_str}. void Fmpz_poly_target realloc(slong alloc) void Fmpz_poly_target::fit_length(slong len) void Fmpz_poly_target::_normalise() void Fmpz_poly_target::_set_length(slong len) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Polynomial parameters +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong Fmpz_poly_expr::length() const slong Fmpz_poly_expr::degree() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Assignment and basic manipulation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_target Fmpz_poly_target::operator=(T:is_integer) Fmpz_poly_target Fmpz_poly_target::operator=(Fmpz_expr) Fmpz_poly_target Fmpz_poly_target::operator=(const char*) std::string Fmpz_poly_expr::to_string() const std::string Fmpz_poly_expr::pretty(const char* x) const See \code{fmpz_poly_get_str_pretty}. void Fmpz_poly_target::set_zero() void Fmpz_poly_target::set_one() static fmpz_polyxx fmpz_polyxx::zero() static fmpz_polyxx fmpz_polyxx::one() void Fmpz_poly_target::zero_coeffs(slong i, slong j) Fmpz_poly_expr reverse(Fmpz_poly_expr, T:fits_into_slong) void Fmpz_poly_target::truncate(slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Randomisation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static fmpz_polyxx fmpz_polyxx::randtest( frandxx& state, slong len, mp_bitcnt_t bits) static fmpz_polyxx fmpz_polyxx::randtest_unsigned( frandxx& state, slong len, mp_bitcnt_t bits) static fmpz_polyxx fmpz_polyxx::randtest_not_zero( frandxx& state, slong len, mp_bitcnt_t bits) See \code{fmpz_poly_randtest} etc. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Getting and setting coefficients +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr Fmpz_poly_expr::get_coeff(slong n) Obtain coefficient $n$ of the polynomial. It is valid to call this with $n$ greater than the degree, in which case zero is returned. void Fmpz_poly_target::set_coeff(slong n, Fmpz_expr) void Fmpz_poly_target::set_coeff(slong n, T:is_integer) ?? Fmpz_poly_expr::coeff(slong n) const Unified coefficient access for coefficient $n$. The result is undefined if $n$ is greater than the degree of the polynomial (or negative). If the leading coefficient of the polynomial is set to zero in this way, a call to \code{_normalise} is necessary. ?? Fmpz_poly_expr::lead() const Unified coefficient access for the leading coefficient. The result is undefined if the length of the polynomial is zero. If this is used to set the leading coefficient to zero, call to \code{_normalise} is necessary. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparison As usual, \code{fmpz_polyxx} can be compared using \code{operator==}. Additionally, the following functions are provided. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpz_poly_expr::is_one() const bool Fmpz_poly_expr::is_zero() const bool Fmpz_poly_expr::is_unit() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Addition and subtraction The overloaded operators \code{+ -} can be used for addition, subtraction and negation. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Scalar multiplication and division The overloaded operators \code{* /} can be used for scalar multiplication and division, and the operator \code{\%} for remaindering. For finer control, the following functions are provided. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr mul_2exp(Fmpz_poly_expr, T:is_unsigned_integer) Fmpz_poly_expr fdiv_2exp(Fmpz_poly_expr, T:is_unsigned_integer) Fmpz_poly_expr tdiv(Fmpz_poly_expr, Fmpz_expr) Fmpz_poly_expr tdiv(Fmpz_poly_expr, T:is_integer) Fmpz_poly_expr divexact(Fmpz_poly_expr, Fmpz_expr) Fmpz_poly_expr divexact(Fmpz_poly_expr, T:is_integer) Fmpz_poly_expr smod(Fmpz_poly_expr, Fmpz_expr) See \code{fmpz_poly_scalar_smod_fmpz}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Bit packing +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr bit_pack(Fmpz_poly_expr, T:fits_into_mp_bitcnt_t) static Fmpz_poly_expr fmpz_polyxx::bit_unpack(Fmpz_expr, T:fits_into_mp_bitcnt_t) static Fmpz_poly_expr fmpz_polyxx::bit_unpack_unsigned( Fmpz_expr, traits::fits_into_mp_bitcnt_t) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Multiplication The overloaded operator \code{*} can also be used for poly-poly multiplication. Additionally, the following functions are provided. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr mul_classical(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr mulmid_classical(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr mul_karatsuba(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr mul_SS(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr mul_KS(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr mullow(Fmpz_poly_expr, Fmpz_poly_expr, slong) Fmpz_poly_expr mullow_classical(Fmpz_poly_expr, Fmpz_poly_expr, slong) Fmpz_poly_expr mullow_karatsuba_n(Fmpz_poly_expr, Fmpz_poly_expr, slong) Fmpz_poly_expr mullow_KS(Fmpz_poly_expr, Fmpz_poly_expr, slong) Fmpz_poly_expr mullow_SS(Fmpz_poly_expr, Fmpz_poly_expr, slong) Fmpz_poly_expr mulhigh_n(Fmpz_poly_expr, Fmpz_poly_expr, slong) Fmpz_poly_expr mulhigh_classical(Fmpz_poly_expr, Fmpz_poly_expr, slong) Fmpz_poly_expr mulhigh_karatsuba_n(Fmpz_poly_expr, Fmpz_poly_expr, slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Squaring +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr sqr(Fmpz_poly_expr) Fmpz_poly_expr sqr_KS(Fmpz_poly_expr) Fmpz_poly_expr sqr_karatsuba(Fmpz_poly_expr) Fmpz_poly_expr sqr_classical(Fmpz_poly_expr) Fmpz_poly_expr sqrlow(Fmpz_poly_expr, T:fits_into_slong n) Fmpz_poly_expr sqrlow_classical(Fmpz_poly_expr, T:fits_into_slong n) Fmpz_poly_expr sqrlow_KS(Fmpz_poly_expr, T:fits_into_slong n) Fmpz_poly_expr sqrlow_karatsuba_n(Fmpz_poly_expr, T:fits_into_slong n) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Powering +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr pow(Fmpz_poly_expr, T:is_unsigned_integer) Fmpz_poly_expr pow_multinomial(Fmpz_poly_expr, T:is_unsigned_integer) Fmpz_poly_expr pow_binomial(Fmpz_poly_expr, T:is_unsigned_integer) Fmpz_poly_expr pow_binexp(Fmpz_poly_expr, T:is_unsigned_integer) Fmpz_poly_expr pow_addchains(Fmpz_poly_expr, T:is_unsigned_integer) Fmpz_poly_expr pow_trunc(Fmpz_poly_expr, ulong e, slong n) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Shifting +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr shift_left(Fmpz_poly_expr, T:fits_into_slong) Fmpz_poly_expr shift_right(Fmpz_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Bit sizes and norms +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr height(Fmpz_poly_expr) Fmpz_expr twonorm(Fmpz_poly_expr) ulong Fmpz_poly_expr::max_limbs() const slong Fmpz_poly_expr::max_bits() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Greatest common divisor +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr gcd(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr gcd_subresultant(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr gcd_heuristic(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr gcd_modular(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr lcm(Fmpz_poly_expr, Fmpz_poly_expr) Ltuple_expr xgcd(Fmpz_poly_expr f, Fmpz_poly_expr g) Ltuple_expr xgcd_modular(Fmpz_poly_expr f, Fmpz_poly_expr g) \code{ltupleref(N, Q, R) = xgcd(F, G)} has the same effect as \code{fmpz_poly_xgcd(n, q, r, f, g)} where \code{n, q, r, f, g} are the underlying C objects. Fmpz_expr resultant(Fmpz_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Gaussian content +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr content(Fmpz_poly_expr) Fmpz_poly_expr primitive_part(Fmpz_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Square-free +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpz_poly_expr::is_squarefree() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Euclidean division The overloaded operators \code{/ %} can be used for euclidean division and remainder. Additionally, the following functions are provided. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr div_basecase(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr div_divconquer(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr rem_basecase(Fmpz_poly_expr, Fmpz_poly_expr) Ltuple_expr divrem(Fmpz_poly_expr A, Fmpz_poly_expr B) Ltuple_expr divrem_basecase(Fmpz_poly_expr A, Fmpz_poly_expr B) Ltuple_expr divrem_divconquer( Fmpz_poly_expr A, Fmpz_poly_expr B) \code{ltupleref(Q, R) = divrem(A, B)} has the same effect as \code{fmpz_poly_divrem(q, r, a, b)}, where \code{q, r, a, b} are the underlying \code{fmpz_poly_t} corresponding to \code{Q, R, A, B}. Fmpz_poly_expr div_root(Fmpz_poly_expr, Fmpz_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Divisibility testing +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr divides(Fmpz_poly_expr A, Fmpz_poly_expr B) \code{ltupleref(d, Q) = divides(A, B)} sets \code{d} to \code{true} and \code{Q} to \code{A/B} if \code{B} divides \code{A}, and else sets \code{d} to \code{false}. See \code{fmpz_poly_divides}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Power series division +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr inv_series_newton(Fmpz_poly_expr, T:fits_into_slong) Fmpz_poly_expr inv_series(Fmpz_poly_expr, T:fits_into_slong) Fmpz_poly_expr div_series(Fmpz_poly_expr, Fmpz_poly_expr, slong n) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Pseudo division +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr pseudo_divrem( Fmpz_poly_expr A, Fmpz_poly_expr B) Ltuple_expr pseudo_divrem_basecase( Fmpz_poly_expr A, Fmpz_poly_expr B) Ltuple_expr pseudo_divrem_divconquer( Fmpz_poly_expr A, Fmpz_poly_expr B) \code{ltupleref(Q, R, d) = pseudo_divrem(A, B)} has the same effect as\\ \code{fmpz_poly_pseudo_divrem(q, r, &d, a, b)}, where \code{q, r, a, b} are the underlying \code{fmpz_poly_t} corresponding to \code{Q, R, A, B}. Ltuple_expr pseudo_divrem_cohen(Fmpz_poly_expr A, Fmpz_poly_expr B) \code{ltupleref(Q, R) = pseudo_divrem_cohen(A, B)} has the same effect as\\ \code{fmpz_poly_pseudo_divrem_cohen(q, r, a, b)}, where \code{q, r, a, b} are the underlying \code{fmpz_poly_t} corresponding to \code{Q, R, A, B}. Ltuple_expr pseudo_div(Fmpz_poly_expr A, Fmpz_poly_expr B) Ltuple_expr pseudo_rem(Fmpz_poly_expr A, Fmpz_poly_expr B) \code{ltupleref(Q, d) = pseudo_div(A, B)} has the same effect as \code{fmpz_poly_pseudo_div(q, &d, a, b)}, where \code{q, a, b} are the underlying \code{fmpz_poly_t} corresponding to \code{Q, A, B}. Fmpz_poly_expr pseudorem_cohen(Fmpz_poly_expr, Fmpz_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Derivative +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr derivative(Fmpz_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Evaluation The overloaded \code{operator()} can be used for evaluation. Additionally, the following functions are provided. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr evaluate(Fmpz_poly_expr, Fmpz_expr) Fmpz_vec_expr evaluate(Fmpz_poly_expr, Fmpz_vec_expr) Fmpz_expr evaluate_horner(Fmpz_poly_expr, Fmpz_expr) Fmpz_expr evaluate_divconquer(Fmpz_poly_expr, Fmpz_expr) mp_limb_t evaluate_mod(Fmpz_poly_expr p, mp_limb_t x, mp_limb_t n) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Interpolation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static Fmpz_poly_expr fmpz_polyxx::interpolate( Fmpz_vec_expr xs, Fmpz_vec_expr ys) See \code{fmpz_poly_interpolate_fmpz_vec}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Composition. The overloaded \code{operator()} can be used for composition. Additionally, the following functions are provided. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr compose(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr compose_horner(Fmpz_poly_expr, Fmpz_poly_expr) Fmpz_poly_expr compose_divconquer(Fmpz_poly_expr, Fmpz_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Taylor shift +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr taylor_shift(Fmpz_poly_expr, Fmpz_expr) Fmpz_poly_expr taylor_shift_horner(Fmpz_poly_expr, Fmpz_expr) Fmpz_poly_expr taylor_shift_divconquer(Fmpz_poly_expr, Fmpz_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Power series composition +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr compose_series(Fmpz_poly_expr, Fmpz_poly_expr, slong) Fmpz_poly_expr compose_series_horner(Fmpz_poly_expr, Fmpz_poly_expr, slong) Fmpz_poly_expr compose_series_brent_kung(Fmpz_poly_expr, Fmpz_poly_expr, slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Power series reversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr revert_series(Fmpz_poly_expr, T:fits_into_slong) Fmpz_poly_expr revert_series_newton(Fmpz_poly_expr, T:fits_into_slong) Fmpz_poly_expr revert_series_lagrange(Fmpz_poly_expr, T:fits_into_slong) Fmpz_poly_expr revert_series_lagrange_fast(Fmpz_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Square root +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr sqrt(Fmpz_poly_expr p) Fmpz_poly_expr sqrt_classical(Fmpz_poly_expr p) Compute the square root of \code{p}, provided \code{p} is a perfect square. Else raise \code{flint_exception}. See \code{fmpz_poly_sqrt}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Signature +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Fmpz_poly_expr::signature(slong& r1, slong& r2) const See \code{fmpz_poly_signature}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Hensel lifting +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr hensel_lift( Fmpz_poly_expr f, Fmpz_poly_expr g, Fmpz_poly_expr h, Fmpz_poly_expr a, Fmpz_poly_expr b, Fmpz_expr p, Fmpz_expr p1) Ltuple_expr hensel_lift_without_inverse( Fmpz_poly_expr f, Fmpz_poly_expr g, Fmpz_poly_expr h, Fmpz_poly_expr a, Fmpz_poly_expr b, Fmpz_expr p, Fmpz_expr p1) Ltuple_expr hensel_lift_only_inverse( Fmpz_poly_expr G, Fmpz_poly_expr H, Fmpz_poly_expr a, Fmpz_poly_expr b, Fmpz_expr p, Fmpz_expr p1) See \code{fmpz_poly_hensel_lift} etc. fmpz_poly_factorxx::set_hensel_lift_once(Fmpz_poly_expr, const nmod_poly_factorxx&, slong) fmpz_poly_factorxx hensel_lift_once(Fmpz_poly_expr, const nmod_poly_factorxx&, slong) See \code{fmpz_poly_hensel_lift_once}. Note that these two functions are defined in the \code{fmpz_factorxx} module. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ print(Fmpz_poly_expr) print(FILE*, Fmpz_poly_expr) print_pretty(Fmpz_poly_expr, const char* var) print_pretty(FILE*, Fmpz_poly_expr, const char* var) read(Fmpz_poly_target) read(FILE*, Fmpz_poly_target) read_pretty(Fmpz_poly_target, const char* var) read_pretty(FILE*, Fmpz_poly_target, const char* var) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Modular reduction and reconstruction For modular reduction, see \code{nmod_polyxx::reduce}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr Fmpz_poly_expr::CRT(Fmpz_expr, Nmod_poly_expr, bool) Fmpz_poly_expr CRT(Fmpz_poly_expr, Fmpz_expr, Nmod_poly_expr, bool) See \code{fmpz_poly_CRT_ui}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Products +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static Fmpz_poly_expr fmpz_polyxx::product_roots(Fmpz_vec_expr xs) See \code{fmpz_poly_product_roots_fmpz_vec}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Roots +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr bound_roots(Fmpz_poly_expr p) ******************************************************************************* fmpz\_poly\_factorxx ******************************************************************************* bool fmpz_poly_factorxx::operator==(const fmpz_poly_factorxx&) Compare two factorisations. ulong fmpz_poly_factorxx::size() const Return the number of stored factors. slong fmpz_poly_factorxx::exp(slong i) const slong& fmpz_poly_factorxx::exp(slong i) Obtain the exponent of the ith factor. fmpz_polyxx_srcref fmpz_poly_factorxx::p(slong i) const fmpz_polyxx_ref fmpz_poly_factorxx::p(slong i) Obtain the ith factor. fmpzxx_srcref fmpz_poly_factorxx::content() const fmpzxx_ref fmpz_poly_factorxx::content() Obtain the content of the factorised polynomial. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmpz_poly_factorxx::fmpz_poly_factorxx() explicit fmpz_poly_factorxx::fmpz_poly_factorxx(slong alloc) Initialise an empty factorisation. fmpz_poly_factorxx::fmpz_poly_factorxx(const fmpz_poly_factorxx& o) Copy a factorisation. void fmpz_poly_factorxx::realloc(slong a) void fmpz_poly_factorxx::fit_length(slong a) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Manipulating factors +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void fmpz_poly_factorxx::insert(Fmpz_poly_expr p, slong e) void fmpz_poly_factorxx::concat(const fmpz_poly_factorxx&) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Factoring algorithms +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void fmpz_poly_factorxx::set_factor_squarefree(Fmpz_poly_expr p) void fmpz_poly_factorxx::set_factor_zassenhaus(Fmpz_poly_expr p) void fmpz_poly_factorxx::set_factor_zassenhaus_recombination( const fmpz_poly_factorxx& lifted_fac, Fmpz_poly_expr F, Fmpz_expr P, slong exp) fmpz_poly_factorxx::factor_squarefree(Fmpz_poly_expr) fmpz_poly_factorxx::factor_zassenhaus(Fmpz_poly_expr) ******************************************************************************* fmpqxx ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ C++ particulars +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ?? Fmpq_expr::num() const ?? Fmpq_expr::den() const Unified coefficient access to numerator and denominator. If this is used to modify the object, a call to \code{canonicalise()} may be necessary. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmpqxx::fmqxx() Initialize to zero. fmpqxx::fmpqxx(Fmpz_src num, Fmpz_src den) fmpqxx::fmpqxx(T:fits_into_slong num, U:is_unsigned_integer den) Initialize from numerator \code{num} and denominator \code{den}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Canonicalisation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Fmpq_target::canonicalise() bool Fmpq_src::is_canonical() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic assignment +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_expr Fmpq_expr::abs() const Fmpq_expr abs(Fmpq_expr) void Fmpq_target::set_zero() void Fmpq_target::set_one() static fmpqxx fmpqxx::zero() static fmpqxx fmpqxx::one() +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparison The overloaded relational operators can be used for comparison. Additionally, we have the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpq_expr::is_zero() const bool Fmpq_expr::is_one() const int Fmpq_expr::sgn() const mp_bitcnt_t Fmpq_expr::height_bits() const Fmpz_expr Fmpq_expr::height() const mp_bitcnt_t height_bits(Fmpq_expr) Fmpq_expr height(Fmpq_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Conversion Conversion can be done using the assignment operator, and through the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static fmpqxx fmpqxx::frac(const T& t, const U& u) Same as \code{fmpqxx res;res.set_frac(t, u)}. static fmpqxx fmpqxx::integer(const T& t) Same as \code{fmpqxx res;res.set_integer(t)}. void Fmpq_target::set_frac(const T& t, const U& u) \code{f.set_frac(t, u)} has the same effect as \code{f.num() = t;f.den() = u;f.canonicalise()}. void Fmpq_target::set_integer(const T& t) \code{f.set_integer(t)} has the same effect as \code{f.num() = t;f.den() = 1u}; std::string Fmpq_expr::to_string(int base = 10) const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int print(Fmpq_expr) int print(FILE*, Fmpq_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Random number generation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static fmpqxx fmpqxx::randbits(frandxx& state) static fmpqxx fmpqxx::randtest(frandxx& state) static fmpqxx fmpqxx::randtest_not_zero(frandxx& state) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Arithmetic The overloaded operators \code{+ - * /} can be used for arithmetic. Additionally, we provide the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_expr Fmpq_expr::inv() const Fmpq_expr Fmpq_expr::pow(T:fits_into_slong) const Fmpq_expr inv(Fmpq_expr) Fmpq_expr pow(Fmpq_expr, T:fits_into_slong) Fmpq_expr operator<<(Fmpq_expr, T:is_integer) Fmpq_expr operator>>(Fmpq_expr, T:is_integer) Shift operators are overloaded. See \code{fmpq_div_2exp} and \code{fmpq_mul_2exp}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Modular reduction and rational reconstruction +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_expr operator%(Fmpq_expr, Fmpz_expr) See \code{fmpq_mod_fmpz}. The modular reduction operator may raise a \code{flint_exception} if modular inversion is not possible. static Fmpq_expr fmpqxx::reconstruct(Fmpz_expr a, Fmpz_expr m, Fmpz_expr N, Fmpz_expr D) static Fmpq_expr fmpqxx::reconstruct(Fmpz_expr a, Fmpz_expr m) Rational reconstruction. May raise a \code{flint_exception} if reconstruction is not possible. See \code{fmpq_reconstruct_fmpz} and \code{fmpq_reconstruct_fmpz2}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Rational enumeration +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_expr Fmpq_expr::next_minimal() const Fmpq_expr Fmpq_expr::next_signed_minimal() const Fmpq_expr Fmpq_expr::next_calkin_wilf() const Fmpq_expr Fmpq_expr::next_signed_calkin_wilf() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Continued fractions +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong Fmpq_expr::cfrac_bound() const template void Fmpq_target::set_cfrac(const Vec& v, slong n) Set value to a partial fraction expansion. The same conventions apply to \code{v} as in the constructor. template static fmpqxx fmpqxx::from_cfrac(const Vec& v, slong n) Initialize from a partial fraction expansion. \code{v} must be an instance of a class which provides a method \code{_array()} that returns (a pointer to) an array of \code{fmpz}. One such class is \code{fmpz_vecxx}. The array must have size (at least) \code{n}. ******************************************************************************* fmpq\_matxx The class \code{fmpq_matxx} wraps \code{fmpq_mat_t}. Like \code{fmpz_matxx}, many operations on \code{fmpq_matxx} do not support aliasing. The details can be found in the documentation of \code{fmpq_mat_t}. Since \code{fmpq_matxx} does not use temporary merging, evaluation of subexpressions never creates new aliases. ******************************************************************************* Fmpq_mat_expr::unary operation() const The following unary functions are made available as member functions: \code{inv}, \code{transpose}, \code{det}, \code{trace}, \code{numden_entrywise}, \code{numden_rowwise}, \code{numden_colwise}, \code{numden_matwise}, \code{num_rowwise}. Fmpq_mat_expr::binary operation(??) const The following binary functions are made available as member functions: \code{solve_dixon}, \code{solve_fraction_free}, \code{mul_cleared}, \code{mul_direct}. Fmpq_mat_expr operator?(??, ??) Arithmetic operators \code{+ - * /} are overloaded when provided by \code{fmpq_mat_t}. Fmpq_mat_expr operator-(Fmpq_mat_expr) The unary negation operator is overloaded. Fmpq_mat_target Fmpq_mat_target::operator=(Fmpz_mat_expr) See \code{fmpq_mat_set_fmpz_mat}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmpq_matxx::fmpq_matxx(slong m, slong n) See \code{fmpq_mat_init}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int print(Fmpq_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Entry access +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ?? Fmpq_mat_expr::at(slong, slong) const Unified coefficient access to the entries of the matrix. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic assignment +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_mat_expr transpose(Fmpq_poly_mat_expr) void Fmpq_mat_target::set_zero() void Fmpq_mat_target::set_one() static fmpq_matxx fmpq_matxx::zero(slong rows, slong cols) static fmpq_matxx fmpq_matxx::one(slong rows, slong cols) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Random matrix generation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Fmpq_mat_target::set_randtest(frandxx& state, slong len, mp_bitcnt_t) static fmpq_matxx fmpq_matxx::randtest(slong rows, slong cols, frandxx& state, slong len, mp_bitcnt_t) void Fmpq_mat_target::set_randtest_unsigned(frandxx& state, slong len, mp_bitcnt_t) static fmpq_matxx fmpq_matxx::randtest_unsigned(slong rows, slong cols, frandxx& state, slong len, mp_bitcnt_t) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Special matrices +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Fmpq_target::set_hilbert_matrix() Fmpq_mat_expr hilbert_matrix(slong m, slong n) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic properties +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpq_mat_expr::is_zero() const bool Fmpq_mat_expr::is_empty() const bool Fmpq_mat_expr::is_square() const bool Fmpq_mat_expr::is_integral() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Integer matrix conversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static fmpq_matxx fmpq_matxx::frac(Fmpz_mat_expr, Fmpz_expr) void Fmpq_mat_target::set_frac(Fmpz_mat_expr, Fmpz_expr) See \code{fmpq_mat_set_fmpz_mat_div_fmpz}. static fmpq_matxx fmpq_matxx::integer_matrix(Fmpz_mat_expr) See \code{fmpq_mat_set_fmpz_mat}. Fmpz_mat_expr num_rowwise(Fmpq_mat_expr) This has the effect of calling \code{fmpq_mat_get_fmpz_mat_rowwise} with second argument \code{NULL}. Ltuple_expr numden_entrywise(Fmpq_mat_expr) See \code{fmpq_mat_get_fmpz_mat_entrywise}. Ltuple_expr numden_matwise(Fmpq_mat_expr) See \code{fmpq_mat_get_fmpz_mat_matwise}. Ltuple_expr numden_rowwise(Fmpq_mat_expr) See \code{fmpq_mat_get_fmpz_mat_rowwise}. Ltuple_expr numden_colwise(Fmpq_mat_expr) See \code{fmpq_mat_get_fmpz_mat_colwise}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Modular reduction and rational reconstruction To reduce an \code{fmpq_matxx} modulo an \code{fmpzxx} to get an \code{fmpz_matxx}, see \code{fmpz_matxx::reduce}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static fmpq_matxx fmpq_matxx::reconstruct(Fmpz_mat_expr, Fmpz_expr) See \code{fmpq_mat_set_fmpz_mat_mod_fmpz}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Matrix multiplication The overloaded \code{operator*} can be used for matrix multiplication. Finer control can be obtained using the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_mat_expr mul_direct(Fmpq_mat_expr, Fmpq_mat_expr) Fmpq_mat_expr mul_cleared(Fmpq_mat_expr, Fmpq_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Trace +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_expr trace(Fmpq_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Determinant +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_expr det(Fmpq_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nonsingular solving +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_mat_expr solve_dixon(Fmpq_mat_expr B, Fmpq_mat_expr X) Fmpq_mat_expr solve_fraction_free(Fmpq_mat_expr B, Fmpq_mat_expr X) See \code{fmpq_mat_solve_dixon} and \code{fmpq_mat_solve_fraction_free}. Raises \code{flint_exception} if $B$ is singular. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Inverse +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_mat_expr inv(Fmpq_mat_expr A) Compute the inverse of the square matrix $A$. Raises \code{flint_exception} if $A$ is singular. The modulus is required to be prime. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Echelon form +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpq_mat_target::pivot(slong r, slong c, permxx* perm = 0) See \code{fmpq_mat_pivot}. Ltuple_expr rref(Fmpq_mat_expr) Ltuple_expr rref_classical(Fmpq_mat_expr) Ltuple_expr rref_fraction_free(Fmpq_mat_expr) See \code{fmpq_mat_rref} etc. ******************************************************************************* fmpq\_polyxx ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ C++ particulars +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr Fmpq_poly_expr::operator()(Fmpq_poly_expr) const Fmpq_poly_expr Fmpq_poly_expr::operator()(Fmpq_expr) const Overloaded \code{operator()} for evaluation or composition. Fmpq_poly_expr::unary operation() const The following unary functions are made available as member functions: \code{derivative}, \code{integral}, \code{inv}, \code{make_monic}, \code{primitive_part}, \code{content}. Fmpq_poly_expr::binary operation(??) const The following binary functions are made available as member functions: \code{asinh_series}, \code{asin_series}, \code{atanh_series}, \code{atan_series}, \code{cosh_series}, \code{cos_series}, \code{divrem}, \code{exp_series}, \code{gcd}, \code{inv_series}, \code{inv_series_newton}, \code{lcm}, \code{log_series}, \code{pow}, \code{resultant}, \code{reverse}, \code{revert_series}, \code{revert_series_lagrange}, \code{revert_series_lagrange_fast}, \code{revert_series_newton}, \code{sinh_series}, \code{tanh_series}, \code{tan_series}, \code{xgcd}, \code{rescale},\\ \code{shift_left}, \code{shift_right}. Fmpq_poly_expr::ternary operation(??, ??) const The following ternary functions are made available as member functions: \code{compose_series}, \code{compose_series_brent_kung}, \code{compose_series_horner}, \code{div_series}, \code{mullow}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmpq_polyxx::fmpq_polyxx() fmpq_polyxx::fmpq_polyxx(slong alloc) See \code{fmpq_poly_init2}. fmpq_polyxx::fmpq_polyxx(const char* str) See \code{fmpq_poly_set_str}. void Fmpq_poly_target realloc(slong alloc) void Fmpq_poly_target::fit_length(slong len) void Fmpq_poly_target::_normalise() void Fmpq_poly_target::_set_length(slong len) void Fmpq_poly_target::canonicalise() bool Fmpq_poly_src::is_canonical() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Polynomial parameters +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong Fmpq_poly_expr::length() const slong Fmpq_poly_expr::degree() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Accessing the numerator and denominator +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmzqxx_ref Fmpq_poly_target::get_coeff_numref(slong n) fmzqxx_srcref Fmpq_poly_src::get_coeff_numref(slong n) const Obtain a reference to the numerator of coefficient $n$. The result is undefined if $n$ is greater than the degree of the polynomial (or negative). If this is used to modify the object, a call to \code{canonicalise()} may be necessary. (No unified access, see \code{get_coeff}.) ?? Fmpq_poly_expr::den() const Unified coefficient access to the denominator of the polynomial. If this is used to modify the object, a call to \code{canonicalise()} may be necessary. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Random testing +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static fmpq_polyxx fmpq_polyxx::randtest( frandxx& state, slong len, mp_bitcnt_t bits) static fmpq_polyxx fmpq_polyxx::randtest_unsigned( frandxx& state, slong len, mp_bitcnt_t bits) static fmpq_polyxx fmpq_polyxx::randtest_not_zero( frandxx& state, slong len, mp_bitcnt_t bits) See \code{fmpq_poly_randtest} etc. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Assignment +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_target Fmpq_poly_target::operator=(T:is_integer) Fmpq_poly_target Fmpq_poly_target::operator=(Fmpq_expr) Fmpq_poly_target Fmpq_poly_target::operator=(Fmpz_expr) Fmpq_poly_target Fmpq_poly_target::operator=(Fmpz_poly_expr) Fmpq_poly_target Fmpq_poly_target::operator=(const char*) void Fmpq_poly_target::set_zero() void Fmpq_poly_target::set_one() static fmpq_polyxx fmpq_polyxx::zero() static fmpq_polyxx fmpq_polyxx::one() Fmpq_poly_expr inv(Fmpq_poly_expr) static fmpq_polyxx fmpq_polyxx::get_slice(Fmpq_poly_expr, slong i, slong j) void Fmpq_poly_target::truncate(slong) Fmpq_poly_expr reverse(Fmpq_poly_expr, T:fits_into_slong) std::string Fmpq_poly_expr::pretty(const char* x) const See \code{fmpq_poly_get_str_pretty}. std::string Fmpq_poly_expr::to_string() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Getting and setting coefficients +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpqxx_expr Fmpq_poly_expr::get_coeff(slong n) const void Fmpq_poly_target::set_coeff(slong n, Fmpz_expr) void Fmpq_poly_target::set_coeff(slong n, Fmpq_expr) void Fmpq_poly_target::set_coeff(slong n, T:is_integer) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparison The overloaded operators \code{== != >= >} etc. can be used for comparison. Additionally, we have the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpq_poly_expr::is_one() const bool Fmpq_poly_expr::is_zero() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Arithmetic The overloaded operators \code{* / + -} can be used for both polynomial-polynomial and polynomial-scalar arithmetic. Additionally, we provide the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr mullow(Fmpq_poly_expr, Fmpq_poly_expr, slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Powering +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr pow(Fmpq_poly_expr, T:is_unsigned_integer) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Shifting +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr shift_left(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr shift_right(Fmpq_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Euclidean division The overloaded operators \code{/ %} can be used for euclidean division and remainder. Additionally, we have the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr divrem(Fmpq_poly_expr A, Fmpq_poly_expr B) \code{ltupleref(Q, R) = divrem(A, B)} has the same effect as \code{fmpq_poly_divrem(q, r, a, b)} where \code{q, r, a, b} are the underlying \code{fmpq_poly_t} corresponding to \code{Q, R, A, B}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Power series division +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr inv_series_newton(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr inv_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr div_series(Fmpq_poly_expr, Fmpq_poly_expr, slong n) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Greatest common divisor +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr gcd(Fmpq_poly_expr, Fmpq_poly_expr) Fmpq_poly_expr lcm(Fmpq_poly_expr, Fmpq_poly_expr) Ltuple_expr xgcd( Fmpq_poly_expr f, Fmpq_poly_expr g) \code{ltupleref(G, S, T) = xgcd(A, B)} has the same effect as \code{fmpq_poly_xgcd(g, s, t, a, b)}, where \code{g, s, t, a, b} denote the underlying \code{fmpq_poly_t} corresponding to \code{G, S, T, A, B}. Fmpq_expr resultant(Fmpq_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Derivative and integral +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr derivative(Fmpq_poly_expr) Fmpq_poly_expr integral(Fmpq_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Square roots +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr sqrt_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr invsqrt_series(Fmpq_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Transcendental functions +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr exp_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr log_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr atan_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr atanh_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr asin_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr asinh_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr tan_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr sin_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr cos_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr sinh_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr cosh_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr tanh_series(Fmpq_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Evaluation The overloaded \code{operator()} can be used for evaluation. Additionally we have the following. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_expr evaluate(Fmpq_poly_expr, Fmpq_expr) Fmpq_expr evaluate(Fmpq_poly_expr, Fmpz_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Interpolation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static Fmpq_poly_expr fmpq_polyxx::interpolate( Fmpz_vec_expr xs, Fmpz_vec_expr ys) See \code{fmpq_poly_interpolate_fmpq_vec}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Composition +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr compose(Fmpq_poly_expr, Fmpq_poly_expr) Fmpq_poly_expr rescale(Fmpq_poly_expr, Fmpq_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Power series composition +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr compose_series(Fmpq_poly_expr, Fmpq_poly_expr, slong) Fmpq_poly_expr compose_series_horner(Fmpq_poly_expr, Fmpq_poly_expr, slong) Fmpq_poly_expr compose_series_brent_kung(Fmpq_poly_expr, Fmpq_poly_expr, slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Power series reversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr revert_series(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr revert_series_newton(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr revert_series_lagrange(Fmpq_poly_expr, T:fits_into_slong) Fmpq_poly_expr revert_series_lagrange_fast(Fmpq_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Gaussian content +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_expr content(Fmpq_poly_expr) Fmpq_poly_expr primitive_part(Fmpq_poly_expr) bool Fmpq_poly_expr::is_monic() const Fmpq_poly_expr make_monic(Fmpq_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Square-free +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpq_poly_expr::is_squarefree() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ print(Fmpq_poly_expr) print(FILE*, Fmpq_poly_expr) print_pretty(Fmpq_poly_expr, const char* var) print_pretty(FILE*, Fmpq_poly_expr, const char* var) read(Fmpq_poly_target) read(FILE*, Fmpq_poly_target) ******************************************************************************* fmpz\_poly\_qxx ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmpz_poly_qxx::fmpz_poly_qxx() fmpz_poly_qxx::fmpz_poly_qxx(const char*) See \code{fmpz_poly_q_set_str}. void Fmpz_poly_q_target::canonicalise() bool Fmpz_poly_q_src::is_canonical() const ?? Fmpz_poly_q_expr::num() const ?? Fmpz_poly_q_expr::den() const Unified coefficient access to the numerator or denominator of the rational function. If this is used for modification, a call to \code{canonicalise()} may be necessary. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Randomisation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static fmpz_poly_qxx fmpz_poly_qxx::randtest(frandxx& state, slong len1, mp_bitcnt_t bits1, slong len2, mp_bitcnt_t bits2) static fmpz_poly_qxx fmpz_poly_qxx::randtest_not_zero(frandxx& state, slong len1, mp_bitcnt_t bits1, slong len2, mp_bitcnt_t bits2) See \code{fmpz_poly_q_randtest} etc. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Assignment +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_q_target Fmpz_poly_q_target::operator=(T:fits_into_slong) void Fmpz_poly_q_target::set_zero() void Fmpz_poly_q_target::set_one() static fmpz_poly_qxx fmpz_poly_qxx::zero() static fmpz_poly_qxx fmpz_poly_qxx::one() Fmpz_poly_q_expr inv(Fmpz_poly_q_expr) Fmpz_poly_q_expr Fmpz_poly_q_expr::inv() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparison The overloaded operator \code{==} can be used for comparison. Additionally, we have the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpz_poly_q_expr::is_one() const bool Fmpz_poly_q_expr::is_zero() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Powering +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_q_expr pow(Fmpz_poly_q_expr, T:is_unsigned_integer) Fmpz_poly_q_expr Fmpz_poly_q_expr::pow(T:is_unsigned_integer) const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Derivative +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_q_expr Fmpz_poly_q_expr::derivative() const Fmpz_poly_q_expr derivative(Fmpz_poly_q_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_q_target Fmpz_poly_q_target::operator=(const char*) See \code{fmpz_poly_q_set_str}. std::string Fmpz_poly_q_expr::to_string() const See \code{fmpz_poly_q_get_str}. std::string Fmpz_poly_q_expr::pretty(const char* x) const See \code{fmpz_poly_q_get_str_pretty}. int print(Fmpz_poly_q_expr) int print_pretty(Fmpz_poly_q_expr, const char* var) ******************************************************************************* fmpz\_poly\_matxx The class \code{fmpz_poly_matxx} wraps \code{fmpz_poly_mat_t}, and so represents matrices with coefficients in $\mathbf{Z}[X]$. Its usage is similar to \code{fmpz_matxx} in most regards. ******************************************************************************* Fmpz_poly_mat_expr::unary operation() const The following unary functions are made available as member functions: \code{det}, \code{det_fflu}, \code{det_interpolate}, \code{trace}, \code{sqr}, \code{sqr_classical}, \code{sqr_KS}, \code{transpose}. Fmpz_poly_mat_expr::binary operation(??) const The following binary functions are made available as member functions: \code{solve}, \code{solve_fflu}, \code{mul_classical}, \code{mul_interpolate}, \code{mul_KS}, \code{pow}, \code{sqrlow}. Fmpz_poly_mat_expr::three operation(??) const The following ternary functions are made available as member functions: \code{mullow}, \code{pow_trunc}. Fmpz_mat_expr Fmpz_poly_mat_expr::operator()(Fmpz_expr) const \code{operator()} is overloaded for matrix evaluation. Fmpz_poly_mat_expr operator?(??, ??) Arithmetic operators \code{+ - *} are overloaded when provided by \code{fmpz_poly_mat_t}. Fmpz_poly_mat_expr operator-(Fmpz_poly_mat_expr) The unary negation operator is overloaded. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int print_pretty(Fmpz_poly_mat_expr, const char* x) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic properties +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong Fmpz_poly_mat_expr::rows() const slong Fmpz_poly_mat_expr::cols() const Obtain the number of rows/columns in this matrix. These functions never cause evaluation (the matrix size is computed from the operations in the expression template and the size of the input matrices). +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic assignment and manipulation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ?? Fmpz_poly_mat_expr::at(T:fits_into_slong, U:fits_into_slong) const Unified coefficient access to the matrix entries. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Standard matrices +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Fmpz_poly_mat_target::set_zero() void Fmpz_poly_mat_target::set_one() static fmpz_poly_matxx fmpz_poly_matxx::zero(slong rows, slong cols) static fmpz_poly_matxx fmpz_poly_matxx::one(slong rows, slong cols) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Random matrix generation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Fmpz_poly_mat_target::set_randtest(frandxx& state, slong len, mp_bitcnt_t) void Fmpz_poly_mat_target::set_randtest_unsigned(frandxx& state, slong len, mp_bitcnt_t) void Fmpz_poly_mat_target::set_randtest_sparse(frandxx& state, slong len, mp_bitcnt_t, float) static fmpz_poly_matxx fmpz_poly_matxx::randtest(slong rows, slong cols, frandxx&, slong len, mp_bitcnt_t) static fmpz_poly_matxx fmpz_poly_matxx::randtest_unsigned(slong rows, slong cols, frandxx&, slong len, mp_bitcnt_t) static fmpz_poly_matxx fmpz_poly_matxx::randtest_sparse(slong rows, slong cols, frandxx&, slong len, mp_bitcnt_t, float density) See \code{fmpz_poly_mat_randtest} etc. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic comparison and properties +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpz_poly_mat_expr::is_zero() const bool Fmpz_poly_mat_expr::is_one() const bool Fmpz_poly_mat_expr::is_empty() const bool Fmpz_poly_mat_expr::is_square() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Norms +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong Fmpz_poly_mat_expr::max_length() const slong Fmpz_poly_mat_expr::max_bits() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Transpose +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_mat_expr transpose(Fmpz_poly_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Arithmetic Basic arithmetic is most easily done using the overloaded operators \code{+ * -}. Finer control can be obtained using the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mat_expr mul_classical(Fmpz_mat_expr, Fmpz_mat_expr) Fmpz_mat_expr mul_KS(Fmpz_mat_expr, Fmpz_mat_expr) Fmpz_poly_mat_expr mullow(Fmpz_poly_mat_expr, Fmpz_poly_mat_expr, slong) Fmpz_poly_mat_expr sqr(Fmpz_poly_mat_expr) Fmpz_poly_mat_expr sqr_KS(Fmpz_poly_mat_expr) Fmpz_poly_mat_expr sqr_classical(Fmpz_poly_mat_expr) Fmpz_poly_mat_expr sqrlow(Fmpz_poly_mat_expr, T:fits_into_slong n) Fmpz_poly_mat_expr pow(Fmpz_poly_mat_expr, T:is_unsigned_integer) Fmpz_poly_mat_expr pow_trunc(Fmpz_poly_mat_expr, T:is_unsigned_integer, T:fits_into_slong) Fmpz_poly_mat_expr prod(Fmpz_poly_mat_vec_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Row reduction Beware that compared to the C interface, the flintxx row reduction interface changes some argument orders. This is to facilitate default arguments. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong find_pivot_any(Fmpz_poly_mat_expr, slong, slong, slong) See \code{fmpz_poly_mat_find_pivot_any}. slong find_pivot_partial(Fmpz_poly_mat_expr, slong, slong, slong) See \code{fmpz_poly_mat_find_pivot_partial}. Ltuple_expr fflu(Fmpz_poly_mat_expr A, permxx* perm = 0, bool rankcheck = false) See \code{fmpz_poly_mat_fflu}. Ltuple_expr rref(Fmpz_poly_mat_expr A) See \code{fmpz_poly_mat_rref}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Trace +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr trace(Fmpz_poly_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Determinant and rank +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr det(Fmpz_poly_mat_expr) Fmpz_poly_expr det_fflu(Fmpz_poly_mat_expr) Fmpz_poly_expr det_interpolate(Fmpz_poly_mat_expr) slong rank(Fmpz_poly_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Inverse +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr inv(Fmpz_poly_mat_expr) \code{ltupleref(b, M, D) = inv(A)} has the same effect as \code{b = fmpz_poly_mat_inv(m, d, a)}, where \code{m, d, a} are the underlying C objects corresponding to \code{M, D, A}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nullspace +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr nullspace(Fmpz_poly_mat_expr A) \code{ltupleref(n, B) = nullspace(A)} has the same effect as\\ \code{n = fmpz_poly_mat_nullspace(b, a)}, where \code{b, a} are the underlying \code{fmpz_poly_mat_t} corresponding to \code{B, A}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Solving +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr solve( Fmpz_poly_mat_expr B, Fmpz_poly_mat_expr X) Ltuple_expr solve_fflu( Fmpz_poly_mat_expr B, Fmpz_poly_mat_expr X) Ltuple_expr solve_fflu_precomp( const permxx&, Fmpz_poly_mat_expr B, Fmpz_poly_mat_expr FFLU, Fmpz_poly_mat_expr X) \code{ltupleref(w, M, D) = solve(B, X)} has the same effect as\\ \code{w = fmpz_poly_mat_solve(m, d, b, x)}, where \code{m, d, b, x} are the underlying C objects corresponding to \code{M, D, B, X}. Similarly for the other functions. ******************************************************************************* nmodxx The class \code{nmodxx} encapsulates the use of \code{mp_limb_t} together with \code{nmod_t} for doing arithmetic modulo a word-sized integer. It is defined in \code{nmod_vecxx.h}. The C++ equivalent to \code{nmod_t} is \code{nmodxx_ctx}. There is a reference version\\ \code{nmodxx_ctx_srcref}. The C++ equivalent to \code{mp_limb_t} in this context is \code{nmodxx}. Immediate \code{nmodxx} expressions store both an \code{mp_limb_t} and an \code{nmodxx_ctx_srcref}. The most common ways to construct \code{nmodxx} are using the static member functions \code{nmodxx::red} and \code{nmodxx::make_nored}. For convenience, \code{operator%} is overloaded with right hand side \code{nmodxx_ctx} (or \code{nmodxx_ctx_srcref}) to call \code{nmodxx::red}. Just like when \code{mp_limb_t} is passed to \code{nmod_t} operations, the limb stored in \code{nmodxx} is assumed to be reduced, and under this assumption, all computations yield reduced data. It is assumed that any expression of \code{nmodxx} involves only one modulus, so that all contexts are interchangeable. ******************************************************************************* explicit nmodxx_ctx::nmodxx_ctx(mp_limb_t n) Initialise a new context for operations modulo $n$. nmodxx_ctx_srcref::nmodxx_ctx_srcref(const nmodxx_ctx&) Initialise a reference to an \code{nmodxx_ctx}. static nmodxx_ctx_srcref::make(const nmod_t& nm) Initialise a reference pointing to an \code{nmod_t}. const nmod_t& nmodxx_ctx::_nmod() const const nmod_t& nmodxx_ctx_srcref::_nmod() const Obtain a reference to the underlying \code{nmod_t}. mp_limb_t nmodxx_ctx::n() const mp_limb_t nmodxx_ctx_srcref::n() const Obtain the modulus stored in this context. nmodxx::nmodxx(nmodxx_ctx_srcref ctx) Initialise an \code{nmodxx} to zero. static nmodxx nmodxx::make_nored(mp_limb_t n, nmodxx_ctx_srcref ctx) Initialise an \code{nmodxx} to $n$, performing no reductions. static nmodxx nmodxx::red(mp_limb_t n, nmodxx_ctx_srcref ctx) static nmodxx nmodxx::red(Fmpz_expr n, nmodxx_ctx_srcref ctx) static nmodxx nmodxx::red(Fmpq_expr n, nmodxx_ctx_srcref ctx) Initialise an \code{nmodxx} to the reduction of $n$. static nmodxx_ref nmodxx_ref::make(mp_limb_t& l, nmodxx_ctx_srcref c) static nmodxx_srcref nmodxx_srcref::make(const mp_limb_t&, nmodxx_ctx_srcref) Obtain a flintxx reference object pointing to \code{l}, which is interpreted as a limb reduced modulo \code{c}. void Nmod_target::reduce() Reduce the stored limb. void Nmod_target::set_nored(mp_limb_t n) Set the stored limb to $n$. std::string Nmod_expr::to_string() const Convert self into a string of the form ``a mod b''. mp_limb_t Nmod_expr::to() const Obtain the stored limb. nmodxx_ctx_srcref Nmod_expr::estimate_ctx() const Obtain the context of any immediate subexpression. (By our homogeneity assumptions, the result of this operation does not depend on the subexpression chosen.) Nmod_expr Nmod_expr::inv() const Nmod_expr Nmod_expr::pow(T:is_unsigned_integer) const Nmod_expr operator??(Nmod_expr, Nmod_expr) Arithmetic operators \code{+ - * /} are overloaded for nmod expressions. Nmod_expr operator-(Nmod_expr) Nmod_expr pow(Nmod_expr, T:is_unsigned_integer) Nmod_expr inv(Nmod_expr) ******************************************************************************* nmod\_polyxx The class \code{nmod_polyxx} wraps \code{nmod_poly_t}. Like \code{nmodxx}, instances of \code{nmod_polyxx} always have an associated \code{nmodxx_ctx} storing the operating modulus. No expression may involve more than one modulus at a time. In order to reduce convert a \code{fmpz_polyxx} or \code{fmpq_polyxx} to \code{nmod_polyxx}, see the \code{reduce} method of \code{fmpz_polyxx} or \code{fmpq_polyxx}, respectively. ******************************************************************************* nmodxx_ctx_srcref Nmod_poly_expr::estimate_ctx() const Obtain the relevant context. This never causes evaluation. Nmod_poly_expr::unary operation() const The following unary functions are made available as member functions: \code{derivative}, \code{integral}, \code{make_monic}, \code{sqrt}. Nmod_poly_expr::binary operation() const The following binary functions are made available as member functions:\\ \code{compose_divconquer}, \code{compose_horner}, \code{div_basecase},\\ \code{div_divconquer}, \code{div_newton}, \code{divrem},\\ \code{divrem_basecase}, \code{divrem_divconquer},\\ \code{divrem_newton}, \code{div_root}, \code{evaluate_fast},\\ \code{evaluate_iter}, \code{gcd}, \code{gcd_euclidean}, \code{gcd_hgcd},\\ \code{inv_series}, \code{inv_series_basecase}, \code{inv_series_newton},\\ \code{invsqrt_series}, \code{mul_classical}, \code{mul_KS},\\ \code{shift_left}, \code{shift_right}, \code{pow},\\ \code{pow_binexp}, \code{rem_basecase}, \code{resultant},\\ \code{resultant_euclidean}, \code{reverse}, \code{revert_series},\\ \code{revert_series_lagrange}, \code{revert_series_lagrange_fast},\\ \code{revert_series_newton}, \code{sqrt_series}, \code{taylor_shift},\\ \code{taylor_shift_convolution}, \code{taylor_shift_horner}, \code{xgcd},\\ \code{xgcd_euclidean}, \code{xgcd_hgcd}, \code{log_series},\\ \code{exp_series}, \code{exp_series_basecase}, \code{atan_series},\\ \code{atanh_series}, \code{asin_series}, \code{asinh_series},\\ \code{sin_series}, \code{cos_series}, \code{tan_series},\\ \code{sinh_series}, \code{cosh_series}, \code{tanh_series}. Nmod_poly_expr Nmod_poly_expr::inflate(T:is_unsigned_integer) const \code{See inflate}. Nmod_poly_expr Nmod_poly_expr::deflate(T:is_unsigned_integer) const \code{See deflate}. Nmod_poly_expr::ternary operation(??, ??) const The following ternary functions are made available as member functions:\\ \code{compose_mod}, \code{compose_mod_horner},\\ \code{compose_series_brent_kung}, \code{compose_series},\\ \code{compose_series_brent_kung}, \code{compose_series_divconquer},\\ \code{compose_series_horner}, \code{div_newton_n_preinv},\\ \code{divrem_newton_n_preinv}, \code{div_series}, \code{mulhigh},\\ \code{mulhigh_classical}, \code{mullow}, \code{mullow_classical},\\ \code{mullow_KS}, \code{mulmod}, \code{powmod_binexp}, \code{pow_trunc},\\ \code{pow_trunc_binexp}. Nmod_poly_expr::fourary operation(??, ??, ??) const The following functions of four arguments are made available as member functions: \code{compose_mod_brent_kung_preinv}, \code{mulmod_preinv}, \code{powmod_binexp_preinv}. Nmod_poly_expr Nmod_poly_expr::operator()(Nmod_poly_expr) const Nmod_expr Nmod_poly_expr::operator()(Nmod_expr) const Nmod_vec_expr Nmod_poly_expr::operator()(Nmod_vec_expr) const The \code{operator()} is overloaded for evaluation or composition, depending on the argument. Nmod_poly_expr operator?(??, ??) Arithmetic operators \code{+ - * / %} are overloaded when provided by \code{nmod_poly_t}. Nmod_poly_expr operator-(Nmod_poly_expr) The unary negation operator is overloaded. Nmod_poly_target Nmod_poly_target::operator=(const char*) See \code{nmod_poly_set_str}. Raises \code{flint_exception} if the string is malformed. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Conversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static nmod_polyxx nmod_polyxx::reduce(Fmpz_mod_poly_expr, nmodxx_ctx_srcref) static nmod_polyxx nmod_polyxx::reduce(Fmpq_mod_poly_expr, nmodxx_ctx_srcref) static nmod_polyxx nmod_polyxx::reduce(Fmpz_mod_poly_expr, mp_limb_t) static nmod_polyxx nmod_polyxx::reduce(Fmpq_mod_poly_expr, mp_limb_t) See \code{fmpz_poly_get_nmod_poly}. static nmod_polyxx nmod_polyxx::from_ground(Nmod_expr e) static nmod_polyxx nmod_polyxx::from_ground(mp_limb_t e, nmodxx_ctx_srcref c) Consider $e \in \mathbf{Z}/n\mathbf{Z}$ as an element of $\mathbf{Z}/n\mathbf{Z}[X]$. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ print(Nmod_poly_expr) print(FILE*, Nmod_poly_expr) read(Nmod_poly_target) read(FILE*, Nmod_poly_target) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ nmod_polyxx::nmod_polyxx(mp_limb_t modulus) nmod_polyxx::nmod_polyxx(mp_limb_t modulus, slong alloc) nmod_polyxx::nmod_polyxx(nmodxx_ctx_srcref ctx) nmod_polyxx::nmod_polyxx(nmodxx_ctx_srcref ctx, slong alloc) Instantiate \code{nmod_polyxx} relative to some modulus. If the second argument is provided, space is allocated for \code{alloc} coefficients. nmod_polyxx::nmod_polyxx(const char* str) Instantiate \code{nmod_polyxx} from a string representation. The modulus is parsed (second integer in the string) and the polynomial is initialised with this modulus, then \code{nmod_poly_set_str} is called. Raises \code{flint_exception} if the string is malformed. static nmod_polyxx nmod_polyxx::zero(mp_limb_t n) static nmod_polyxx nmod_polyxx::one(mp_limb_t n) void Nmod_poly_target realloc(slong alloc) void Nmod_poly_target::fit_length(slong len) void Nmod_poly_target::_normalise() +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Polynomial properties +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sslong Nmod_poly_expr::length() const sslong Nmod_poly_expr::degree() const sslong Nmod_poly_expr::max_bits() const mp_limb_t Nmod_poly_expr::modulus() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Assignment and basic manipulation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Nmod_poly_target::truncate(slong) void Nmod_poly_target::set_zero() void Nmod_poly_target::set_one() Nmod_poly_expr reverse(Nmod_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Randomisation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Nmod_target::set_randtest(frandxx& state, slong len) void Nmod_target::set_randtest_irreducible(frandxx& state, slong len) static nmod_polyxx nmod_polyxx::randtest(mp_limb_t n, frandxx& state, slong len) static nmod_polyxx nmod_polyxx::randtest_irreducible(mp_limb_t n, frandxx& state, slong len) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Getting and setting coefficients +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmodxx_expr Nmod_poly_expr::get_coeff(slong n) const void Nmod_target::set_coeff(slong i, Nmodxx_expr) void Nmod_target::set_coeff(slong i, mp_limb_t) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ std::string Nmod_poly_expr::to_string() const std::ostream& operator<<(std::ostream&, Nmod_poly_expr) Output to streams is done by first converting to string. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparison +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Nmod_poly_expr::is_one() const bool Nmod_poly_expr::is_zero() const bool operator==(Nmod_poly_expr, Nmod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Scalar multiplication and division Scalar multiplication is provided via overloaded \code{operator*}. Additionally, the following functions are implemented: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr make_monic(Nmod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Bit packing and unpacking +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr Nmod_poly_expr::bit_pack(T:fits_into_mp_bitcnt_t) const static nmod_polyxx nmod_polyxx::bit_unpack( Fmpz_expr, T:fits_into_mp_bitcnt_t) const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Multiplication Basic multiplication is provided via overloaded \code{operator*}. Finer control can be obtained using the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr mul_classical(Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr mul_KS(Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr mullow(Nmod_poly_expr, Nmod_poly_expr, slong) Nmod_poly_expr mullow_classical(Nmod_poly_expr, Nmod_poly_expr, slong) Nmod_poly_expr mullow_KS(Nmod_poly_expr, Nmod_poly_expr, slong) Nmod_poly_expr mulhigh(Nmod_poly_expr, Nmod_poly_expr, slong) Nmod_poly_expr mulhigh_classical(Nmod_poly_expr, Nmod_poly_expr, slong) Nmod_poly_expr mulmod(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr mulmod_preinv(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Powering +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr pow(Nmod_poly_expr, T:is_unsigned_integer) Nmod_poly_expr pow_binexp(Nmod_poly_expr, T:is_unsigned_integer) Nmod_poly_expr pow_trunc(Nmod_poly_expr, T:is_unsigned_integer, T:fits_into_slong) Nmod_poly_expr pow_trunc_binexp(Nmod_poly_expr, T:is_unsigned_integer, T:fits_into_slong) Nmod_poly_expr powmod_binexp(Nmod_poly_expr, T:is_unsigned_integer, Nmod_poly_expr) Nmod_poly_expr powmod_binexp_preinv(Nmod_poly_expr, T:is_unsigned_integer, Nmod_poly_expr, Nmod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Division Basic division and remainder is provided by overloaded \code{operator/} and \code{operator%}. Finer control can be obtained using the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr divrem(Nmod_poly_expr A, Nmod_poly_expr B) Ltuple_expr divrem_basecase(Nmod_poly_expr A, Nmod_poly_expr B) Ltuple_expr divrem_divconquer( Nmod_poly_expr A, Nmod_poly_expr B) Ltuple_expr divrem_newton( Nmod_poly_expr A, Nmod_poly_expr B) Ltuple_expr divrem_newton_n_preinv( Nmod_poly_expr A, Nmod_poly_expr B) Nmod_poly_expr div_basecase(Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr div_divconquer(Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr div_newton(Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr div_newton_n_preinv(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr rem_basecase(Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr inv_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr inv_series_basecase(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr inv_series_newton(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr div_series(Nmod_poly_expr, Nmod_poly_expr, slong n) Nmod_poly_expr div_root(Nmod_poly_expr, Nmod_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Derivative and integral +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr derivative(Nmod_poly_expr) Nmod_poly_expr integral(Nmod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Evaluation Basic evaluation and multipoint evaluation can be achieved using the overloaded \code{operator()}. Finer control can be obtained using the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_expr evaluate(Nmod_poly_expr, Nmod_expr) Nmod_vec_expr evaluate(Nmod_poly_expr, Nmod_vec_expr) Nmod_vec_expr evaluate_fast(Nmod_poly_expr, Nmod_vec_expr) Nmod_vec_expr evaluate_iter(Nmod_poly_expr, Nmod_vec_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Interpolation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static Nmod_poly_expr fmpz_polyxx::interpolate( Nmod_vec_expr xs, Nmod_vec_expr ys) static Nmod_poly_expr fmpz_polyxx::interpolate_barycentric( Nmod_vec_expr xs, Nmod_vec_expr ys) static Nmod_poly_expr fmpz_polyxx::interpolate_fast( Nmod_vec_expr xs, Nmod_vec_expr ys) static Nmod_poly_expr fmpz_polyxx::interpolate_newton( Nmod_vec_expr xs, Nmod_vec_expr ys) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Composition Basic composition can be achieved with the overloaded \code{operator()}. Finer control can be obtained using the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr compose(Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr compose_horner(Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr compose_divconquer(Nmod_poly_expr, Nmod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Taylor Shift +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr taylor_shift(Nmod_poly_expr, Nmod_expr) Nmod_poly_expr taylor_shift_horner(Nmod_poly_expr, Nmod_expr) Nmod_poly_expr taylor_shift_convolution(Nmod_poly_expr, Nmod_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Modular composition +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr compose_mod(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr compose_mod_horner(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr compose_mod_divconquer(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr compose_mod_brent_kung(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr compose_mod_brent_kung_preinv(Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr, Nmod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Greatest common divisor +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr gcd(Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr gcd_euclidean(Nmod_poly_expr, Nmod_poly_expr) Nmod_poly_expr gcd_hgcd(Nmod_poly_expr, Nmod_poly_expr) Ltuple_expr xgcd( Nmod_poly_expr, Nmod_poly_expr) Ltuple_expr xgcd_euclidean( Nmod_poly_expr, Nmod_poly_expr) Ltuple_expr xgcd_hgcd( Nmod_poly_expr, Nmod_poly_expr) Nmod_expr resultant(Nmod_poly_expr, Nmod_poly_expr) Nmod_expr resultant_euclidean(Nmod_poly_expr, Nmod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Power series composition +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr compose_series(Nmod_poly_expr, Nmod_poly_expr, slong) Nmod_poly_expr compose_series_horner(Nmod_poly_expr, Nmod_poly_expr, slong) Nmod_poly_expr compose_series_brent_kung(Nmod_poly_expr, Nmod_poly_expr, slong) Nmod_poly_expr compose_series_divconquer(Nmod_poly_expr, Nmod_poly_expr, slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Power series reversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr revert_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr revert_series_newton(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr revert_series_lagrange(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr revert_series_lagrange_fast(Nmod_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Square roots +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr sqrt_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr invsqrt_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr sqrt_series(Nmod_poly_expr p) Compute the square root of $p$. Raises \code{flint_exception} if $p$ is not a perfect square. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Transcendental functions +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr exp_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr log_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr atan_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr atanh_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr asin_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr asinh_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr tan_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr sin_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr cos_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr sinh_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr cosh_series(Nmod_poly_expr, T:fits_into_slong) Nmod_poly_expr tanh_series(Nmod_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Products +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static Nmod_poly_expr fmpz_polyxx::product_roots(Nmod_vec_expr xs) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Inflation and deflation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr inflate(Nmod_poly_expr, T:is_unsigned_integer) Nmod_poly_expr deflate(Nmod_poly_expr, T:is_unsigned_integer) uslong Nmod_poly_expr::deflation() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Factorisation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Nmod_poly_expr::is_squarefree() const bool Nmod_poly_expr::is_irreducible() const sslong Nmod_poly_target::remove(Nmod_poly_expr) nmod_poly_factorxx::nmod_poly_factorxx() Initialise an empty factorisation. nmod_poly_factorxx::nmod_poly_factorxx(const nmod_poly_factorxx& o) Copy a factorisation. bool nmod_poly_factorxx::operator==(const nmod_poly_factorxx&) Compare two factorisations. ulong nmod_poly_factorxx::size() const Return the number of stored factors. slong nmod_poly_factorxx::exp(slong i) const slong& nmod_poly_factorxx::exp(slong i) Obtain the exponent of the ith factor. nmod_polyxx_srcref nmod_poly_factorxx::p(slong i) const nmod_polyxx_ref nmod_poly_factorxx::p(slong i) Obtain the ith factor. void nmod_poly_factorxx::realloc(slong a) void nmod_poly_factorxx::fit_length(slong a) void nmod_poly_factorxx::insert(Nmod_poly_expr p, slong e) void nmod_poly_factorxx::concat(const nmod_poly_factorxx&) void nmod_poly_factorxx::set_factor(Nmod_poly_expr) void nmod_poly_factorxx::set_factor_cantor_zassenhaus(Nmod_poly_expr) void nmod_poly_factorxx::set_factor_berlekamp(Nmod_poly_expr) void nmod_poly_factorxx::set_factor_kaltofen_shoup(Nmod_poly_expr) void nmod_poly_factorxx::set_factor_with_cantor_zassenhaus(Nmod_poly_expr) void nmod_poly_factorxx::set_factor_with_berlekamp(Nmod_poly_expr) void nmod_poly_factorxx::set_factor_with_kaltofen_shoup(Nmod_poly_expr) void nmod_poly_factorxx::set_factor_squarefree(Nmod_poly_expr) Factorise a polynomial and store its factors. See \code{nmod_poly_factor} etc. void nmod_poly_factorxx::set_factor_equal_deg_probab(frandxx&, Nmod_poly_expr, slong) void nmod_poly_factorxx::set_factor_equal_deg(Nmod_poly_expr, slong) See \code{nmod_poly_factor_equal_deg_prob} and \code{nmod_poly_factor_equal_deg}. void nmod_poly_factorxx::set_factor_distinct_deg(Nmod_poly_expr p, std::vector& degs) See \code{nmod_poly_factor_distinct_deg}. Note that \code{degs} must have sufficient size to hold all factors. The size of \code{degs} is not modified. nmod_poly_factorxx factor(Nmod_poly_expr) nmod_poly_factorxx factor_cantor_zassenhaus(Nmod_poly_expr) nmod_poly_factorxx factor_berlekamp(Nmod_poly_expr) nmod_poly_factorxx factor_kaltofen_shoup(Nmod_poly_expr) nmod_poly_factorxx factor_with_cantor_zassenhaus(Nmod_poly_expr) nmod_poly_factorxx factor_with_berlekamp(Nmod_poly_expr) nmod_poly_factorxx factor_with_kaltofen_shoup(Nmod_poly_expr) nmod_poly_factorxx factor_squarefree(Nmod_poly_expr) ******************************************************************************* nmod\_matxx The class \code{nmod_matxx} wraps \code{nmod_mat_t}. Like \code{nmodxx}, instances of \code{nmod_matxx} always have an associated \code{nmodxx_ctx} storing the operating modulus. No expression may involve more than one modulus at a time. Like \code{fmpz_matxx}, many operations on \code{nmod_matxx} do not support aliasing. The details can be found in the documentation of \code{nmod_mat_t}. Since \code{nmod_matxx} does not use temporary merging, evaluation of subexpressions never creates new aliases. ******************************************************************************* nmodxx_ctx_srcref Nmod_mat_expr::estimate_ctx() const Obtain the relevant context. This never causes evaluation. Nmod_mat_expr::unary operation() const The following unary functions are made available as member functions: \code{inv}, \code{transpose}, \code{trace}, \code{det}. Nmod_mat_expr::binary operation(??) const The following binary functions are made available as member functions: \code{solve}, \code{mul_classical}, \code{mul_strassen}. Nmod_mat_expr::ternary operation(??, ??) const The following ternary functions are made available as member functions: \code{solve_tril}, \code{solve_tril_recursive}, \code{solve_tril_classical}, \code{solve_triu}, \code{solve_triu_recursive}, \code{solve_triu_classical}. Nmod_mat_expr operator?(??, ??) Arithmetic operators \code{+ - *} are overloaded when provided by \code{nmod_mat_t}. Nmod_mat_expr operator-(Nmod_mat_expr) The unary negation operator is overloaded. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Conversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static nmod_matxx::reduce(Fmpz_mat_expr, mp_limb_t modulus) See \code{fmpz_mat_get_nmod_mat}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int print(Nmod_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ nmod_matxx::nmod_matxx(slong m, slong n, mp_limb_t modulus) See \code{nmod_mat_init}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic properties and manipulation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ?? Nmod_mat_expr::at(T:fits_into_slong, U:fits_into_slong) const Unified coefficient access to the matrix entries. sslong Nmod_mat_expr::rows() const sslong Nmod_mat_expr::cols() const Obtain the number of rows/columns in this matrix. These functions never cause evaluation (the matrix size is computed from the operations in the expression template and the size of the input matrices). bool Nmod_mat_expr::is_zero() const bool Nmod_mat_expr::is_empty() const bool Nmod_mat_expr::is_square() const mp_limb_t Nmod_mat_expr::modulus() const void Nmod_mat_target::set_zero() static nmod_matxx nmod_matxx::zero(slong rows, slong cols, mp_limb_t modulus) See \code{nmod_mat_zero}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Random matrix generation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Nmod_mat_target::set_randtest(frandxx&) void Nmod_mat_target::set_randfull(frandxx&) void Nmod_mat_target::set_randrank(frandxx&, slong rank) void Nmod_mat_target::set_randtril(frandxx&, bool unit) void Nmod_mat_target::set_randtriu(frandxx&, bool unit) See \code{nmod_mat_randtest} etc. static nmod_matxx nmod_matxx::randtest(slong rows, slong cols, mp_limb_t M, frandxx&) static nmod_matxx nmod_matxx::randfull(slong rows, slong cols, mp_limb_t M, frandxx&) static nmod_matxx nmod_matxx::randrank(slong rows, slong cols, mp_limb_t M, frandxx&, slong rank) static nmod_matxx nmod_matxx::randtril(slong rows, slong cols, mp_limb_t M, frandxx&, bool unit) static nmod_matxx nmod_matxx::randtriu(slong rows, slong cols, mp_limb_t M, frandxx&, bool unit) Static versions of the above. int Nmod_mat_target::set_randpermdiag(frandxx&, const Vec& v) \code{M.set_randpermdiag(Rand, V)} has the same effect as \code{nmod_mat_randpermdiag(m, rand, V._array(), V.size())}, where \code{m} and \code{rand} are the underlying C structs corresponding to \code{M} and \code{Rand}. One possibility for Vec is \code{nmod_vecxx}. void Nmod_target::apply_randops(frandxx&, slong count) See \code{nmod_mat_randops}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Transpose +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_mat_expr transpose(Nmod_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Matrix multiplication The overloaded \code{operator*} can be used for both matrix-matrix and matrix-scalar multiplication. Finer control can be obtained with the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_mat_expr mul_classical(Nmod_mat_expr, Nmod_mat_expr) Nmod_mat_expr mul_strassen(Nmod_mat_expr, Nmod_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Trace +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_expr trace(Nmod_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Determinant and rank +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_expr det(Nmod_mat_expr) slong rank(Nmod_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Inverse +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_mat_expr inv(Nmod_mat_expr A) Compute the inverse of the square matrix $A$. Raises \code{flint_exception} if $A$ is singular. The modulus is required to be prime. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Triangular solving +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_mat_expr solve_triu(Nmod_mat_expr, Nmod_mat_expr, bool unit) Nmod_mat_expr solve_triu_classical(Nmod_mat_expr, Nmod_mat_expr, bool unit) Nmod_mat_expr solve_triu_recursive(Nmod_mat_expr, Nmod_mat_expr, bool unit) Nmod_mat_expr solve_tril(Nmod_mat_expr, Nmod_mat_expr, bool unit) Nmod_mat_expr solve_tril_classical(Nmod_mat_expr, Nmod_mat_expr, bool unit) Nmod_mat_expr solve_tril_recursive(Nmod_mat_expr, Nmod_mat_expr, bool unit) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Non-singular square solving +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_mat_expr solve(Nmod_mat_expr B, Nmod_mat_expr X) Nmod_vec_expr solve(Nmod_mat_expr B, Nmod_vec_expr X) See \code{nmod_mat_solve} and \code{nmod_mat_solve_vec}. Raises \code{flint_exception} if $B$ is singular. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ LU decomposition +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Tuple Nmod_mat_target::set_lu(bool rank_check = false) Tuple Nmod_mat_target::set_lu_classical(bool rank_check = false) Tuple Nmod_mat_target::set_lu_recursive(bool rank_check = false) See \code{nmod_mat_lu} etc. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Reduced row echelon form +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Nmod_mat_target::set_rref() +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nullspace +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr nullspace(Nmod_mat_expr) ******************************************************************************* nmod\_poly\_matxx The class \code{nmod_poly_matxx} wraps \code{nmod_poly_mat_t}. Like \code{nmod_matxx}, instances of \code{nmod_poly_matxx} always have an associated \code{nmodxx_ctx} storing the operating modulus. No expression may involve more than one modulus at a time. Contrary to \code{nmod_poly_mat_t}, it is \emph{not} valid to use instances of \code{nmod_poly_matxx} with zero rows or columns. Like \code{fmpz_matxx}, many operations on \code{nmod_poly_matxx} do not support aliasing. The details can be found in the documentation of \code{nmod_poly_mat_t}. Since \code{nmod_poly_matxx} does not use temporary merging, evaluation of subexpressions never creates new aliases. ******************************************************************************* nmodxx_ctx_srcref Nmod_poly_mat_expr::estimate_ctx() const Obtain the relevant context. This never causes evaluation. Nmod_poly_mat_expr::unary operation() const The following unary functions are made available as member functions: \code{det}, \code{det_fflu}, \code{det_interpolate}, \code{trace}, \code{sqr}, \code{sqr_classical}, \code{sqr_interpolate}, \code{sqr_KS}, \code{transpose}. Nmod_poly_mat_expr::binary operation(??) const The following binary functions are made available as member functions: \code{solve}, \code{solve_fflu}, \code{mul_classical}, \code{mul_interpolate}, \code{mul_KS}, \code{pow}. Nmod_mat_expr Nmod_poly_mat_expr::operator()(Nmod_expr) const \code{operator()} is overloaded for matrix evaluation. Nmod_poly_mat_expr operator?(??, ??) Arithmetic operators \code{+ - *} are overloaded when provided by \code{nmod_poly_mat_t}. Nmod_poly_mat_expr operator-(Nmod_poly_mat_expr) The unary negation operator is overloaded. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int print_pretty(Nmod_poly_mat_expr, const char*) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ nmod_poly_matxx::nmod_poly_matxx(slong m, slong n, mp_limb_t modulus) See \code{nmod_poly_mat_init}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic assignment and manipulation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ?? Nmod_poly_mat_expr::at(T:fits_into_slong, U:fits_into_slong) const Unified coefficient access to the matrix entries. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Standard matrices +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static nmod_poly_matxx nmod_poly_matxx::zero(slong rows, slong cols, mp_limb_t n) static nmod_poly_matxx nmod_poly_matxx::one(slong rows, slong cols, mp_limb_t n) void Nmod_poly_mat_target::set_zero() void Nmod_poly_mat_target::set_one() +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Random matrix generation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Nmod_poly_mat_target::set_randtest(frandxx&, slong) void Nmod_poly_mat_target::set_randtest_sparse(frandxx&, slong, float) static nmod_poly_matxx nmod_poly_matxx::randtest(slong rows, slong cols, mp_limb_t n, slong len) static nmod_poly_matxx nmod_poly_matxx::randtest_sparse(slong rows, slong cols, mp_limb_t n, slong len, float density) See \code{nmod_poly_mat_randtest} etc. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic comparison and properties +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sslong Nmod_poly_mat_expr::rows() const sslong Nmod_poly_mat_expr::cols() const Obtain the number of rows/columns in this matrix. These functions never cause evaluation (the matrix size is computed from the operations in the expression template and the size of the input matrices). bool Nmod_poly_mat_expr::is_zero() const bool Nmod_poly_mat_expr::is_one() const bool Nmod_poly_mat_expr::is_empty() const bool Nmod_poly_mat_expr::is_square() const mp_limb_t Nmod_poly_mat_expr::modulus() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Norms +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sslong Nmod_poly_mat_expr::max_length() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Arithmetic The overloaded operators \code{+ - *} can be used for both matrix-matrix and matrix-scalar multiplication, and matrix-matrix addition/subtraction. Finer control can be obtained with the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_mat_expr mul_classical(Nmod_poly_mat_expr, Nmod_poly_mat_expr) Nmod_poly_mat_expr mul_interpolate(Nmod_poly_mat_expr, Nmod_poly_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Row reduction Beware that compared to the C interface, the flintxx row reduction interface changes some argument orders. This is to facilitate default arguments. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong find_pivot_any(Nmod_poly_mat_expr, slong, slong, slong) See \code{nmod_poly_mat_find_pivot_any}. slong find_pivot_partial(Nmod_poly_mat_expr, slong, slong, slong) See \code{nmod_poly_mat_find_pivot_partial}. Ltuple_expr fflu(Nmod_poly_mat_expr A, permxx* perm = 0, bool rankcheck = false) See \code{nmod_poly_mat_fflu}. Ltuple_expr rref(Nmod_poly_mat_expr A) See \code{nmod_poly_mat_rref}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Transpose +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_mat_expr transpose(Nmod_poly_mat_expr A) Compute the transpose of $A$. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Trace +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr trace(Nmod_poly_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Determinant and rank +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nmod_poly_expr det(Nmod_poly_mat_expr) Nmod_poly_expr det_fflu(Nmod_poly_mat_expr) Nmod_poly_expr det_interpolate(Nmod_poly_mat_expr) slong rank(Nmod_poly_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Inverse +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr inv(Nmod_poly_mat_expr A) \code{ltupleref(worked, M, P) = inv(A)} has the same effect as \code{worked = nmod_poly_mat_inv(m, p, a)}, where \code{m, p, a} are the C structs underlying \code{M, P, A}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Nullspace +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr nullspace(Nmod_poly_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Solving +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr solve(Nmod_poly_mat_expr, Nmod_poly_mat_expr) Ltuple_expr solve_fflu(Nmod_poly_mat_expr, Nmod_poly_mat_expr) Ltuple_expr solve_fflu_precomp( const permxx&, Nmod_poly_mat_expr B, Nmod_poly_mat_expr FFLU, Nmod_poly_mat_expr X) \code{ltupleref(worked, M, P) = solve(A, X)} has the same effect as \code{worked = nmod_poly_mat_solve(m, p, a, x)}, where \code{m, p, a, x} are the C structs underlying \code{M, P, A, X}. ******************************************************************************* fmpz\_mod\_polyxx The type \code{fmpz_mod_polyxx} wraps \code{fmpz_mod_poly}. Every instance of \code{fmpz_mod_poly} contains a reference to a context \code{fmpz_mod_ctx}. The only polynomial operation that can change the context object is \code{read}. ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Context +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmpz_modxx_ctx::fmpz_modxx_ctx(Fmpz_src n) fmpz_modxx_ctx::fmpz_modxx_ctx(ulong n) Initialize a context for the integers modulo \code{n}. fmpz_modxx_ctx::set_modulus(Fmpz_src n) fmpz_modxx_ctx::set_modulus(ulong n) Change the modulus of the context. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Operations +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mod_poly_expr::unary operation() const The following unary functions are made available as member functions: \code{derivative}, \code{integral}, \code{make_monic}, \code{sqr}. Fmpz_mod_poly_expr::binary operation() const The following binary functions are made available as member functions:\\ \code{compose_divconquer}, \code{compose_horner}, \code{div_basecase},\\ \code{div_divconquer}, \code{div_newton}, \code{divrem},\\ \code{divrem_basecase}, \code{divrem_divconquer},\\ \code{divrem}, \code{divrem_f},\\ \code{gcd}, \code{gcd_euclidean}, \code{gcd_euclidean_f}, \code{gcd_f},\\ \code{gcdinv}, \code{invmod}, \code{inv_series_newton},\\ \code{shift_left}, \code{shift_right}, \code{pow},\\ \code{rem_basecase}, \code{xgcd}, \code{xgcd_euclidean}. Fmpz_mod_poly_expr::ternary operation(??, ??) const The following ternary functions are made available as member functions:\\ \code{compose_mod}, \code{compose_mod_horner},\\ \code{compose_series_brent_kung}, \code{mullow},\\ \code{mulmod}, \code{powmod_binexp}, \code{pow_trunc},\\ \code{pow_trunc_binexp}. Fmpz_mod_poly_expr Fmpz_mod_poly_expr::operator()(Fmpz_mod_poly_expr) const Fmpz_mod_expr Fmpz_mod_poly_expr::operator()(Fmpz_mod_expr) const The \code{operator()} is overloaded for evaluation or composition, depending on the argument. Fmpz_mod_poly_expr operator?(??, ??) Arithmetic operators \code{+ - * %} are overloaded when provided by \code{nmod_poly_t}. Fmpz_mod_poly_expr operator-(Fmpz_mod_poly_expr) The unary negation operator is overloaded. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ print(Fmpz_mod_poly_expr) print(FILE*, Fmpz_mod_poly_expr) print_pretty(Fmpz_mod_poly_expr, const char* var) print_pretty(FILE*, Fmpz_mod_poly_expr, const char* var) read(Fmpz_mod_poly_target) read(FILE*, Fmpz_mod_poly_target) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmpz_mod_polyxx::fmpz_mod_polyxx(fmpz_modxx_ctx_srcref) fmpz_mod_polyxx::fmpz_mod_polyxx(fmpz_modxx_ctx_srcref, slong alloc) void Fmpz_mod_poly_target realloc(slong alloc) void Fmpz_mod_poly_target::fit_length(slong len) void Fmpz_mod_poly_target::_normalise() void Fmpz_mod_poly_target::truncate(slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Randomisation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Fmpz_mod_poly_mat_target::set_randtest(frandxx&, slong) void Fmpz_mod_poly_mat_target::set_randtest_irreducible(frandxx&, slong) void Fmpz_mod_poly_mat_target::set_randtest_not_zero(frandxx&, slong) See \code{fmpz_mod_poly_randtest}, etc. static fmpz_mod_polyxx fmpz_mod_polyxx::randtest(Fmpz_expr, frandx&, slong) static fmpz_mod_polyxx fmpz_mod_polyxx::randtest_not_zero(Fmpz_expr, frandx&, slong) static fmpz_mod_polyxx fmpz_mod_polyxx::randtest_irreducible(Fmpz_expr, frandx&, slong) Static versions of the above. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Attributes +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmpzxx_srcref Fmpz_mod_poly_mat_expr::modulus() const Obtain the relevant modulus. This never causes evaluation. slong Fmpz_mod_poly_expr::length() const slong Fmpz_mod_poly_expr::degree() const ?? Fmpz_mod_poly_expr::lead() const Unified coefficient access for the leading coefficient. The result is undefined if the length of the polynomial is zero. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Assignment and swap +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Fmpz_mod_poly_target::zero_coeffs(slong i, slong j) void Fmpz_mod_poly_target::set_zero() static fmpz_mod_polyxx fmpz_mod_polyxx::zero(Fmpz_expr m) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Conversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mod_poly_target Fmpz_mod_poly_target::operator=(T:is_unsigned_integer) Fmpz_mod_poly_target Fmpz_mod_poly_target::operator=(Fmpz_expr) Fmpz_mod_poly_target Fmpz_mod_poly_target::operator=(Fmpz_poly_expr) See \code{fmpz_mod_poly_set_ui}, \code{fmpz_mod_poly_set_fmpz} and \code{fmpz_mod_poly_set_fmpz_poly}. Fmpz_poly_expr Fmpz_mod_poly_expr::to() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparison +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Fmpz_mod_poly_expr::is_zero() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Getting and setting coefficients +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr Fmpz_mod_poly_expr::get_coeff(slong n) const void Fmpz_mod_target::set_coeff(slong i, Fmpz_expr) void Fmpz_mod_target::set_coeff(slong i, T:is_unsigned_integer) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Shifting +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mod_poly_expr shift_left(Fmpz_mod_poly_expr, T:fits_into_slong) Fmpz_mod_poly_expr shift_right(Fmpz_mod_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Multiplication The overloaded \code{operator*} can be used for both poly-poly and poly-scalar multiplication. Finer control can be obtained using the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mod_poly_expr mullow(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr, slong) Fmpz_mod_poly_expr sqr(Fmpz_mod_poly_expr) Fmpz_mod_poly_expr mulmod(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Powering +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mod_poly_expr pow(Fmpz_mod_poly_expr, T:is_unsigned_integer) Fmpz_mod_poly_expr pow_binexp(Fmpz_mod_poly_expr, T:is_unsigned_integer) Fmpz_mod_poly_expr pow_trunc(Fmpz_mod_poly_expr, T:is_unsigned_integer, T:fits_into_slong) Fmpz_mod_poly_expr pow_trunc_binexp(Fmpz_mod_poly_expr, T:is_unsigned_integer, T:fits_into_slong) Fmpz_mod_poly_expr powmod_binexp(Fmpz_mod_poly_expr, T:is_unsigned_integer, Fmpz_mod_poly_expr) Fmpz_mod_poly_expr powmod_binexp(Fmpz_mod_poly_expr, Fmpz_expr, Fmpz_mod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Division The overloaded operators \code{/ %} can be used for division and remainder. Finer control can be obtained using the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ltuple_expr divrem( Fmpz_mod_poly_expr A, Fmpz_mod_poly_expr B) Ltuple_expr divrem_basecase( Fmpz_mod_poly_expr A, Fmpz_mod_poly_expr B) Ltuple_expr divrem_divconquer( Fmpz_mod_poly_expr A, Fmpz_mod_poly_expr B) Ltuple_expr divrem_f( Fmpz_mod_poly_expr A, Fmpz_mod_poly_expr B) Fmpz_mod_poly_expr div_basecase(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Fmpz_mod_poly_expr rem_basecase(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Fmpz_mod_poly_expr rem(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) slong Fmpz_mod_poly_target::remove(Fmpz_mod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Power series inversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mod_poly_expr inv_series_newton(Fmpz_mod_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Greatest common divisor +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mod_poly_expr gcd(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Fmpz_mod_poly_expr gcd_euclidean(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Ltuple_expr xgcd( Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Ltuple_expr xgcd_euclidean( Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Ltuple_expr gcdinv( Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Ltuple_expr gcd_f(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Ltuple_expr gcd_euclidean_f(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Fmpz_mod_poly_expr invmod(Fmpz_mod_poly_expr f, Fmpz_mod_poly_expr g) See \code{fmpz_mod_poly_invmod}. Raises \code{flint_exception} if $f$ and $g$ are not coprime. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Derivative +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mod_poly_expr derivative(Fmpz_mod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Evaluation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mod_expr evaluate(Fmpz_mod_poly_expr, Fmpz_mod_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Composition Basic composition can be achieved with the overloaded \code{operator()}. Finer control can be obtained using the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mod_poly_expr compose(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Fmpz_mod_poly_expr compose_horner(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Fmpz_mod_poly_expr compose_divconquer(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Modular composition +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_mod_poly_expr compose_mod(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Fmpz_mod_poly_expr compose_mod_horner(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Fmpz_mod_poly_expr compose_mod_divconquer(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) Fmpz_mod_poly_expr compose_mod_brent_kung(Fmpz_mod_poly_expr, Fmpz_mod_poly_expr, Fmpz_mod_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Radix conversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fmpz_mod_poly_radixxx::fmpz_mod_poly_radixxx(Fmpz_poly_expr, slong deg) Initialise temporary data for radix conversion. See \code{fmpz_mod_poly_radix_init}. Fmpz_mod_poly_vec_expr Fmpz_mod_poly_expr::radix(const fmpz_mod_poly_radxxx&) Fmpz_mod_poly_vec_expr radix(Fmpz_mod_poly_expr F, const fmpz_mod_poly_radxxx&) Perform radix conversion. See \code{fmpz_mod_poly_radix}. Note that computing the output vector size requires knowing the degree of \code{F}. In the current implementation, this will result in evaluating \code{F} twice. In order to avoid this, pass in \code{F} in evaluated form, or do not form expressions requiring temporaries. ******************************************************************************* fmpz\_mod\_poly\_factorxx ******************************************************************************* bool Fmpz_mod_poly_expr::is_squarefree() const bool Fmpz_mod_poly_expr::is_irreducible() const bool Fmpz_mod_poly_expr::is_irreducible_ddf() const bool Fmpz_mod_poly_expr::is_irreducible_rabin() const slong Fmpz_mod_poly_target::remove(Fmpz_mod_poly_expr) fmpz_mod_poly_factorxx::fmpz_poly_factorxx(fmpz_modxx_ctx_srcref) Initialise an empty factorisation. fmpz_mod_poly_factorxx::nmod_poly_factorxx(const nmod_poly_factorxx& o) Copy a factorisation. bool fmpz_mod_poly_factorxx::operator==(const nmod_poly_factorxx&) Compare two factorisations. ulong fmpz_mod_poly_factorxx::size() const Return the number of stored factors. slong fmpz_mod_poly_factorxx::exp(slong i) const slong& fmpz_mod_poly_factorxx::exp(slong i) Obtain the exponent of the ith factor. fmpz_mod_polyxx_ref nmod_poly_factorxx::p(slong i) Obtain the ith factor. void fmpz_mod_poly_factorxx::realloc(slong a) void fmpz_mod_poly_factorxx::fit_length(slong a) void fmpz_mod_poly_factorxx::insert(Fmpz_mod_poly_expr p, slong e) void fmpz_mod_poly_factorxx::concat(const nmod_poly_factorxx&) void fmpz_mod_poly_factorxx::set_factor(Fmpz_mod_poly_expr) void fmpz_mod_poly_factorxx::set_factor_cantor_zassenhaus(Fmpz_mod_poly_expr) void fmpz_mod_poly_factorxx::set_factor_berlekamp(Fmpz_mod_poly_expr) void fmpz_mod_poly_factorxx::set_factor_kaltofen_shoup(Fmpz_mod_poly_expr) void fmpz_mod_poly_factorxx::set_factor_squarefree(Fmpz_mod_poly_expr) Factorise a polynomial and store its factors. See \code{fmpz_mod_poly_factor} etc. void fmpz_mod_poly_factorxx::set_factor_equal_deg_probab(frandxx&, Fmpz_mod_poly_expr, slong) void fmpz_mod_poly_factorxx::set_factor_equal_deg(Fmpz_mod_poly_expr, slong) See \code{fmpz_mod_poly_factor_equal_deg_prob} and \code{fmpz_mod_poly_factor_equal_deg}. void fmpz_mod_poly_factorxx::set_factor_distinct_deg(Fmpz_mod_poly_expr p, std::vector& degs) See \code{fmpz_mod_poly_factor_distinct_deg}. Note that \code{degs} must have sufficient size to hold all factors. The size of \code{degs} is not modified. fmpz_mod_poly_factorxx factor(Fmpz_mod_poly_expr) fmpz_mod_poly_factorxx factor_cantor_zassenhaus(Fmpz_mod_poly_expr) fmpz_mod_poly_factorxx factor_berlekamp(Fmpz_mod_poly_expr) fmpz_mod_poly_factorxx factor_kaltofen_shoup(Fmpz_mod_poly_expr) fmpz_mod_poly_factorxx factor_squarefree(Fmpz_mod_poly_expr) ******************************************************************************* padicxx The type \code{padicxx} wraps the C interface \code{padic_t}, and the type \code{padicxx_ctx} wraps \code{padic_ctx_t}. Evaluating composite expressions requires temporary objects, which must be initialised to a certain precision and with a certain context. The padicxx library employs the following rules: \begin{itemize} \item In any compound expression, there must only be one context involved. \item Temporary objects are initialised to the maximum precision of any subexpression. \end{itemize} In most use cases, all objects in a compound expression have the same precision, and so temporary expressions are evaluated to this precision. If you need temporary subexpressions to be evaluated to higher precision, the \code{toN} method can be used on immediates to increase their effective precision, thus (potentially) increasing the precision of intermediates. ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Context +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ padicxx_ctx::padicxx_ctx(Fmpz_src p, slong min, slong max, padic_print_mode mode) Initialize a padic context. See \code{padic_ctx_init}. padic_ctx_t& padicxx_ctx::_ctx() const Obtain a reference to the underlying C data structure. Note that this reference is mutable even if the instance of \code{padicxx_ctx} it is obtained from is not. This is because the context contains data which is not user-visible, and the C functions change them. If this is called on a constant instance of \code{padicxx_ctx}, you must ensure that no user-visible state is changed. padic_print_mode& padicxx_ctx::mode() padic_print_mode padicxx_ctx::mode() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ C++ particulars +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ padicxx_ctx_srcref Padic_src::get_ctx() const padic_ctx_t& Padic_src::_ctx() const Obtain a reference to the context of this instance. padicxx_ctx_srcref Padic_expr::estimate_ctx() const Obtain a reference to a context occurring in a subexpression. As per the first rule in the introduction to this section, all such contexts are the same by definition. Padic_expr::unary operation() const The following unary functions are made available as member functions: \code{exp}, \code{exp_balanced}, \code{exp_rectangular}, \code{inv}, \code{log}, \code{log_balanced}, \code{log_satoh}, \code{sqrt}, \code{teichmuller}. Padic_expr Padic_expr::pow(T:fits_into_slong) const padicxx_srcref Padic_src::toN(sslong N) const Obtain a new version of the operand, with changed effective precision. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int print(Padic_expr) int print(FILE*, Padic_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Data structures +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr Padic_expr::unit() const See \code{padic_unit}. slong Padic_expr::val() const slong& Padic_target::val() slong Padic_expr::prec() const slong& Padic_target::prec() Obtain the precision of this instance. See \code{padic_prec}. Note that this never requires evaluation. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ padicxx::padicxx(padicxx_ctx_srcref) Initialize padic number to default precision. See \code{padic_init}. padicxx::padicxx(padicxx_ctx_srcref c, slong N) Initialize padic number to precision $N$. See \code{padic_init2}. void Padic_target::reduce() See \code{padic_reduce}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Randomisation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static padicxx padicxx::randtest(frandxx& state, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) static padicxx padicxx::randtest_int(frandxx& state, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) static padicxx padicxx::randtest_not_zero(frandxx& state, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) Obtain a random padic number of precision \code{prec}. See \code{padic_randtest}, \code{padic_randtest_int} and \code{padic_randtest_not_zero}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Conversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Padic_target Padic_target::operator=(T:is_integer) Padic_target Padic_target::operator=(Fmpz_expr) Padic_target Padic_target::operator=(Fmpq_expr) padicxx padicxx::from_QQ(Fmpq_expr, padicxx_ctx_srcref) padicxx padicxx::from_QQ(Fmpz_expr, padicxx_ctx_srcref) padicxx padicxx::from_QQ(T:is_integer, padicxx_ctx_srcref) padicxx padicxx::from_QQ(Fmpq_expr, padicxx_ctx_srcref, sslong N) padicxx padicxx::from_QQ(Fmpz_expr, padicxx_ctx_srcref, sslong N) padicxx padicxx::from_QQ(T:is_integer, padicxx_ctx_srcref, sslong N) void Padic_target::set_zero() void Padic_target::set_one() padicxx padicxx::zero(padicxx_ctx_srcref) padicxx padicxx::zero(padicxx_ctx_srcref, sslong N) padicxx padicxx::one(padicxx_ctx_srcref) padicxx padicxx::one(padicxx_ctx_srcref, sslong N) bool Padic_expr::is_zero() const bool Padic_expr::is_one() const fmpzxx Padic_expr::to() const Convert self to \code{fmpzxx}, if possible. See \code{padic_get_fmpz}. fmpqxx Padic_expr::to() const Convert self to \code{fmpqxx}. See \code{padic_get_fmpz}. std::string Fmpz_expr::to_string() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Arithmetic operations The overloaded operators \code{+ - * / << >>} can be used for arithmetic operations, provided these are implemented for \code{padic_t}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Padic_expr inv(Padic_expr) Padic_expr sqrt(Padic_expr) Compute square root. May raise \code{flint_exception} if no square root exists. See \code{padic_sqrt}. Padic_expr pow(Padic_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Exponential +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Padic_expr exp(Padic_expr) Padic_expr exp_rectangular(Padic_expr) Padic_expr exp_balanced(Padic_expr) Compute the exponential function. These may raise \code{flint_exception}s if the series do not converge. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Logarithm +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Padic_expr log(Padic_expr) Padic_expr log_rectangular(Padic_expr) Padic_expr log_balanced(Padic_expr) Padic_expr log_satoh(Padic_expr) Compute the logarithm function. These may raise \code{flint_exception}s if the series do not converge. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Special functions +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Padic_expr teichmuller(Padic_expr) Fmpz_expr padic_val_fac(Fmpz_expr, Fmpz_expr) ulong padic_val_fac(T:is_unsigned_integer, Fmpz_expr) ******************************************************************************* padic\_polyxx The type \code{padic_polyxx} wraps \code{padic_poly}. Like \code{padicxx}, every instance of \code{padic_polyxx} contains a reference to a context \code{padicxx_ctx}, and stores its own precision. The same rules regarding temporary expressions apply to \code{padic_polyxx} as to \code{padicxx}. ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ C++ particulars +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ padicxx_ctx_srcref Padic_poly_src::get_ctx() const padic_ctx_t& Padic_poly_src::_ctx() const Obtain a reference to the context of this instance. padicxx_ctx_srcref Padic_poly_expr::estimate_ctx() const Obtain a reference to a context occurring in a subexpression. Padic_poly_expr::unary operation() const The following unary functions are made available as member functions: \code{derivative}. Padic_poly_expr::binary operation() const The following binary functions are made available as member functions: \code{pow}, \code{compose_pow}, \code{inv_series}, \code{shift_left}, \code{shift_right}. padic_polyxx_srcref Padic_poly_src::toN(sslong N) const Obtain a new version of the operand, with changed effective precision. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int print(Padic_expr) int print(FILE*, Padic_expr) int print_pretty(Padic_expr, const char*) int print_pretty(FILE*, Padic_expr, const char*) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ padic_polyxx::padic_polyxx(padicxx_ctx_srcref) Initialise to zero. See \code{padic_poly_init}. padic_polyxx::padic_polyxx(padicxx_ctx_srcref, slong prec, slong alloc = 0) See \code{padic_poly_init2}. void Padic_poly_target realloc(slong alloc) void Padic_poly_target::fit_length(slong len) void Padic_poly_target::canonicalise() void Padic_poly_target::reduce() void Padic_poly_target::truncate(slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Polynomial parameters +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong Padic_poly_expr::length() const slong Padic_poly_expr::degree() const slong Padic_expr::val() const slong& Padic_target::val() slong Padic_expr::prec() const slong& Padic_target::prec() +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Randomisation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static padic_polyxx padic_polyxx::randtest(frandxx& state, padicxx_ctx_srcref ctx, slong len, slong prec = PADIC_DEFAULT_PREC) static padic_polyxx padic_polyxx::randtest_val(frandxx& state, padicxx_ctx_srcref ctx, slong len, slong val, slong prec = PADIC_DEFAULT_PREC) static padic_polyxx padic_polyxx::randtest_not_zero(frandxx& state, slong len, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Assignment an basic manipulation The overloaded \code{operator=} can be used for assignments. Additionally, we provide the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ padic_polyxx padic_polyxx::from_QQ(T:is_integer, padicxx_ctx_srcref, sslong N) padic_polyxx padic_polyxx::from_QQ(Fmpz_expr, padicxx_ctx_srcref, sslong N) padic_polyxx padic_polyxx::from_QQ(Fmpq_expr, padicxx_ctx_srcref, sslong N) padic_polyxx padic_polyxx::from_QQ(T:is_integer, padicxx_ctx_srcref) padic_polyxx padic_polyxx::from_QQ(Fmpz_expr, padicxx_ctx_srcref) padic_polyxx padic_polyxx::from_QQ(Fmpq_expr, padicxx_ctx_srcref) padic_polyxx padic_polyxx::from_QQX(Fmpz_poly_expr, padicxx_ctx_srcref, sslong N) padic_polyxx padic_polyxx::from_QQX(Fmpq_poly_expr, padicxx_ctx_srcref, sslong N) padic_polyxx padic_polyxx::from_QQX(Fmpz_poly_expr, padicxx_ctx_srcref) padic_polyxx padic_polyxx::from_QQX(Fmpz_poly_expr, padicxx_ctx_srcref) padic_polyxx padic_polyxx::from_ground(Padic_expr) fmpz_polyxx Padic_poly_expr::to() const Convert to an integer polynomial. Raises \code{flint_exception} if the polynomial is not p-adically integral. See \code{padic_poly_get_fmpz_poly}. fmpq_polyxx Padic_poly_expr::to() const See \code{padic_poly_get_fmpq_poly}. padic_polyxx padic_polyxx::zero(const padic_polyxx_ctx&) padic_polyxx padic_polyxx::zero(const padic_polyxx_ctx&, sslong N) padic_polyxx padic_polyxx::one(const padic_polyxx_ctx&) padic_polyxx padic_polyxx::one(const padic_polyxx_ctx&, sslong N) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Getting and setting coefficients +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Padic_expr Padic_poly_expr::get_coeff(slong n) const void Padic_poly_target::set_coeff(slong i, Padic_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparison The overloaded \code{operator==} can be used for comparison. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Padic_poly_expr::is_zero() const bool Padic_poly_expr::is_one() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Arithmetic The overloaded operators \code{+ - *} can be used for arithmetic. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Powering +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Padic_poly_expr pow(Padic_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Series inversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Padic_poly_expr inv_series_newton(Padic_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Derivative +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Padic_poly_expr derivative(Padic_poly_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Shifting +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Padic_poly_expr shift_left(Padic_poly_expr, T:fits_into_slong) Padic_poly_expr shift_right(Padic_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Evaluation and composition The overloaded \code{operator()} can be used for both evaluation and composition. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Padic_expr evaluate(Padic_poly_expr, Padic_expr) Padic_poly_expr compose(Padic_poly_expr, Padic_poly_expr) Padic_poly_expr compose_pow(Padic_poly_expr, T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Testing +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Padic_poly_src::is_canonical() const bool Padic_poly_src::is_reduced() const ******************************************************************************* padic\_matxx The type \code{padic_matxx} wraps \code{padic_mat}. Like \code{padicxx}, every instance of \code{padic_matxx} contains a reference to a context \code{padicxx_ctx}, and stores its own precision. The same rules regarding temporary expressions apply to \code{padic_matxx} as to \code{padicxx}. ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ C++ particulars +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ padicxx_ctx_srcref Padic_mat_src::get_ctx() const padic_ctx_t& Padic_mat_src::_ctx() const Obtain a reference to the context of this instance. padicxx_ctx_srcref Padic_mat_expr::estimate_ctx() const Obtain a reference to a context occurring in a subexpression. padic_matxx_srcref Padic_mat_src::toN(sslong N) const Obtain a new version of the operand, with changed effective precision. slong Padic_mat_expr::rows() const slong Padic_mat_expr::cols() const Obtain the number of rows/columns of this matrix. This never evaluates. slong Padic_mat_expr::val() const slong& Padic_mat_target::val() Padic_mat_expr Padic_mat_expr::transpose() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Input and output +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int print(Padic_mat_expr) int print(FILE*, Padic_mat_expr) int print_pretty(Padic_mat_expr) int print_pretty(FILE*, Padic_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ padic_matxx::padic_matxx(padicxx_ctx_srcref, slong rows, slong cols) See \code{padic_mat_init}. padic_matxx::padic_matxx(padicxx_ctx_srcref, slong rows, slong cols, slong prec) See \code{padic_mat_init2}. void Padic_mat_target::canonicalise() void Padic_mat_target::reduce() bool Padic_mat_src::is_canonical() const bool Padic_mat_src::is_reduced() const bool Padic_mat_src::is_square() const bool Padic_mat_src::is_empty() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Basic assignment Overloaded \code{operatior=} can be used for assignment. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Padic_mat_target::set_zero() void Padic_mat_target::set_one() padic_matxx padic_matxx::zero(padicxx_ctx_srcref) padic_matxx padic_matxx::zero(padicxx_ctx_srcref, sslong N) padic_matxx padic_matxx::one(padicxx_ctx_srcref) padic_matxx padic_matxx::one(padicxx_ctx_srcref, sslong N) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Conversion Converting from a \code{fmpq_matxx} can be done using \code{operator=}, or the following functions. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ padic_matxx padic_matxx::from_QQ(Fmpq_mat_expr, padicxx_ctx_srcref) fmpq_matxx Padic_mat_expr::to() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Entries +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ?? Padic_mat_expr::at(slong i, slong j) Unified coefficient access to the underlying integer matrix. See \code{padic_mat_entry}. Fmpz_expr Padic_mat_expr::get_entry(slong i, slong j) void Padic_mat_target::set_entry(slong i, slong j, Padic_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparison Overloaded \code{operator==} can be used for comparison. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bool Padic_mat_expr::is_zero() const +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Random matrix generation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static padic_polyxx padic_polyxx::randtest(slong rows, slong cols, frandxx& state, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Transpose +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Padic_mat_expr transpose(Padic_mat_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Arithmetic Overloaded operators \code{+ - * /} can be used for arithmetic. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ******************************************************************************* qadicxx The type \code{qadicxx} wraps the C interface \code{qadic_t}, and the type \code{qadicxx_ctx} wraps \code{qadic_ctx_t}. Evaluating composite expressions requires temporary objects, which must be initialised to a certain precision and with a certain context. The same rules apply as for \code{padicxx}. ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Context +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qadicxx_ctx::qadicxx_ctx(Fmpz_src p, sslong min, slong max, padic_print_mode mode, const char* var = "x") Initialize a qadic context. See \code{qadic_ctx_init_conway}. qadic_ctx_t& qadicxx_ctx::_ctx() const Obtain a reference to the underlying C data structure. Note that this reference is mutable even if the instance of \code{qadicxx_ctx} it is obtained from is not. This is because the context contains data which is not user-visible, and the C functions change them. If this is called on a constant instance of \code{qadicxx_ctx}, you must ensure that no user-visible state is changed. padicxx_ctx_srcref qadicxx_ctx::pctx() const Obtain a reference to the underlying padic context. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ C++ particulars +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ padicxx_ctx_srcref Qadic_src::get_ctx() const const qadicxx_ctx& Qadic_src::get_qctx() const qadic_ctx_t& Qadic_src::_ctx() const Obtain a reference to the context of this instance. const qadicxx_ctx& Qadic_expr::estimate_ctx() const Obtain a reference to a context occurring in a subexpression. As per the first rule in the introduction to this section, all such contexts are the same by definition. Qadic_expr::unary operation() const The following unary functions are made available as member functions: \code{exp}, \code{exp_balanced}, \code{exp_rectangular}, \code{inv}, \code{log}, \code{log_balanced}, \code{teichmuller}, \code{trace}, \code{norm}, \code{norm_analytic}, \code{norm_resultant}. Qadic_expr Qadic_expr::pow(Fmpz_expr) const Qadic_expr Qadic_expr::frobenius(T:fits_into_slong) const qadicxx_srcref Qadic_src::toN(sslong N) const Obtain a new version of the operand, with changed effective precision. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Data structures +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int print_pretty(Qadic_expr) int print_pretty(FILE*, Qadic_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Data structures +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong Qadic_expr::val() const slong Qadic_expr::prec() const Obtain the precision of this instance. See \code{qadic_prec}. Note that this never requires evaluation. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Memory management +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qadicxx::qadicxx(const qadicxx_ctx&) Initialize qadic number to default precision. See \code{qadic_init}. qadicxx::qadicxx(const qadicxx_ctx& c, slong N) Initialize qadic number to precision $N$. See \code{qadic_init2}. void Qadic_target::reduce() See \code{qadic_reduce}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Randomisation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static qadicxx qadicxx::randtest(frandxx& state, const qadicxx_ctx& ctx, slong prec = PADIC_DEFAULT_PREC) static qadicxx qadicxx::randtest_int(frandxx& state, slong val, const qadicxx_ctx& ctx, slong prec = PADIC_DEFAULT_PREC) static qadicxx qadicxx::randtest_val(frandxx& state, const qadicxx_ctx& ctx, slong prec = PADIC_DEFAULT_PREC) static qadicxx qadicxx::randtest_not_zero(frandxx& state, const qadicxx_ctx& ctx, slong prec = PADIC_DEFAULT_PREC) Obtain a random qadic number of precision \code{prec}. See \code{qadic_randtest}, \code{qadic_randtest_int} and \code{qadic_randtest_not_zero}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Conversion +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Qadic_target Qadic_target::operator=(T:is_unsigned_integer) Qadic_target Qadic_target::operator=(Padic_expr) qadicxx qadicxx::from_ground(Padic_expr, const qadicxx_ctx&) void Qadic_target::set_zero() void Qadic_target::set_one() void Qadic_target::set_gen(const qadicxx_ctx&) qadicxx qadicxx::zero(const qadicxx_ctx&) qadicxx qadicxx::zero(const qadicxx_ctx&, sslong N) qadicxx qadicxx::one(const qadicxx_ctx&) qadicxx qadicxx::one(const qadicxx_ctx&, sslong N) qadicxx qadicxx::gen(const qadicxx_ctx&) qadicxx qadicxx::gen(const qadicxx_ctx&, sslong N) bool Qadic_expr::is_zero() const bool Qadic_expr::is_one() const padicxx Qadic_expr::to() const Convert self to \code{padicxx}, if possible. See \code{qadic_get_padic}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Arithmetic operations The overloaded operators \code{+ - * / << >>} can be used for arithmetic operations, provided these are implemented for \code{qadic_t}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Qadic_expr inv(Qadic_expr) Qadic_expr pow(Qadic_expr, Fmpz_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Exponential +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Qadic_expr exp(Qadic_expr) Qadic_expr exp_rectangular(Qadic_expr) Qadic_expr exp_balanced(Qadic_expr) Compute the exponential function. These may raise \code{flint_exception}s if the series do not converge. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Logarithm +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Qadic_expr log(Qadic_expr) Qadic_expr log_balanced(Qadic_expr) Compute the logarithm function. These may raise \code{flint_exception}s if the series do not converge. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Special functions +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Qadic_expr teichmuller(Qadic_expr) Padic_expr trace(Qadic_expr) Padic_expr norm(Qadic_expr) Padic_expr norm_analytic(Qadic_expr) Padic_expr norm_resultant(Qadic_expr) ******************************************************************************* arithxx The \code{arithxx} module wraps the \code{arith} module, i.e. provides functions for computing number theoretic functions. ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Primorials +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr primorial(T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Harmonic numbers +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_expr harmonic_number(T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Stirling numbers +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr stirling_number_1u(T:fits_into_slong, T:fits_into_slong) Fmpz_expr stirling_number_1(T:fits_into_slong, T:fits_into_slong) Fmpz_expr stirling_number_2(T:fits_into_slong, T:fits_into_slong) Fmpz_vec_expr stirling_number_1u_vec(T:fits_into_slong, T:fits_into_slong) Fmpz_vec_expr stirling_number_1_vec(T:fits_into_slong, T:fits_into_slong) Fmpz_vec_expr stirling_number_2_vec(T:fits_into_slong, T:fits_into_slong) Fmpz_vec_expr stirling_number_1u_vec_next(Fmpz_vec_expr v, T:fits_into_slong n) Fmpz_vec_expr stirling_number_1_vec_next(Fmpz_vec_expr v, T:fits_into_slong n) Fmpz_vec_expr stirling_number_2_vec_next(Fmpz_vec_expr v, T:fits_into_slong n) Given the vector $v$ of length $k$, compute the next vector of Stirling numbers. The size of the new vector is $k + 1$ if $k = n$, and else $k$. See \code{arith_stirling_number_1u_vec_next} etc. Fmpz_mat_expr stirling_matrix_1u(T:fits_into_slong m, T:fits_into_slong) Fmpz_mat_expr stirling_matrix_1(T:fits_into_slong m, T:fits_into_slong) Fmpz_mat_expr stirling_matrix_2(T:fits_into_slong m, T:fits_into_slong) Compute an $m \times n$ Stirling matrix. See \code{arith_stirling_matrix_1u} etc. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Bell numbers +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr bell_number(T:is_unsigned_integer) Fmpz_expr bell_number_bsplit(T:is_unsigned_integer) Fmpz_expr bell_number_multi_mod(T:is_unsigned_integer) Fmpz_vec_expr bell_number_vec(T:is_unsigned_integer) Fmpz_vec_expr bell_number_vec_recursive(T:is_unsigned_integer) Fmpz_vec_expr bell_number_vec_multi_mod(T:is_unsigned_integer) Nmod_expr bell_number_nmod(T:is_unsigned_integer, Nmodxx_ctx_src) Nmod_vec_expr bell_number_nmod_vec(T:is_unsigned_integer, Nmodxx_ctx_src) Nmod_vec_expr bell_number_nmod_vec_recursive(T:is_unsigned_integer, Nmodxx_ctx_src) Nmod_vec_expr bell_number_nmod_vec_series(T:is_unsigned_integer, Nmodxx_ctx_src) double bell_number_size(ulong n) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Bernoulli numbers and polynomials +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_expr bernoulli_number(T:is_unsigned_integer) Fmpq_vec_expr bernoulli_number_vec(T:fits_into_slong) Fmpz_expr bernoulli_number_denom(T:is_unsigned_integer) double bernoulli_number_size(ulong) Fmpq_poly_expr bernoulli_polynomial(T:is_unsigned_integer) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Euler numbers and polynomials +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_expr euler_number(T:is_unsigned_integer) Fmpq_vec_expr euler_number_vec(T:fits_into_slong) double euler_number_size(ulong) Fmpq_poly_expr euler_polynomial(T:is_unsigned_integer) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Legendre polynomials +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpq_poly_expr legendre_polynomial(T:is_unsigned_integer) Fmpz_poly_expr chebyshev_t_polynomial(T:is_unsigned_integer) Fmpz_poly_expr chebyshev_u_polynomial(T:is_unsigned_integer) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Multiplicative functions +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr euler_phi(Fmpz_expr) int moebius_mu(Fmpz_expr) Fmpz_expr divisor_sigma(Fmpz_expr, ulong) Fmpz_poly_expr divisors(Fmpz_expr) Fmpz_expr ramanujan_tau(Fmpz_expr) Fmpz_poly_expr ramanujan_tau_series(T:fits_into_slong) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cyclotomic polynomials +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr cyclotomic_polynomial(T:is_unsigned_integer) Fmpz_poly_expr cos_minpoly(T:is_unsigned_integer) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Swinnerton-Dyer polynomials +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_poly_expr swinnerton_dyer_polynomial(T:is_unsigned_integer) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Landau's function +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_vec_expr landau_function_vec(T:is_unsigned_integer) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Dedekind sums +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr dedekind_sum_naive(Fmpz_expr, Fmpz_expr) Fmpz_expr dedekind_sum(Fmpz_expr, Fmpz_expr) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Number of partitions +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_vec_expr number_of_partitions_vec(T:fits_into_slong) Nmod_vec_expr number_of_partitions_nmod_vec(T:fits_into_slong) Fmpz_expr number_of_partitions(T:is_unsigned_integer) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Sums of squares +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Fmpz_expr sum_of_squares(T:is_unsigned_integer, Fmpz_expr) Fmpz_vec_expr sum_of_squares(T:is_unsigned_integer, T:fits_into_slong) flint2-2.8.4/flintxx/doc/genericxx.txt000066400000000000000000000415411414523752600177370ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ ******************************************************************************* Rules and standard methods A typical expression template class begins with the following lines of code: \begin{lstlisting}[language=c++] template class some_expression : public expression, Operation, Data> { // ... }; \end{lstlisting} We document here methods this class inherits from its base, and how they relate to rules. There are the following public typedefs: \begin{description} \item[ev\_traits\_t] A specialisation of \code{detail::evaluation_traits}. Used to compute the rule for evaluation. \item[derived\_t] The specialised derived class. \item[evaluated\_t] The resulting type of evaluating this expression. \item[evaluation\_return\_t] The return type of \code{evaluate()}. This differs from the above for immediates, where evaluation returns a reference instead of a copy. \item[data\_t] The same as \code{Data}. \item[operation\_t] The same as \code{Operation}. \end{description} ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Standard methods +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ data_t& some_expression::_data() const data_t& some_expression::_data() const Obtain the data related to this expression template. evaluated_t some_expression::create_temporary() const Default instantiate a temporary. Override this if your class is not default instantiable. template T some_expression::to() const Convert self to type \code{T} (after evaluating). Uses \code{rules::conversion}. void some_expression::print(std::ostream& o) const Print self to \code{o}. Uses \code{rules::print} or \code{rules::to_string}. int some_expression::print(FILE* f = stdout) const Print self to \code{f}. Uses \code{rules::cprint}. int some_expression::print_pretty(FILE* f = stdout) const Print self to \code{f}. Uses \code{rules::print_pretty}. template int some_expression::print_pretty(const T& extra, FILE* f = stdout) const Print self to \code{f}. Uses \code{rules::print_pretty} with two arguments. int some_expression::read(FILE* f = stdin) Read self from \code{f}. Uses \code{rules::read}. const evaluation_return_t some_expression::evaluate() const Evaluate self. template void some_expression::set(const T& t) Assign \code{t} to self. Uses evaluation and/or \code{rules::assignment}. template bool some_expression::equals(const T& t) const Determine if \code{t} is equal to self. Uses \code{rules::equals} or \code{rules::cmp}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Global functions In addition to member functions, flintxx also provides a number of global functions. In general these operate on sets of arguments at least one of which derives from \code{expression}, and are conditionally enabled only if the relevant operation is implemented (via a rule). +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ template std::ostream& operator<<(std::ostream& o, const Expr& e) Print \code{e} to \code{o}. Uses the member \code{print}. template bool operator==(const Expr1&, const Expr2&) template bool operator!=(const Expr1&, const Expr2&) Compare two expressions. Uses the member \code{equals}. template bool operator??(const Expr1&, const Expr2&) Relational operators \code{< > <= =>} are implemented using \code{rules::cmp}. template ?? operator??(const Expr1&, const Expr2&) Arithmetic operators \code{+ - * / % & | ^ << >>} are implemented by constructing new expression templates with operation \code{operations::plus} etc. template ?? operator??(const Expr1&) Unary operators \code{- ~} are implemented by constructing new expression templates with operation \code{operations::negate} and \code{operations::complement}. template ?? operator?=(const Expr1&, const Expr2&) Arithmetic-assignment operators \code{+= -= *= /= %= |= &= ^=}. template int print(const Expr1&) template int print(FILE*f, const Expr1&) template int print_pretty(const Expr1&) template int print_pretty(FILE*f, const Expr1&) template int print_pretty(const Expr1&, const T& extra) template int print_pretty(FILE*f, const Expr1&, const T& extra) Forward to member. template void swap(Expr1& e1, Expr2& e2) Swap \code{e1} and \code{e2} using \code{rules::swap}. Note that via ADL, this can be used by STL containers. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ flintxx classes The flint wrapper classes share some other common interfaces. These have to be enabled using the convenience macros in \code{flintxx/flint_classes.h} (q.v.). Here \code{accessname} and \code{ctype} are specified via the macros. For e.g. \code{fmpz_polyxx} these are \code{_poly} and \code{fmpz_poly_struct}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ?? some_expression::accessname() ?? some_expression::accessname() const Obtain a reference to the underlying C struct. This is only available on immediate expressions. some_expression_ref::some_expression_ref(some_expression&) some_expression_srcref::some_expression_srcref(const some_expression&) some_expression_srcref::some_expression_srcref(some_expression_ref) Build a reference type. Note that these are \emph{implicit} constructors. static some_expression_ref some_expression_ref::make(ctype*) static some_expression_srcref some_expression_srcref::make(const ctype*) Build a reference type from a pointer to the underlying C struct. ******************************************************************************* Convenience macros ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ flintxx/rules.h +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FLINT_DEFINE_GET2(name, totype, fromtype1, fromtype2, eval) Specialise a getter called \code{name}, which takes arguments \code{e1} of type \code{fromtype1} and \code{e2} of type \code{fromtype2}. It returns \code{totype} by executing \code{eval}. FLINT_DEFINE_GET(name, totype, fromtype, eval) Same as \code{FLINT_DEFINE_GET2(name, totype, fromtype, fromtype, eval)}. FLINT_DEFINE_GET_COND(name, totype, cond, eval) Specialise a getter called \code{name}, which takes an argument \code{from} of type \code{T:cond} It returns \code{totype} by executing \code{eval}. FLINT_DEFINE_DOIT(name, totype, fromtype, eval) Specialise a doit rule called \code{name}, which takes arguments \code{to} of type \code{totype&} and \code{from} of type \code{const fromtype&}, and executes \code{eval}. FLINT_DEFINE_DOIT_COND(name, totype, cond, eval) Same as above, but takes \code{const T& from} for any \code{T:cond}. FLINT_DEFINE_DOIT_COND2(name, cond1, cond2, eval) Same as \code{FLINT_DEFINE_DOIT_COND}, but takes \code{T& to} and \code{const U& from} for any \code{T} satisfying \code{cond1} and \code{U} satisfying \code{cond2}. FLINT_DEFINE_PRINT_COND(cond, eval) Specialise the \code{cprint} rule. This takes a arguments \code{FILE* to} and \code{const T& from} for any \code{T:cond}. It prints \code{from} to \code{to} and returns \code{int} by executing \code{eval}. FLINT_DEFINE_PRINT_PRETTY_COND(cond, eval) Same as above, but with \code{print_pretty} instead of \code{cprint}. FLINT_DEFINE_PRINT_PRETTY_COND2(cond, extratype, eval) Same as above, but takes an additional argument \code{extratype extra}. Useful e.g. when printing polynomials and taking an extra variable name. FLINT_DEFINE_READ_COND(cond, eval) Specialise the \code{read} rule. This takes a arguments \code{FILE* from} and \code{T& to} for any \code{T:cond}. It reads \code{to} from \code{from} and returns \code{int} by executing \code{eval}. FLINT_DEFINE_UNARY_EXPR_(name, rtype, type, eval) Specialise the unary expression rule for \code{operations::name} with nominal return type \code{rtype}. It takes arguments \code{V& to} and \code{const type& from}. Here \code{V} is any type which \code{rtype} can be evaluated into. Executes \code{eval}. FLINT_DEFINE_UNARY_EXPR(name, type, eval) Same as \code{FLINT_DEFINE_UNARY_EXPR_(name, type, type, eval)}. FLINT_DEFINE_BINARY_EXPR2(name, rtype, type1, type2, eval) Specialise the binary expression rule for \code{operations::name} of nominal return type \code{rtype}, and arguments \code{type1} and \code{type2}. FLINT_DEFINE_BINARY_EXPR(name, type, eval) Same as \code{FLINT_DEFINE_BINARY_EXPR2(name, type, type, type, eval)}. FLINT_DEFINE_CBINARY_EXPR(name, type, eval) Same as above, but with \code{commutative_binary_expression} instead of \code{binary_expression}. FLINT_DEFINE_BINARY_EXPR_COND(name, type, cond, eval) FLINT_DEFINE_CBINARY_EXPR_COND(name, type, cond, eval) Specialise the (commutative) binary expression rule for \code{operations::name} of nominal return type \code{type}, and arguments \code{type} and \code{T:cond}. FLINT_DEFINE_BINARY_EXPR_COND2(name, rettype, cond1, cond2, eval) FLINT_DEFINE_CBINARY_EXPR_COND2(name, rettype, cond1, cond2, eval) Specialise the (commutative) binary expression rule for \code{operations::name} of nominal return type \code{rettype}, and arguments \code{T:cond1} and \code{U:cond2}. FLINT_DEFINE_THREEARY_EXPR_COND3(name, rettype, cond1, cond2, cond3, eval) FLINT_DEFINE_FOURARY_EXPR_COND4(name, rettype, cond1 ... cond4, eval) FLINT_DEFINE_FIVEARY_EXPR_COND5(name, rettype, cond1 ... cond5, eval) FLINT_DEFINE_SIXARY_EXPR_COND6(name, rettype, cond1 ... cond6, eval) FLINT_DEFINE_SEVENARY_EXPR_COND7(name, rettype, cond1 ... cond7, eval) Specialise higher order rules, similarly to the above. FLINT_DEFINE_THREEARY_EXPR(name, rettype, T1, T2, T3, eval) Specialise a threeary expression rule unconditionally. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ flintxx/expression.h +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FLINT_DEFINE_UNNOP(name) FLINT_DEFINE_BINOP(name) FLINT_DEFINE_THREEARY(name) FLINT_DEFINE_FOURARY(name) FLINT_DEFINE_FIVEARY(name) FLINT_DEFINE_SIXARY(name) FLINT_DEFINE_SEVENARY(name) Introduce a new n-ary operation \code{operations::##name##_op} and make it available. This has to be called in namespace \code{flint}. FLINT_DEFINE_UNNOP_HERE(name) FLINT_DEFINE_BINOP_HERE(name) FLINT_DEFINE_THREEARY_HERE(name) FLINT_DEFINE_FOURARY_HERE(name) FLINT_DEFINE_FIVEARY_HERE(name) FLINT_DEFINE_SIXARY_HERE(name) FLINT_DEFINE_SEVENARY_HERE(name) Make the n-ary operation \code{operations::##name##_op} available in the current namespace. FLINT_DEFINE_THREEARY_HERE_2DEFAULT(name, type1, val1, type2, val2) Make the threeary operation \code{name} available in current namespace, but with only two arguments, the second of which is of type \code{type1} and defaults to \code{val1}, and the third argument always (implicitly) of type \code{type2} and value \code{val2}. The suggested usage of this macro is to first call \code{FLINT_DEFINE_THREEARY_HERE} (or \code{FLINT_DEFINE_THREEARY}), and then call \code{FLINT_DEFINE_THREEARY_HERE_2DEFAULT}. The effect will be an operation which can be invoked with 1, 2 or 3 arguments. FLINT_UNOP_ENABLE_RETTYPE(name, T1) FLINT_BINOP_ENABLE_RETTYPE(name, T1, T2) FLINT_THREEARY_ENABLE_RETTYPE(name, T1, T2, T3) FLINT_FOURARY_ENABLE_RETTYPE(name, T1, T2, T3, T4) FLINT_FIVEARY_ENABLE_RETTYPE(name, T1, T2, T3, T4, T5) FLINT_SIXARY_ENABLE_RETTYPE(name, T1, T2, T3, T4, T5, T6) FLINT_SEVENARY_ENABLE_RETTYPE(name, T1, T2, T3, T4, T5, T6, T7) Obtain the resulting type of invoking \code{name} with arguments of types \code{T1}, ..., \code{Tn} if this is possible. Otherwise results in an (SFINAE) error. FLINT_UNOP_BUILD_RETTYPE(name, rettype, T) Obtain the resulting type (i.e. expression template) of invoking \code{name} with argument type \code{T}, assuming the nominal return type is \code{rettype}. This version is sometimes necessary to break cyclic dependencies. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ flintxx/flint\_classes.h +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FLINTXX_DEFINE_BASICS(name) Add standard constructors (forwarded to \code{data_t}, and implicit ones for reference types). Here \code{name} is the name of the expression template class. FLINTXX_DEFINE_C_REF(name, ctype, accessname) Enable the reference types scheme. FLINTXX_DEFINE_FORWARD_STATIC(funcname) Add a statically forwarded constructor (similar to \code{make} for reference types) which invokes a static constructor of the same name of \code{data_t}. FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(rettype, name) Add a no-argument member function which applies self to the lazy function \code{name}, where \code{name} has nominal return type \code{rettype}. (The return type has to be specified to break circular dependencies.) FLINTXX_DEFINE_MEMBER_UNOP(name) Same as above, but where the nominal return type is the (evaluated type of the) current expression template class. FLINTXX_DEFINE_MEMBER_BINOP(name) FLINTXX_DEFINE_MEMBER_3OP(name) FLINTXX_DEFINE_MEMBER_4OP(name) FLINTXX_DEFINE_MEMBER_5OP(name) Add a member function which \code{n-1} arguments, the result of which is to invoke \code{name} on self and the arguments (in that order). FLINTXX_COND_S(Base) FLINTXX_COND_T(Base) Expands to a condition (which can be passed to e.g. \code{FLINT_DEFINE_CBINARY_EXPR_COND2}) appropriate for testing a source/target of type \code{Base}. FLINTXX_DEFINE_TO_STR(Base, eval) Add a \code{to_string} rule which works well with the \code{*_get_str} functions in FLINT. FLINTXX_DEFINE_SWAP(Base, eval) Add a swap rule. FLINTXX_DEFINE_CONVERSION_TMP(totype, Base, eval) Define a conversion rule from \code{Base} to \code{totype}, which default-constructs a temporary object \code{to} of type \code{totype}, then executes \code{eval}, and then returns \code{to}. FLINTXX_DEFINE_CMP(Base, eval) FLINTXX_DEFINE_EQUALS(Base, eval) Define a cmp/equality rule. FLINTXX_DEFINE_ASSIGN_STR(Base, eval) Define a string assignment rule (used by many polynomial classes). +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ flintxx/matrix.h +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FLINTXX_DEFINE_MATRIX_METHODS(Traits) Inside a matrix expression template class definition, given the unified access traits \code{Traits} appropriate for this class, define the standard methods \code{rows, cols, create_temporary}. FLINTXX_DEFINE_TEMPORARY_RULES(Matrix) Given a matrix expression template class \code{Matrix}, define appropriate temporary instantiation rule, disable temporary merging, etc. ******************************************************************************* Helper functions ******************************************************************************* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ flintxx/flint\_exception.h +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void execution_check(bool worked, const std::string& where, const std::string& context) If \code{worked} is true, do nothing. Else raise a \code{flint_exception} with message \code{context + " computation failed: " + where}. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ permxx.h +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ slong* maybe_perm_data(permxx* p) Return \code{0} if \code{p == 0}, and else the underlying data. It is helpful to use this together with \code{traits::is_maybe_perm} as condition. flint2-2.8.4/flintxx/dummy.c000066400000000000000000000001251414523752600157250ustar00rootroot00000000000000/* Just here to please the build system. */ void __do_nothing() {/* stop warning */} flint2-2.8.4/flintxx/evaluation_tools.h000066400000000000000000001107611414523752600201760ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // This file contains helpers for evaluating expression templates. #ifndef CXX_EVALUATION_TOOLS_H #define CXX_EVALUATION_TOOLS_H #include #include "../flint.h" // FLINT_MAX and FLINT_MIN #include "expression_traits.h" #include "mp.h" #include "rules.h" #include "tuple.h" namespace flint { namespace mp { // Find the highest-priority implemented evaluation rule, if any. // TODO move to tools? template struct find_evaluation { private: typedef rules::evaluation r2; typedef rules::evaluation r1; typedef rules::evaluation r0; typedef traits::is_implemented i2; typedef traits::is_implemented i1; typedef traits::is_implemented i0; public: typedef typename mp::select, r2, mp::and_v, r1, mp::and_v, r0 >::type type; }; } // mp namespace tools { namespace tdetail { template struct cmp_invert { static int get(const T& t, const U& u) { return -rules::cmp::get(u, t); } }; } // A version of the cmp rule which tries both argument orders template struct symmetric_cmp : mp::if_ >, rules::cmp, typename mp::if_ >, tdetail::cmp_invert, rules::UNIMPLEMENTED >::type >::type { }; // A version of equals which uses cmp if possible namespace tdetail { template struct equals_using_cmp_ : rules::UNIMPLEMENTED { }; template struct equals_using_cmp_ > >::type> { static bool get(const T& t, const U& u) { return tools::symmetric_cmp::get(t, u) == 0; } }; } // tdetail template struct equals_using_cmp : mp::if_ >, rules::equals, tdetail::equals_using_cmp_ >::type { }; // Automatic printing if to_string is implemented namespace tdetail { template struct print_using_str_ : rules::UNIMPLEMENTED { }; template struct print_using_str_ > >::type> { static void doit(const T& v, std::ostream& o) { int base = 10; std::ios_base::fmtflags ff = o.flags(); if(ff & o.hex) base = 16; if(ff & o.oct) base = 8; o << v.to_string(base); } }; } // tdetail template struct print_using_str : mp::if_ >, rules::print, tdetail::print_using_str_ >::type { }; // Finding a subexpression of precsribed type namespace tdetail { template struct find_subexpr_helper2; template struct find_subexpr_helper { typedef find_subexpr_helper2 fsh; typedef typename fsh::rtype rtype; static const bool val = fsh::val; static rtype get(const Expr& e) {return fsh::get(e._data());} }; template struct find_subexpr_helper >::type> { static const bool val = true; typedef const Expr& rtype; static rtype get(rtype t) {return t;} }; template struct find_subexpr_helper, mp::not_ > > >::type> { static const bool val = false; typedef void rtype; }; template struct find_subexpr_helper2 { typedef find_subexpr_helper2 fsh; typedef typename fsh::rtype rtype; static const bool val = fsh::val; static rtype get(const Data& d) {return fsh::get(d.tail);} }; template struct find_subexpr_helper2, typename mp::enable_if::type> >::type> { static const bool val = true; typedef typename traits::basetype::type head_t; typedef find_subexpr_helper fsh; typedef typename fsh::rtype rtype; static rtype get(const tuple& d) {return fsh::get(d.head);} }; template struct find_subexpr_helper2 { static const bool val = false; typedef void rtype; }; } // tdetail // A predicate which applies if the argument type equals T. template struct equal_types_pred { template struct type : mp::equal_types { }; }; // Given an expression template Expr, traverse the tree of data arguments // until an argument matching the predicate Pred is found. Here pred must have // a member template "type" performing the boolean computation. // See equal_types_pred for an example. // If there is no matching subexpression, a compile time error will be // encountered. // The current implementation performs depth-first search. template inline typename tdetail::find_subexpr_helper::rtype find_subexpr(const Expr& e) { return tdetail::find_subexpr_helper::get(e); } // Find a subexpression of type T. template inline const T& find_subexpr_T(const Expr& e) { return find_subexpr >(e); } // Boolean computation to determine if find_subexpr above will work. template struct has_subexpr : tdetail::find_subexpr_helper { }; // A helper to invoke htuples::fill with instantiate_temporaries namespace tdetail { template struct fill_tmps_helper { const Expr& expr; fill_tmps_helper(const Expr& e) : expr(e) {}; template T create() const {return rules::instantiate_temporaries::get(expr);} }; } // tdetail template tdetail::fill_tmps_helper temporaries_filler(const Expr& e) { return tdetail::fill_tmps_helper(e); } // A helper to "evaluate" a single term, independend of whether or not it is // actually an expression template template struct evaluation_helper { typedef typename traits::basetype::type type; typedef typename traits::forwarding::type ftype; typedef ftype etype; static ftype get(const type& t) {return t;} typedef empty_tuple temporaries_t; }; template struct evaluation_helper >::type> { typedef typename T::evaluated_t type; typedef const typename T::evaluated_t& ftype; typedef type etype; static type get(const T& t) {return t.evaluate();} typedef typename T::ev_traits_t::temp_rule_t::temporaries_t temporaries_t; }; /////////////////////////////////////////////////////////////////////////// // Helper to evaluate n terms /////////////////////////////////////////////////////////////////////////// // The template argument is an arbitrary argument tuple template struct evaluate_n; // Count the number of non-immediate terms in arguments template struct count_nonimm { static const unsigned val = traits::is_lazy_expr::val + count_nonimm::val; }; template<> struct count_nonimm { static const unsigned val = 0; }; template struct evaluated_args_tuple { typedef typename tools::evaluation_helper::ftype evt; typedef typename evaluated_args_tuple::type tail_t; typedef tuple type; }; template<> struct evaluated_args_tuple { typedef empty_tuple type; }; namespace tdetail { // Unoptimized evaluation (in order) // The constructor sets up any local temporaries (coming from non-merging). // Then init does the actual computation. Note that init chains at the end // (in contrast to construction), so we do evaluate in order. template struct evaluate_n_unopt { // case where head is immediate typedef evaluate_n_unopt next_t; typedef typename next_t::temporaries_t temporaries_t; typedef typename Args::head_t headr_t; next_t next; headr_t res; headr_t gethead() const { return res; } void init(const Args& args, temporaries_t temps) { next.init(args.tail, temps); } evaluate_n_unopt(const Args& args) : next(args.tail), res(args.head) {} }; template<> struct evaluate_n_unopt { // basecase typedef empty_tuple temporaries_t; void init(empty_tuple, empty_tuple) {} evaluate_n_unopt(empty_tuple) {} }; template struct evaluate_n_unopt, mp::not_ > > >::type> { // Case with non-merging lazy head typedef evaluate_n_unopt next_t; typedef typename Args::head_t expr_t; typedef typename expr_t::ev_traits_t::temp_rule_t rule_t; typedef typename rule_t::return_t tmp_t; typedef mp::merge_tuple merger; typedef typename merger::type temporaries_t; typedef typename traits::forwarding::type headr_t; next_t next; tmp_t tmp; headr_t gethead() const { return tmp; } evaluate_n_unopt(const Args& args) : next(args.tail), tmp( rules::instantiate_temporaries::get(args.head)) {} void init(const Args& args, temporaries_t temps) { rule_t::doit(args.head._data(), merger::get_first(temps), &tmp); next.init(args.tail, merger::get_second(temps)); } }; template struct evaluate_n_unopt, traits::use_temporary_merging< typename Args::head_t::evaluated_t> > >::type> { // Case with merging lazy head typedef evaluate_n_unopt next_t; typedef typename Args::head_t expr_t; typedef typename expr_t::ev_traits_t::temp_rule_t rule_t; typedef typename rule_t::return_t tmp_t; typedef mp::merge_tuple > merger; typedef typename merger::type temporaries_t; typedef typename traits::forwarding::type headr_t; next_t next; tmp_t* tmp; headr_t gethead() const { return *tmp; } evaluate_n_unopt(const Args& args) : next(args.tail) {} void init(const Args& args, temporaries_t temps) { tmp = merger::get_second(temps).head; rule_t::doit(args.head._data(), merger::get_first(temps), tmp); next.init(args.tail, merger::get_second(temps).tail); } }; template struct unopt_get { typedef unopt_get getn; typedef typename getn::type type; static type get(const evaluate_n_unopt& e) {return getn::get(e.next);} }; template struct unopt_get { typedef evaluate_n_unopt evalt; typedef typename evalt::headr_t type; static type get(const evalt& e) {return e.gethead();} }; template struct unopt_gettuple { typedef unopt_gettuple next; typedef evaluate_n_unopt eval_t; typedef tuple type; static type get(const eval_t& e) { return type(e.gethead(), next::get(e.next)); } }; template<> struct unopt_gettuple { typedef empty_tuple type; template static type get(const T&) {return empty_tuple();} }; // Optimized case with precisely two non-immediates template struct evaluate_n_2_analyze { typedef evaluate_n_2_analyze next; static const unsigned first = next::first + 1; static const unsigned second = next::second + 1; }; template struct evaluate_n_2_analyze >::type> { typedef evaluate_n_2_analyze next; static const unsigned first = 0; static const unsigned second = next::second + 1; }; template struct evaluate_n_2_analyze >::type> { static const unsigned first = 0; static const unsigned second = 0; }; template struct evaluate_2; // Case where neither is immediate, no merging template struct evaluate_2, traits::is_lazy_expr, mp::not_ >, mp::not_ > > >::type> { private: typedef typename Expr1::ev_traits_t::temp_rule_t rule1_t; typedef typename Expr2::ev_traits_t::temp_rule_t rule2_t; public: typedef typename rule1_t::return_t return1_t; typedef typename rule2_t::return_t return2_t; private: typedef typename rule1_t::temporaries_t temporaries1_t; typedef typename rule2_t::temporaries_t temporaries2_t; typedef mp::merge_tuple merger; return1_t tmp1; return2_t tmp2; public: typedef typename merger::type temporaries_t; evaluate_2(temporaries_t temps, const Expr1& e1, const Expr2& e2) : tmp1(rules::instantiate_temporaries::get(e1)), tmp2(rules::instantiate_temporaries::get(e2)) { rule1_t::doit(e1._data(), merger::get_first(temps), &tmp1); rule2_t::doit(e2._data(), merger::get_second(temps), &tmp2); } const return1_t& get1() const {return tmp1;} const return2_t& get2() const {return tmp2;} }; // Case where neither is immediate, first has merging, second does not template struct evaluate_2, traits::is_lazy_expr, traits::use_temporary_merging, mp::not_ > > >::type> { private: typedef typename Expr1::ev_traits_t::temp_rule_t rule1_t; typedef typename Expr2::ev_traits_t::temp_rule_t rule2_t; public: typedef typename rule1_t::return_t return1_t; typedef typename rule2_t::return_t return2_t; private: typedef typename rule1_t::temporaries_t temporaries1_t; typedef typename rule2_t::temporaries_t temporaries2_t; typedef mp::merge_tuple::type, temporaries1_t> merger1; typedef mp::merge_tuple merger2; return2_t tmp2; return1_t* ret1; public: typedef typename merger2::type temporaries_t; evaluate_2(temporaries_t temps, const Expr1& e1, const Expr2& e2) : tmp2(rules::instantiate_temporaries::get(e2)) { rule2_t::doit(e2._data(), merger2::get_second(temps), &tmp2); ret1 = merger1::get_first(merger2::get_first(temps)).head; rule1_t::doit(e1._data(), merger1::get_second(merger2::get_first(temps)), ret1); } const return1_t& get1() const {return *ret1;} const return2_t& get2() const {return tmp2;} }; // Case where neither is immediate, second has merging, first does not template struct evaluate_2, traits::is_lazy_expr, traits::use_temporary_merging, mp::not_ > > >::type> { // XXX this is copy-paste from above case where right is immediate private: typedef evaluate_2 ev2_t; ev2_t ev2; public: typedef typename ev2_t::return1_t return2_t; typedef typename ev2_t::return2_t return1_t; typedef typename ev2_t::temporaries_t temporaries_t; evaluate_2(temporaries_t temps, const Expr1& e1, const Expr2& e2) : ev2(temps, e2, e1) {}; const return1_t& get1() const {return ev2.get2();} const return2_t& get2() const {return ev2.get1();} }; // Case where neither is immediate, all merging template struct evaluate_2, traits::is_lazy_expr, traits::use_temporary_merging, traits::use_temporary_merging > >::type> { private: typedef typename Expr1::ev_traits_t::temp_rule_t rule1_t; typedef typename Expr2::ev_traits_t::temp_rule_t rule2_t; public: typedef typename rule1_t::return_t return1_t; typedef typename rule2_t::return_t return2_t; private: typedef typename rule1_t::temporaries_t temporaries1_t; typedef typename rule2_t::temporaries_t temporaries2_t; template friend struct evaluate_2; // We can either evaluate the Expr1 first and then Expr2, or the other // way round. We would like to choose the most efficient strategy. // Since we have no access to other metrics, we compare the number of // temporaries required (see typedef of doit below). struct doit_1 { typedef mp::merge_tuple::type, temporaries2_t> merger2; typedef mp::merge_tuple, temporaries1_t> merger1; typedef typename merger1::type temporaries_t; static void init(temporaries_t temps, const Expr1& e1, const Expr2& e2, return1_t*& ret1, return2_t*& ret2) { temporaries1_t temps1 = merger1::get_second(temps); temporaries2_t temps2 = merger2::get_second(merger1::get_first(temps).tail); ret1 = merger1::get_first(temps).head; ret2 = merger2::get_first(merger1::get_first(temps).tail).head; rule1_t::doit(e1._data(), temps1, ret1); rule2_t::doit(e2._data(), temps2, ret2); } }; struct doit_2 { typedef typename evaluate_2::doit_1 doit_other; typedef typename doit_other::temporaries_t temporaries_t; static void init(temporaries_t temps, const Expr1& e1, const Expr2& e2, return1_t*& ret1, return2_t*& ret2) { doit_other::init(temps, e2, e1, ret2, ret1); } }; typedef typename mp::if_v< (doit_1::temporaries_t::len <= doit_2::temporaries_t::len), doit_1, doit_2>::type doit; return1_t* ret1; return2_t* ret2; public: typedef typename doit::temporaries_t temporaries_t; evaluate_2(temporaries_t temps, const Expr1& e1, const Expr2& e2) { doit::init(temps, e1, e2, ret1, ret2); } const return1_t& get1() const {return *ret1;} const return2_t& get2() const {return *ret2;} }; template struct evaluate_n_2_get { template static typename mp::tuple_get::type get(const Args& args, const First&, const Second&) { return mp::tuple_get::get(args); } }; template struct evaluate_n_2_get { template static const First& get(const Args&, const First& f, const Second&) { return f; } }; template struct evaluate_n_2_get { template static const Second& get(const Args&, const First&, const Second& s) { return s; } }; template struct evaluate_n_2_gettuple { template static Tuple get(const T& t) { return Tuple(t.template get(), evaluate_n_2_gettuple::get(t)); } }; template struct evaluate_n_2_gettuple { template static empty_tuple get(const T&) {return empty_tuple();} }; } // tdetail template struct evaluate_n { typedef tdetail::evaluate_n_unopt eval_t; typedef typename eval_t::temporaries_t temporaries_t; typedef typename tdetail::unopt_gettuple::type evtup_t; eval_t eval; evaluate_n(const Args& args, temporaries_t temps) : eval(args) { eval.init(args, temps); } template typename tdetail::unopt_get::type get() const { return tdetail::unopt_get::get(eval); } evtup_t gettuple() const { return tdetail::unopt_gettuple::get(eval); } }; template struct evaluate_n::val == 2>::type> { typedef tdetail::evaluate_n_2_analyze analysis; static const unsigned first = analysis::first; static const unsigned second = analysis::second; typedef mp::tuple_get getfirst; typedef mp::tuple_get getsecond; typedef typename getfirst::type first_t; typedef typename getsecond::type second_t; typedef tdetail::evaluate_2 ev_t; typedef typename ev_t::temporaries_t temporaries_t; const Args& args; ev_t ev; evaluate_n(const Args& a, temporaries_t temps) : args(a), ev(temps, getfirst::get(a), getsecond::get(a)) {} typedef typename evaluated_args_tuple::type evtup_t; template typename mp::tuple_get::type get() const { return tdetail::evaluate_n_2_get::get( args, ev.get1(), ev.get2()); } evtup_t gettuple() const { return tdetail::evaluate_n_2_gettuple::get(*this); } }; /////////////////////////////////////////////////////////////////////////// // Helper to evaluate three homogeneous terms /////////////////////////////////////////////////////////////////////////// // // Evaluation using ternary operators is actually surprisingly hard. // Consider e.g. a + b*c. The number of temporaries needed for this depends // on whether or not b, c are immediates, and on the numbers of temporaries // needed for each non-immediate expression. namespace tdetail { // This struct deals with the difficulties in whether b or c might be // immediate. template struct ternary_hhelper; // To be specialised below. } // tdetail // The following struct can be used to simplify writing evaluation rules which // use ternary operations (addmul, submul). // // In the situation of a + b*c, the optimization can be applied if // - the result goes to a temporary (i.e. we can write to it prematurely) // - a is not an immediate // - a, b, c are of the same type, and addmul is available for this type // If so, one needs to evaluate a into the return location and b, c into // temporaries; after that addmul can be applied. // // The ternary_helper facilitates both the checking if we are in the right // situation and the intermediate evaluations. Instantiate it with // "T" being your ground type (for which addmul is implemented), "Left" the type // of a, "Right1" the type of b and "Right2" the type of c. // Then the member enable::type can be used in SFINAE situations to // conditionally enable a template only if we are in the addmul situation. // The member type "temporaries_t" and static member function "doit" can be used // to evaluate the intermediate terms. // // It may sometimes be useful to preclude a certain type of expression for a. // (E.g. one needs rules for both a + b*c and b*c + a, but then which of these // applies to b*c + a*d?) To do this, pass the operation you want to exclude in // "disable_op". // // NOTE: in the current implementation, ternary_helper only works with // *homogeneous* expressions. These are defined to be expressions evaluating to // type T, which only need temporaries of type T. // This condition is included in the checks done by the enable member type. // NOTE: This implementation does not honor use_temporary_merging! // template struct ternary_helper { }; template struct ternary_helper, traits::is_expression::type>, traits::is_expression::type> > >::type> { typedef typename traits::basetype::type right1_t; typedef typename traits::basetype::type right2_t; typedef typename Left::ev_traits_t::temp_rule_t evl; typedef tools::evaluation_helper evhr1; typedef tools::evaluation_helper evhr2; typedef mp::enable_if, traits::is_homogeneous_tuple, traits::is_homogeneous_tuple, traits::is_homogeneous_tuple< typename mp::make_tuple< typename evl::return_t, typename evhr1::type, typename evhr2::type>::type, T>, mp::not_ > > > enable; typedef tdetail::ternary_hhelper::val, traits::is_immediate::val> inner; typedef typename inner::temporaries_t temporaries_t; // evaluate left into res, rigth1 and right2 to arbitrary location, // set toright1, toright2 to these locations static void doit(const Left& left, const right1_t& right1, const right2_t& right2, temporaries_t temps, T* res, const T*& toright1, const T*& toright2) { inner::doit(left, right1, right2, temps, res, toright1, toright2); } }; namespace tdetail { // Case where both are immediate. template struct ternary_hhelper { typedef typename Left::ev_traits_t::temp_rule_t evl; static const unsigned norig = evl::temporaries_t::len; static const unsigned ntemps = FLINT_MAX(norig, 1); typedef typename mp::make_homogeneous_tuple::type temporaries_t; static void doit(const Left& left, const right1_t& right1, const right2_t& right2, temporaries_t temps, T* res, const T*& toright1, const T*& toright2) { evl::doit(left._data(), mp::htuples::extract(temps), res); toright1 = &right1; toright2 = &right2; } }; // If c is immediate but b is not, there are still two subcases. // Let t1 be the number of temporaries needed to evaluate a, and // t2 the number for b. If t1 >= t2, then we need to evaluate a first. // Otherwise b. // In any case, the number of temporaries is at least two (for the two return // values), and generically equal to the maximum of t1 and t2. If however // t1 == t2, then we need an additional temporary. template struct ternary_hhelper_1imm; // Case where t1 >= t2 template struct ternary_hhelper_1imm { typedef typename Left::ev_traits_t::temp_rule_t evl; typedef typename right1_t::ev_traits_t::temp_rule_t evr; static const unsigned t1 = evl::temporaries_t::len; static const unsigned t2 = evr::temporaries_t::len; // t1 >= t2 template static void doit(const Left& left, const right1_t& right1, Temps temps, T* res, const T*& toright1) { evl::doit(left._data(), mp::htuples::extract(temps), res); typename Temps::tail_t nores = mp::htuples::removeres(temps, res); evr::doit(right1._data(), mp::htuples::extract(nores), nores.head); toright1 = nores.head; } }; // Case where t1 < t2 template struct ternary_hhelper_1imm { typedef typename Left::ev_traits_t::temp_rule_t evl; typedef typename right1_t::ev_traits_t::temp_rule_t evr; static const unsigned t1 = evl::temporaries_t::len; static const unsigned t2 = evr::temporaries_t::len; // t1 < t2 template static void doit(const Left& left, const right1_t& right1, Temps temps, T* res, const T*& toright1) { typedef typename Temps::tail_t tail_t; tail_t nores = mp::htuples::removeres(temps, res); evr::doit(right1._data(), mp::htuples::extract(temps), nores.head); toright1 = nores.head; evl::doit(left._data(), mp::htuples::extract(tail_t(res, nores.tail)), res); } }; // Case where c is immediate. template struct ternary_hhelper { typedef typename Left::ev_traits_t::temp_rule_t evl; typedef tools::evaluation_helper evhr1; static const unsigned t1 = evl::temporaries_t::len; static const unsigned t2 = evhr1::temporaries_t::len; static const unsigned ntemps = FLINT_MAX(2, FLINT_MAX(t1, t2) + (t1 == t2)); typedef ternary_hhelper_1imm= t2> thh1; typedef typename mp::make_homogeneous_tuple::type temporaries_t; static void doit(const Left& left, const right1_t& right1, const right2_t& right2, temporaries_t temps, T* res, const T*& toright1, const T*& toright2) { toright2 = &right2; thh1::doit(left, right1, temps, res, toright1); } }; // Case where b is immediate. template struct ternary_hhelper { typedef ternary_hhelper thh; typedef typename thh::temporaries_t temporaries_t; static void doit(const Left& left, const right1_t& right1, const right2_t& right2, temporaries_t temps, T* res, const T*& toright1, const T*& toright2) { thh::doit(left, right2, right1, temps, res, toright2, toright1); } }; // Case where neither is immediate. template struct ternary_hhelper { typedef typename Left::ev_traits_t::temp_rule_t evl; typedef typename right1_t::ev_traits_t::temp_rule_t evr1; typedef typename right2_t::ev_traits_t::temp_rule_t evr2; static const unsigned t1 = evl::temporaries_t::len; static const unsigned t2 = evr1::temporaries_t::len; static const unsigned t3 = evr2::temporaries_t::len; // m1, m2, m3 is t1, t2, t3 reordered s.t. m1 >= m2 >= m3 static const unsigned m1 = FLINT_MAX(t1, FLINT_MAX(t2, t3)); static const unsigned m3 = FLINT_MIN(t1, FLINT_MIN(t2, t3)); static const unsigned m2 = t1 + t2 + t3 - m1 - m3; // The following is obtained by case analysis static const unsigned ntemps = (t1 == t2 && t2 == t3) ? FLINT_MAX(3, t1+2) : // all equal ((m1 > m2 && m2 > m3) ? FLINT_MAX(3, m1) : // all distinct (m1 == m2 ? FLINT_MAX(m1+1, 3) // first two equal : FLINT_MAX(m1, FLINT_MAX(m2+2, 3)))); // second two equal typedef typename mp::make_homogeneous_tuple::type temporaries_t; struct resaccess { T* res; resaccess(T* r) : res(r) {}; template typename Temps::tail_t doit(const Data& d, Temps temps) { Eval::doit(d, mp::htuples::extract(temps), res); return mp::htuples::extract(temps); } }; struct toaccess { const T*& right; toaccess(const T*& r) : right(r) {}; template typename Temps::tail_t doit(const Data& d, Temps temps) { Eval::doit(d, mp::htuples::extract(temps), temps.head); right = temps.head; return temps.tail; } }; struct doit_really { template static void doit(const E1& e1, const E2& e2, const E3& e3, temporaries_t temps, A1 a1, A2 a2, A3 a3) { typedef typename E1::ev_traits_t::temp_rule_t ev1; typedef typename E2::ev_traits_t::temp_rule_t ev2; typedef typename E3::ev_traits_t::temp_rule_t ev3; a3.template doit(e3._data(), a2.template doit(e2._data(), a1.template doit(e1._data(), temps))); } }; struct dont_doit { template static void doit(const E1& e1, const E2& e2, const E3& e3, temporaries_t temps, A1 a1, A2 a2, A3 a3) { } }; template static void doit_sort(const E1& e1, const E2& e2, const E3& e3, temporaries_t temps, A1 a1, A2 a2, A3 a3) { typedef typename E1::ev_traits_t::temp_rule_t ev1; typedef typename E2::ev_traits_t::temp_rule_t ev2; typedef typename E3::ev_traits_t::temp_rule_t ev3; static const unsigned u1 = ev1::temporaries_t::len; static const unsigned u2 = ev2::temporaries_t::len; static const unsigned u3 = ev3::temporaries_t::len; if(u1 < u2) return doit_sort(e2, e1, e3, temps, a2, a1, a3); if(u2 < u3) return doit_sort(e1, e3, e2, temps, a1, a3, a2); // If we reach this point, u1 >= u2 >= u3. // However, even if this is not the case, the following line (and // everything it instantiates) still has to compile. mp::if_v<(u1 >= u2 && u2 >= u3), doit_really, dont_doit>::type::doit( e1, e2, e3, temps, a1, a2, a3); } static void doit(const Left& left, const right1_t& right1, const right2_t& right2, temporaries_t temps, T* res, const T*& toright1, const T*& toright2) { // We re-order the temporaries in such a way that res is at the // very end. When evaluating things in the correct order, it is then // always correct to take temporaries from the front, and drop them // from the front. temporaries_t temps_reordered = mp::concat_tuple< typename temporaries_t::tail_t, typename mp::make_tuple::type>::doit( mp::htuples::removeres(temps, res), mp::make_tuple::make(res)); doit_sort(left, right1, right2, temps_reordered, resaccess(res), toaccess(toright1), toaccess(toright2)); } }; } // tdetail // A helper condition for use with FLINT_DEFINE_*_COND? template struct is_bool : mp::equal_types { }; } // tools } // flint #endif flint2-2.8.4/flintxx/expression.h000066400000000000000000000716641414523752600170160ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_EXPRESSION_H #define CXX_EXPRESSION_H // TODO // * static asserts #include #include #include #include "evaluation_tools.h" #include "expression_traits.h" #include "mp.h" #include "rules.h" #include "traits.h" #include "tuple.h" namespace flint { namespace detail { // Helper traits used by the "expression" class, in particular the evaluate() // method. This is the general (i.e. non-immediate) case, // which requires actual work. template struct evaluation_traits { typedef typename Expr::derived_t derived_t; typedef typename mp::find_evaluation< Operation, Data, false>::type rule_t; typedef typename mp::find_evaluation< Operation, Data, true>::type temp_rule_t; typedef typename rule_t::return_t evaluation_return_t; typedef evaluation_return_t evaluated_t; static evaluation_return_t evaluate(const derived_t& from) { evaluated_t res = rules::instantiate_temporaries::get(from); evaluate_into_fresh(res, from); return res; } template static void evaluate_into(T& to, const derived_t& from) { typedef mp::back_tuple back_t; typename back_t::type temps_backing = mp::htuples::fill( tools::temporaries_filler(from)); typename rule_t::temporaries_t temps; back_t::init(temps, temps_backing, 0); rule_t::doit(from._data(), temps, &to); } static void evaluate_into_fresh(evaluation_return_t& to, const derived_t& from) { typedef mp::back_tuple< typename temp_rule_t::temporaries_t, evaluation_return_t > back_t; typename back_t::type temps_backing = mp::htuples::fill( tools::temporaries_filler(from)); typename temp_rule_t::temporaries_t temps; back_t::init(temps, temps_backing, &to); temp_rule_t::doit(from._data(), temps, &to); } }; // This is the special case of an immediate argument, where "evaluation" is // at most assignment. template struct evaluation_traits { typedef typename Expr::derived_t derived_t; typedef typename Expr::derived_t evaluated_t; typedef evaluated_t& evaluation_return_t; static evaluated_t& evaluate(derived_t& d) {return d;} static const evaluated_t& evaluate(const derived_t& d) {return d;} template static void evaluate_into(T& to, const derived_t& from) { rules::assignment::doit(to, from); } static void evaluate_into_fresh(derived_t& to, const derived_t& from) { evaluate_into(to, from); } }; } // detail // The main expression template class. // // The argument Derived must have the following form: // struct derived // { // template // struct type // { // typedef XYZ result; // }; // }; // See derived_wrapper below for a common example. // // Note that, while Data does not have to be default constructible, // it *does* need to be copy-constructible, and have a working destructor. template class expression { private: Data data; protected: explicit expression(const Data& d) : data(d) {} public: // internal -- see is_expression implementation. typedef void IS_EXPRESSION_MARKER; typedef detail::evaluation_traits ev_traits_t; typedef typename Derived::template type::result derived_t; typedef typename ev_traits_t::evaluated_t evaluated_t; typedef typename ev_traits_t::evaluation_return_t evaluation_return_t; typedef Data data_t; typedef Operation operation_t; private: derived_t& downcast() {return *static_cast(this);} const derived_t& downcast() const { return *static_cast(this); } // Some helpers for initialization, since it is not possible to // conditionally enable constructors in C++98 template static data_t get_data(const T& t, typename mp::disable_if >::type* = 0) { return data_t(t); } template static data_t get_data(T& t, typename mp::disable_if >::type* = 0) { return data_t(t); } template static data_t get_data(const T& t, typename mp::enable_if >::type* = 0, typename mp::disable_if< mp::equal_types >::type* = 0) { return data_t(t.evaluate()); } template static data_t get_data(const T& t, typename mp::enable_if >::type* = 0, typename mp::enable_if< mp::equal_types >::type* = 0) { return data_t(t.evaluate()._data()); } // Invoke the data copy constructor when appropriate static data_t get_data(const derived_t& o) { return data_t(o._data()); } static data_t get_data(derived_t& o) { return data_t(o._data()); } // Having the empty constructor here delays its instantiation, and allows // compiling even if data is *not* default constructible. static data_t get_data() {return data_t();} public: // forwarded constructors template explicit expression(const T& t) : data(get_data(t)) {} template explicit expression(T& t) : data(get_data(t)) {} template expression(const T& t, const U& u) : data(t, u) {} template expression(T& t, const U& u) : data(t, u) {} template expression(const T& t, const U& u, const V& v) : data(t, u, v) {} template expression(T& t, const U& u, const V& v) : data(t, u, v) {} template expression(const T& t, const U& u, const V& v, const W& w) : data(t, u, v, w) {} template expression(T& t, const U& u, const V& v, const W& w) : data(t, u, v, w) {} expression() : data(get_data()) {} expression& operator=(const expression& o) { this->set(o.downcast()); return *this; } // See rules::instantiate_temporaries for explanation. evaluated_t create_temporary() const { return evaluated_t(); } Data& _data() {return data;} const Data& _data() const {return data;} void print(std::ostream& o) const { tools::print_using_str::doit(evaluate(), o); } std::string to_string(int base = 10) const { return rules::to_string::get(evaluate(), base); } template T to() const { return rules::conversion::get(evaluate()); } int print(FILE* f = stdout) const { return rules::cprint::doit(f, evaluate()); } int print_pretty(FILE* f = stdout) const { return rules::print_pretty::doit(f, evaluate()); } template int print_pretty(const T& extra, FILE* f = stdout) const { return rules::print_pretty::doit(f, evaluate(), extra); } int read(FILE* f = stdin) { return rules::read::doit(f, downcast()); } typename traits::make_const::type evaluate() const { return ev_traits_t::evaluate(downcast()); } evaluation_return_t evaluate() {return ev_traits_t::evaluate(downcast());} template void set(const T& t, typename mp::enable_if >::type* = 0, typename mp::enable_if >::type* = 0) { T::ev_traits_t::evaluate_into(downcast(), t); } template void set(const T& t, typename mp::enable_if >::type* = 0, typename mp::disable_if >::type* = 0) { rules::assignment::doit( downcast(), t.evaluate()); } template void set(const T& t, typename mp::disable_if >::type* = 0) { rules::assignment::doit(downcast(), t); } template bool equals(const T& t, typename mp::enable_if >::type* = 0) const { return equals(t.evaluate()); } template bool equals(const T& t, typename mp::disable_if >::type* = 0) const { return tools::equals_using_cmp::get(evaluate(), t); } template struct make_helper { typedef typename Derived::template type::result type; static type make(const NData& ndata) { return type(ndata); } }; }; // If your expression template is of the form // template // class my_expression ... // then derived_wrapper is a valid argument for Derived in // the expression class above. template class Derived> struct derived_wrapper { template struct type { typedef Derived result; }; }; // If your expression template is of the form // template // class my_expression2 ... // where Extra is some extra information which should be passed on unchanged, // then derived_wrapper2 is a valid argument for Derived // in the expression class above. template class Derived, class Extra> struct derived_wrapper2 { template struct type { typedef Derived result; }; }; // operators namespace detail { // These traits determine how arguments of an expression template are stored. // E.g. (e1 + e2) yields a new expression template with a two-argument tuple // as Data. If e1 is an immediate, then we want to (usually) store it by // reference, to avoid copies. If not, we can just store by value (since // copying e1 just copies the references anyway) and avoid indirection. // (Similarly for e2.) template struct storage_traits : mp::if_< traits::is_immediate, typename traits::forwarding::type, Expr > { }; // See tuple.h. template<> struct storage_traits {typedef detail::UNUSED type;}; template struct nary_op_helper_step2 { typedef typename ev_t::return_t Expr; typedef typename Expr::template make_helper make_helper; typedef typename make_helper::type return_t; }; template struct nary_op_helper_step2 { struct return_t { }; struct make_helper { }; }; // Helper to determine the return type of an expression, where Data is already // the correct tuple type. // The step1/step2 splitting above is necessary to avoid compiler errors in // case there is not actually any rule. template struct nary_op_helper { typedef typename mp::find_evaluation::type ev_t; typedef nary_op_helper_step2 nohs2; typedef typename nohs2::return_t return_t; typedef typename nohs2::make_helper make_helper; typedef traits::is_implemented cond; typedef mp::enable_if enable; }; template struct nary_op_helper_maker : nary_op_helper { typedef Maker maker; }; #define FLINTXX_NARY_OP_HELPER_MACRO(arg) typename storage_traits< arg >::type // nary_op_helper invokes nary_op_helper with the correct // tuple type as argument. template struct nary_op_helper2 : nary_op_helper_maker > { typedef nary_op_helper2 noh2; static typename noh2::return_t make(FLINTXX_MAKE_TUPLE_FUNC_ARGS) { return noh2::make_helper::make(noh2::maker::make( FLINTXX_MAKE_TUPLE_FUNC_ARG_NAMES)); } }; // Special casing for binary operators. template struct binary_op_helper : nary_op_helper2 { }; // Special casing for unary operations. template struct unary_op_helper : nary_op_helper2 { }; // For unary member operators, determining the return type the normal way can // lead to cyclic dependencies. See FLINTXX_DEFINE_MEMBER_UNOP_RTYPE. template struct unary_op_helper_with_rettype { typedef mp::make_tuple::type> maker; typedef typename Ret::template make_helper< Op, typename maker::type>::type return_t; }; // Common helper for implementing comparison operators. template struct order_op_helper { typedef typename tools::evaluation_helper::type ev1_t; typedef typename tools::evaluation_helper::type ev2_t; typedef tools::symmetric_cmp scmp; typedef mp::enable_if< mp::and_< traits::is_implemented, mp::or_< traits::is_expression, traits::is_expression > >, bool> enable; static int get(const Expr1& e1, const Expr2& e2) { return scmp::get(tools::evaluation_helper::get(e1), tools::evaluation_helper::get(e2)); } }; } // detail template inline typename mp::enable_if, std::ostream&>::type operator<<(std::ostream& o, const Expr& e) { e.print(o); return o; } template inline typename mp::enable_if, bool>::type operator==(const Expr1& e1, const Expr2& e2) { return e1.equals(e2); } template inline typename mp::enable_if >, traits::is_expression >, bool>::type operator==(const Expr1& e1, const Expr2& e2) { return e2.equals(e1); } template inline typename mp::enable_if, traits::is_expression >, bool>::type operator!=(const Expr1& e1, const Expr2& e2) { return !(e1 == e2); } template inline typename detail::order_op_helper::enable::type operator<(const Expr1& e1, const Expr2& e2) { return detail::order_op_helper::get(e1, e2) < 0; } template inline typename detail::order_op_helper::enable::type operator<=(const Expr1& e1, const Expr2& e2) { return detail::order_op_helper::get(e1, e2) <= 0; } template inline typename detail::order_op_helper::enable::type operator>(const Expr1& e1, const Expr2& e2) { return detail::order_op_helper::get(e1, e2) > 0; } template inline typename detail::order_op_helper::enable::type operator>=(const Expr1& e1, const Expr2& e2) { return detail::order_op_helper::get(e1, e2) >= 0; } template inline typename detail::binary_op_helper< Expr1, operations::plus, Expr2>::enable::type operator+(const Expr1& e1, const Expr2& e2) { return detail::binary_op_helper::make(e1, e2); } template inline typename detail::binary_op_helper< Expr1, operations::minus, Expr2>::enable::type operator-(const Expr1& e1, const Expr2& e2) { return detail::binary_op_helper::make(e1, e2); } template inline typename detail::binary_op_helper< Expr1, operations::times, Expr2>::enable::type operator*(const Expr1& e1, const Expr2& e2) { return detail::binary_op_helper::make(e1, e2); } template inline typename detail::binary_op_helper< Expr1, operations::divided_by, Expr2>::enable::type operator/(const Expr1& e1, const Expr2& e2) { return detail::binary_op_helper::make(e1, e2); } template inline typename detail::binary_op_helper< Expr1, operations::modulo, Expr2>::enable::type operator%(const Expr1& e1, const Expr2& e2) { return detail::binary_op_helper::make(e1, e2); } template inline typename detail::binary_op_helper< Expr1, operations::binary_and, Expr2>::enable::type operator&(const Expr1& e1, const Expr2& e2) { return detail::binary_op_helper::make(e1, e2); } template inline typename detail::binary_op_helper< Expr1, operations::binary_or, Expr2>::enable::type operator|(const Expr1& e1, const Expr2& e2) { return detail::binary_op_helper::make(e1, e2); } template inline typename detail::binary_op_helper< Expr1, operations::binary_xor, Expr2>::enable::type operator^(const Expr1& e1, const Expr2& e2) { return detail::binary_op_helper::make(e1, e2); } template inline typename detail::binary_op_helper< Expr1, operations::shift, Expr2>::enable::type operator<<(const Expr1& e1, const Expr2& e2) { return detail::binary_op_helper::make(e1, e2); } template inline typename detail::binary_op_helper< Expr1, operations::shift, Expr2>::enable::type operator>>(const Expr1& e1, const Expr2& e2) { return detail::binary_op_helper::make(e1, -e2); } template inline typename detail::unary_op_helper::enable::type operator-(const Expr& e) { return detail::unary_op_helper::make(e); } template inline typename detail::unary_op_helper::enable::type operator~(const Expr& e) { return detail::unary_op_helper::make(e); } template inline typename mp::enable_if, Expr1&>::type operator+=(Expr1& e1, const Expr2& e2) { e1.set(e1 + e2); return e1; } template inline typename mp::enable_if, Expr1&>::type operator-=(Expr1& e1, const Expr2& e2) { e1.set(e1 - e2); return e1; } template inline typename mp::enable_if, Expr1&>::type operator*=(Expr1& e1, const Expr2& e2) { e1.set(e1 * e2); return e1; } template inline typename mp::enable_if, Expr1&>::type operator/=(Expr1& e1, const Expr2& e2) { e1.set(e1 / e2); return e1; } template inline typename mp::enable_if, Expr1&>::type operator%=(Expr1& e1, const Expr2& e2) { e1.set(e1 % e2); return e1; } template inline typename mp::enable_if, Expr1&>::type operator|=(Expr1& e1, const Expr2& e2) { e1.set(e1 | e2); return e1; } template inline typename mp::enable_if, Expr1&>::type operator&=(Expr1& e1, const Expr2& e2) { e1.set(e1 & e2); return e1; } template inline typename mp::enable_if, Expr1&>::type operator^=(Expr1& e1, const Expr2& e2) { e1.set(e1 ^ e2); return e1; } // c-style IO template typename mp::enable_if >, int>::type print(const T& t) { return t.print(); } template typename mp::enable_if >, int>::type print(FILE* f, const T& t) { return t.print(f); } template typename mp::enable_if >, int>::type print_pretty(const T& t, const U& extra) { return t.print_pretty(extra); } template typename mp::enable_if >, int>::type print_pretty(FILE* f, const T& t, const U& extra) { return t.print_pretty(extra, f); } template typename mp::enable_if >, int>::type print_pretty(const T& t) { return t.print_pretty(); } template typename mp::enable_if >, int>::type print_pretty(FILE* f, const T& t) { return t.print_pretty(f); } template typename mp::enable_if >, int>::type read(T& t) { return t.read(); } template typename mp::enable_if >, int>::type read(FILE* f, T& t) { return t.read(f); } // TODO move to std? template inline typename mp::enable_if > >::type swap(Expr1& e1, Expr2& e2) { rules::swap::doit(e1, e2); } } // TODO remove this? #include "default_rules.h" //////////////////////////////////////////////////////////////////////// // HELPER MACROS //////////////////////////////////////////////////////////////////////// // To be called in any namespace // Make the binary operation "name" available in current namespace #define FLINT_DEFINE_BINOP_HERE(name) \ template \ inline typename ::flint::detail::binary_op_helper<\ T1, ::flint::operations::name##_op, T2>::enable::type \ name(const T1& t1, const T2& t2) \ { \ return ::flint::detail::binary_op_helper< \ T1, ::flint::operations::name##_op, T2>::make(t1, t2); \ } // Make the unary operation "name" available in current namespace #define FLINT_DEFINE_UNOP_HERE(name) \ template \ inline typename ::flint::detail::unary_op_helper<\ ::flint::operations::name##_op, T1>::enable::type \ name(const T1& t1) \ { \ return ::flint::detail::unary_op_helper< ::flint::operations::name##_op, T1>::make(t1); \ } // Make the threeary operation "name" available in current namespace #define FLINT_DEFINE_THREEARY_HERE(name) \ template \ inline typename ::flint::detail::nary_op_helper2<\ ::flint::operations::name##_op, T1, T2, T3>::enable::type \ name(const T1& t1, const T2& t2, const T3& t3) \ { \ return ::flint::detail::nary_op_helper2< \ ::flint::operations::name##_op, T1, T2, T3>::make(t1, t2, t3); \ } // Make the threeary operation "name" available in current namespace, // but with only two arguments, the second of which is of type type1 and // defaults to val1, and the third argument always (implicitly) of type type2 // and value val2. // The suggested usage of this macro is to first call FLINT_DEFINE_THREEARY_HERE, // and then call FLINT_DEFINE_THREEARY_HERE_2DEFAULT. The effect will be an // operation which can be invoked with 1, 2 or 3 arguments. #define FLINT_DEFINE_THREEARY_HERE_2DEFAULT(name, type1, val1, type2, val2) \ template \ inline typename ::flint::detail::nary_op_helper2<\ ::flint::operations::name##_op, T1, type1, type2 >::enable::type \ name(const T1& t1, type1 t2 = val1) \ { \ return ::flint::detail::nary_op_helper2< \ ::flint::operations::name##_op, T1, type1, type2>::make(t1, t2, val2); \ } // Make the fourary operation "name" available in current namespace #define FLINT_DEFINE_FOURARY_HERE(name) \ template \ inline typename ::flint::detail::nary_op_helper2<\ ::flint::operations::name##_op, T1, T2, T3, T4>::enable::type \ name(const T1& t1, const T2& t2, const T3& t3, const T4& t4) \ { \ return ::flint::detail::nary_op_helper2< \ ::flint::operations::name##_op, T1, T2, T3, T4>::make(t1, t2, t3, t4); \ } // Make the fiveary operation "name" available in current namespace #define FLINT_DEFINE_FIVEARY_HERE(name) \ template \ inline typename ::flint::detail::nary_op_helper2<\ ::flint::operations::name##_op, T1, T2, T3, T4, T5>::enable::type \ name(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) \ { \ return ::flint::detail::nary_op_helper2< \ ::flint::operations::name##_op, T1, T2, T3, T4, T5>::make(t1, t2, t3, t4, t5); \ } // Make the sixary operation "name" available in current namespace #define FLINT_DEFINE_SIXARY_HERE(name) \ template \ inline typename ::flint::detail::nary_op_helper2<\ ::flint::operations::name##_op, T1, T2, T3, T4, T5, T6>::enable::type \ name(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6) \ { \ return ::flint::detail::nary_op_helper2< \ ::flint::operations::name##_op, T1, T2, T3, T4, T5, T6>::make(t1, t2, t3, t4, t5, t6); \ } // Make the sevenary operation "name" available in current namespace #define FLINT_DEFINE_SEVENARY_HERE(name) \ template \ inline typename ::flint::detail::nary_op_helper2<\ ::flint::operations::name##_op, T1, T2, T3, T4, T5, T6, T7>::enable::type \ name(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6, const T7& t7) \ { \ return ::flint::detail::nary_op_helper2< \ ::flint::operations::name##_op, T1, T2, T3, T4, T5, T6, T7>::make(t1, t2, t3, t4, t5, t6, t7); \ } // This set of macros should be called in namespace flint. // Introduce a new binary operation called "name" // NB: because of ADL bugs in g++ <= 4.4, the operation tag is called "name_op", // whereas the function corresponding to it is just called "name" #define FLINT_DEFINE_BINOP(name) \ namespace operations { \ struct name##_op { }; \ } \ FLINT_DEFINE_BINOP_HERE(name) // This macro can be used to conditionally enable a function, and is mostly // used for forwarding. // A typical usage is // template // FLINT_BINOP_ENABLE_RETTYPE(myop, T, U) myop_other(const T& t, const U& u) // { // // perhaps something more interesting // return myop(t, u); // } #define FLINT_BINOP_ENABLE_RETTYPE(name, T1, T2) \ typename detail::binary_op_helper::enable::type // Introduce a new unary operation called "name" #define FLINT_DEFINE_UNOP(name) \ namespace operations { \ struct name##_op { }; \ } \ FLINT_DEFINE_UNOP_HERE(name) #define FLINT_UNOP_ENABLE_RETTYPE(name, T) \ typename detail::unary_op_helper::return_t // See FLINTXX_DEFINE_MEMBER_UNOP_RTYPE #define FLINT_UNOP_BUILD_RETTYPE(name, rettype, T) \ typename detail::unary_op_helper_with_rettype::return_t #define FLINT_DEFINE_THREEARY(name) \ namespace operations { \ struct name##_op { }; \ } \ FLINT_DEFINE_THREEARY_HERE(name) #define FLINT_THREEARY_ENABLE_RETTYPE(name, T1, T2, T3) \ typename detail::nary_op_helper2::enable::type #define FLINT_DEFINE_FOURARY(name) \ namespace operations { \ struct name##_op { }; \ } \ FLINT_DEFINE_FOURARY_HERE(name) #define FLINT_FOURARY_ENABLE_RETTYPE(name, T1, T2, T3, T4) \ typename detail::nary_op_helper2::enable::type #define FLINT_DEFINE_FIVEARY(name) \ namespace operations { \ struct name##_op { }; \ } \ FLINT_DEFINE_FIVEARY_HERE(name) #define FLINT_FIVEARY_ENABLE_RETTYPE(name, T1, T2, T3, T4, T5) \ typename detail::nary_op_helper2::enable::type #define FLINT_DEFINE_SIXARY(name) \ namespace operations { \ struct name##_op { }; \ } \ FLINT_DEFINE_SIXARY_HERE(name) #define FLINT_DEFINE_SEVENARY(name) \ namespace operations { \ struct name##_op { }; \ } \ FLINT_DEFINE_SEVENARY_HERE(name) #endif flint2-2.8.4/flintxx/expression_traits.h000066400000000000000000000052161414523752600203720ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // This file contains helpers recognising expression templates #ifndef CXX_EXPRESSION_TRAITS_H #define CXX_EXPRESSION_TRAITS_H #include "mp.h" #include "traits.h" namespace flint { namespace operations { // These are the operation tags the expression class creates directly. // unary operations struct immediate { }; struct negate { }; struct complement { }; // binary operations struct plus { }; struct minus { }; struct times { }; struct divided_by { }; struct modulo { }; struct shift { }; // left struct binary_and { }; struct binary_or { }; struct binary_xor { }; } // operations namespace traits { template struct is_expression : mp::false_ { }; template struct is_expression : mp::true_ { }; template struct _is_immediate_expr : _is_convertible< typename basetype::type::operation_t, operations::immediate > { }; // Compute if T is an expression, with operation "immediate" template struct is_immediate_expr : _is_immediate_expr { }; template struct is_immediate_expr > >::type> : mp::false_ { }; // Compute if T is an immediate expression, *or not an expression at all* template struct is_immediate : mp::or_ >, is_immediate_expr > { }; // Compute if T is a non-immediate expression template struct is_lazy_expr : mp::and_, mp::not_ > > { }; // Compute if Expr is an expression with prescribed evaluated type "T" template struct is_T_expr : mp::equal_types { }; template struct is_T_expr >::type> : false_ { }; // Decide if an expressing yielding From can be directly evaluated into To. // To be further specialised! template struct can_evaluate_into : mp::false_ { }; template struct can_evaluate_into : mp::true_ { }; // Decide if we should use temporary merging template struct use_temporary_merging : mp::true_ { }; } // traits } // flint #endif flint2-2.8.4/flintxx/flint_classes.h000066400000000000000000001034321414523752600174350ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // Helpers to define concrete subclasses of expression. // Contrary to other parts of this library, they are tailored very // specifically towards FLINT. #include "../flint.h" #include "mp.h" #include "expression.h" #include "expression_traits.h" #include "evaluation_tools.h" #include "tuple.h" #ifndef CXX_FLINT_CLASSES_H #define CXX_FLINT_CLASSES_H // Flint classes distinguish themselves from "ordinary" expression template // classes by a public typedef IS_FLINT_CLASS (see also FLINTXX_DEFINE_BASICS // below). Most functionality in this header disables itself when used on a // non-flint class. // For all flint classes, Data of immediates must have typedefs data_ref_t and // data_srcref_t. // The immediates of any flint class come in three "flavours": ordinary, ref // and srcref. Most of the classes below are used to convert these flavours. // In order for this to work, the expression template class must contain a // public typedef c_base_t which is the underlying "basic" C type (so not the // length one array that is usually used), e.g. fmpz_poly_struct. Conversion to // reference type then yields expression templates which have Data set to // ref_data or srcref_data. These implementation work as // long as all data is stored in c_base_t. If not (e.g. for padic, where there // is an additional reference to the context), ref_data and srcref_data have to // be specialised appropriately. namespace flint { namespace flint_classes { template struct ref_data { typedef void IS_REF_OR_CREF; typedef Wrapped wrapped_t; typedef Inner* data_ref_t; typedef const Inner* data_srcref_t; Inner* inner; ref_data(Wrapped& o) : inner(o._data().inner) {} static ref_data make(Inner* f) {return ref_data(f);} private: ref_data(Inner* fp) : inner(fp) {} }; template struct srcref_data { typedef void IS_REF_OR_CREF; typedef Wrapped wrapped_t; typedef const Inner* data_ref_t; typedef const Inner* data_srcref_t; const Inner* inner; srcref_data(const Wrapped& o) : inner(o._data().inner) {} srcref_data(Ref o) : inner(o._data().inner) {} static srcref_data make(const Inner* f) {return srcref_data(f);} private: srcref_data(const Inner* fp) : inner(fp) {} }; // Helper to determine if T is a flint class. template struct is_flint_class : mp::false_ { }; template struct is_flint_class : mp::true_ { }; // From a lazy or immediate flint expression, obtain the evaluated // non-reference type. // Examples: fmpzxx -> fmpzxx // fmpzxx_ref -> fmpzxx // fmpzxx + fmpzxx -> fmpzxx template struct to_nonref {typedef typename T::evaluated_t type;}; template struct to_nonref { typedef typename T::data_t::wrapped_t type; }; template struct c_base_t { typedef typename T::c_base_t type; }; // Given a lazy or non-lazy flint expression, obtain th evaluated reference // type. // Examples: fmpzxx -> fmpzxx_ref // fmpzxx_ref -> fmpzxx_ref // fmpzxx + fmpzxx -> fmpzxx_ref template struct to_ref { typedef typename T::template make_helper::type, typename c_base_t::type> >::type type; }; // Similarly for srcref. template struct to_srcref { typedef typename T::template make_helper::type, typename to_ref::type, typename c_base_t::type> >::type type; }; // Compute if Ref if the reference type belonging to compare. // Examples: fmpzxx_ref, fmpzxx + fmpzxx -> true_ // fmpzxx_srcref, fmpzxx -> false_ template struct is_ref : mp::equal_types::type> { }; // Similarly for srcref. template struct is_srcref : mp::equal_types::type> { }; // Similarly for non-ref. template struct is_nonref : mp::equal_types::type > { }; // Flint classes allow implicit conversion only in very special situations. // This template determines when. Currently, it is used exclusively to allow // implicit conversion to reference types. template struct enableimplicit : mp::false_ { }; template struct enableimplicit, is_flint_class > >::type> : mp::and_< traits::is_immediate_expr, traits::is_immediate_expr, mp::or_< mp::and_, is_nonref >, mp::and_, is_nonref >, mp::and_, is_ref > > > { }; // Helper template which allows accessing data_(src)ref_t on immediates, // without causing a compiler error on non-immediates. // The main use for this are the _fmpz(), _fmpq() etc methods, which only // work on immediates (but are defined on all instances). template struct maybe_data_ref { typedef void data_ref_t; typedef void data_srcref_t; }; template struct maybe_data_ref >::type> { typedef typename Expr::data_t::data_ref_t data_ref_t; typedef typename Expr::data_t::data_srcref_t data_srcref_t; }; // If Base is a non-ref flint class, determine if T is a source operand // (i.e. non-ref, ref or srcref type belong to Base) // Examples: fmpzxx, fmpzxx_srcref -> true // fmpzxx, fmpzxx -> true // fmpzxx, fmpqxx -> false template struct is_source : mp::false_ { }; template struct is_source, is_flint_class > >::type> : mp::or_, is_ref, is_srcref > { }; // Same with target (i.e. disallow srcref). template struct is_target : mp::false_ { }; template struct is_target, is_flint_class > >::type> : mp::or_, is_ref > { }; // Predicate version of the above. Useful for FLINT_DEFINE_*_COND. // See FLINTXX_COND_S and FLINTXX_COND_T template struct is_source_base { template struct type : is_source { }; }; template struct is_target_base { template struct type : is_target { }; }; // Helper for implementing x += y*z etc template struct ternary_assign_helper { typedef typename mp::make_tuple::type tup_t; typedef tools::evaluate_n ev2_t; typedef typename ev2_t::temporaries_t temporaries_t; typedef mp::back_tuple back_t; typename back_t::type backing; ev2_t ev2; static temporaries_t backtemps(typename back_t::type& backing) { temporaries_t temps; back_t::init(temps, backing); return temps; } ternary_assign_helper(const tup_t& tup) : backing(mp::htuples::fill( tools::temporaries_filler( tup.first()+tup.second() /* XXX */))), ev2(tup, backtemps(backing)) {} const T& getleft() {return ev2.template get<0>();} const T& getright() {return ev2.template get<1>();} }; template struct enable_ternary_assign : mp::enable_if::type, T>, traits::is_T_expr::type, T> >, T&> { }; // convenience helper template struct is_Base : mp::or_< traits::is_T_expr, is_source > { }; } // flint_classes namespace traits { // Enable evaluation into reference types. See can_evaluate_into in // expression_traits.h. // XXX why do we need to disable the case where T, U are equal? // Is not more special? template struct can_evaluate_into, flint_classes::is_flint_class, mp::not_ > > >::type> : flint_classes::is_ref { }; } // traits namespace detail { template struct should_enable_extra_ternop : mp::false_ { }; template struct should_enable_extra_ternop >::type> : mp::equal_types::type>::type> { }; } // detail // We add additional overloads for when the LHS is a reference type. The // problem is that the standard overloads take LHS via reference, and rvalues // (such as coming from fmpz_polyxx::get_coeff()) // cannot bind to this. In this case instead objects should be taken by value. // However, this will make the overload ambiguous. Hence we take by const // reference and then make an additional copy. template inline typename mp::enable_if, Expr1>::type operator+=(const Expr1& e1, const Expr2& e2) { Expr1(e1).set(e1 + e2); return e1; } template inline typename mp::enable_if, Expr1>::type operator-=(const Expr1& e1, const Expr2& e2) { Expr1(e1).set(e1 - e2); return e1; } template inline typename mp::enable_if, Expr1>::type operator*=(const Expr1& e1, const Expr2& e2) { Expr1(e1).set(e1 * e2); return e1; } template inline typename mp::enable_if, Expr1>::type operator/=(const Expr1& e1, const Expr2& e2) { Expr1(e1).set(e1 / e2); return e1; } template inline typename mp::enable_if, Expr1>::type operator%=(const Expr1& e1, const Expr2& e2) { Expr1(e1).set(e1 % e2); return e1; } template inline typename mp::enable_if, Expr1>::type operator<<=(const Expr1& e1, const Expr2& e2) { Expr1(e1).set(e1 << e2); return e1; } template inline typename mp::enable_if, Expr1>::type operator>>=(const Expr1& e1, const Expr2& e2) { Expr1(e1).set(e1 >> e2); return e1; } } // flint // macros that help defining flint classes #define FLINTXX_DEFINE_BASICS_NOFLINTCLASS(name) \ public: \ typedef typename base_t::evaluated_t evaluated_t; \ \ template \ struct doimplicit \ : flint_classes::enableimplicit { }; \ \ template \ name& operator=(const T& t) \ { \ this->set(t); \ return *this; \ } \ \ protected: \ explicit name(const Data& d) : base_t(d) {} \ \ template \ friend class expression; // all flint classes should have this #define FLINTXX_DEFINE_BASICS(name) \ public: \ typedef void IS_FLINT_CLASS; \ FLINTXX_DEFINE_BASICS_NOFLINTCLASS(name) \ // all flint classes should have this #define FLINTXX_DEFINE_CTORS(name) \ public: \ name() : base_t() {} \ template \ explicit name(const T& t, \ typename mp::disable_if >::type* = 0) \ : base_t(t) {} \ template \ explicit name(T& t, \ typename mp::disable_if >::type* = 0) \ : base_t(t) {} \ template \ name(const T& t, \ typename mp::enable_if >::type* = 0) \ : base_t(t) {} \ template \ name(T& t, \ typename mp::enable_if >::type* = 0) \ : base_t(t) {} \ template \ name(const T& t, const U& u) : base_t(t, u) {} \ template \ name(T& t, const U& u) : base_t(t, u) {} \ template \ name(const T& t, const U& u, const V& v) : base_t(t, u, v) {} \ template \ name(T& t, const U& u, const V& v) : base_t(t, u, v) {} \ template \ name(const T& t, const U& u, const V& v, const W& w) \ : base_t(t, u, v, w) {} \ template \ name(T& t, const U& u, const V& v, const W& w) \ : base_t(t, u, v, w) {} // Enable the flint reference type scheme. This typedefs c_base_t to ctype, // and adds the data access wrapper (like _fmpz(), _fmpq()) called accessname. // It also provides reference constructors from C types. // All flint classes should have this. #define FLINTXX_DEFINE_C_REF(name, ctype, accessname) \ public: \ typedef ctype c_base_t; \ typedef flint_classes::maybe_data_ref wrapped_traits; \ typename wrapped_traits::data_ref_t accessname() \ { \ return this->_data().inner; \ } \ typename wrapped_traits::data_srcref_t accessname() const \ { \ return this->_data().inner; \ } \ \ /* These only make sense with the reference types */ \ template \ static name make(T& f) \ { \ return name(Data::make(f)); \ } \ template \ static name make(const T& f) \ { \ return name(Data::make(f)); \ } \ template \ static name make(T& f, const U& u) \ { \ return name(Data::make(f, u)); \ } \ template \ static name make(const T& f, const U& u) \ { \ return name(Data::make(f, u)); \ } \ template \ static name make(const T& f, const U& u, const V& v) \ { \ return name(Data::make(f, u, v)); \ } // Add a statically forwarded constructor called name. (Forwarded to data_t). #define FLINTXX_DEFINE_FORWARD_STATIC(name) \ template \ static typename base_t::derived_t name(const T& f) \ { \ return typename base_t::derived_t(Data::name(f)); \ } \ template \ static typename base_t::derived_t name(const T& f, const U& u) \ { \ return typename base_t::derived_t(Data::name(f, u)); \ } // Add a static randomisation function. // XXX this is not really useful because the arguments are often different. #define FLINTXX_DEFINE_RANDFUNC(CBase, name) \ static CBase##xx_expression name(frandxx& state, flint_bitcnt_t bits) \ { \ CBase##xx_expression res; \ CBase##_##name(res._data().inner, state._data(), bits); \ return res; \ } // Add a forwarded unary operation to the class. Suppose there is a unary // operation foo() which returns my_typeA, and takes an argument of type // my_typeB. Now on instances my_typeB, you want to write x.bar() for foo(x). // Then add FLINTXX_DEFINE_MEMBER_UNOP_RTYPE_(my_typeA, bar, foo) to my_typeB. // // XXX due to circular definition problems, this cannot use the usual // unary_op_helper type approach, and the unop must return the same type // of expression #define FLINTXX_DEFINE_MEMBER_UNOP_RTYPE_(rettype, name, funcname) \ FLINT_UNOP_BUILD_RETTYPE(funcname, rettype, typename base_t::derived_t) \ name() const \ { \ return flint::funcname(*this); \ } // Convenience version when name==funcname #define FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(rettype, name) \ FLINTXX_DEFINE_MEMBER_UNOP_RTYPE_(rettype, name, name) // Convenience version when rettype==argtype #define FLINTXX_DEFINE_MEMBER_UNOP_(name, funcname) \ FLINTXX_DEFINE_MEMBER_UNOP_RTYPE_(typename base_t::derived_t, name, funcname) // Convenience version when rettype==argtype and name==funcname #define FLINTXX_DEFINE_MEMBER_UNOP(name) FLINTXX_DEFINE_MEMBER_UNOP_(name, name) // Add a forwarded binary operation. It is not necessary to specify the return // type. #define FLINTXX_DEFINE_MEMBER_BINOP_(name, funcname) \ template \ typename detail::binary_op_helper::enable::type \ name(const T& t) const \ { \ return flint::funcname(*this, t); \ } // Convenience version when funcname==name. #define FLINTXX_DEFINE_MEMBER_BINOP(name) \ FLINTXX_DEFINE_MEMBER_BINOP_(name, name) #define FLINTXX_DEFINE_MEMBER_3OP_(name, funcname) \ template \ typename detail::nary_op_helper2::enable::type \ name(const T& t, const U& u) const \ { \ return flint::funcname(*this, t, u); \ } #define FLINTXX_DEFINE_MEMBER_3OP(name) \ FLINTXX_DEFINE_MEMBER_3OP_(name, name) #define FLINTXX_DEFINE_MEMBER_4OP_(name, funcname) \ template \ typename detail::nary_op_helper2::enable::type \ name(const T& t, const U& u, const V& v) const \ { \ return flint::funcname(*this, t, u, v); \ } #define FLINTXX_DEFINE_MEMBER_4OP(name) \ FLINTXX_DEFINE_MEMBER_4OP_(name, name) #define FLINTXX_DEFINE_MEMBER_5OP_(name, funcname) \ template \ typename detail::nary_op_helper2::enable::type \ name(const T& t, const U& u, const V& v, const W& w) const \ { \ return flint::funcname(*this, t, u, v, w); \ } #define FLINTXX_DEFINE_MEMBER_5OP(name) \ FLINTXX_DEFINE_MEMBER_5OP_(name, name) // Helper macros for FLINT_DEFINE_*_COND?. #define FLINTXX_COND_S(Base) flint_classes::is_source_base::template type #define FLINTXX_COND_T(Base) flint_classes::is_target_base::template type // Convenience rules. These all take a Base class as argument, and will // automatically apply to the related reference types as well. // Add a to_string() conversion rule, empolying the common flint idiom where // the string is allocated by the to_string function. #define FLINTXX_DEFINE_TO_STR(Base, eval) \ template \ struct to_string >::type> \ { \ static std::string get(const T& from, int base) \ { \ char* str = eval; \ std::string res(str); \ flint_free(str); \ return res; \ } \ }; // Add a swap rule. #define FLINTXX_DEFINE_SWAP(Base, eval) \ template \ struct swap, FLINTXX_COND_T(Base) > >::type> \ { \ static void doit(T& e1, U& e2) \ { \ eval; \ } \ }; // Define a conversion rule through a default-constructed temporary object. #define FLINTXX_DEFINE_CONVERSION_TMP(totype, Base, eval) \ template \ struct conversion >::type> \ { \ static totype get(const T& from) \ { \ totype to; \ eval; \ return to; \ } \ }; // Define a cmp rule. #define FLINTXX_DEFINE_CMP(Base, eval) \ template \ struct cmp, \ FLINTXX_COND_S(Base) > >::type> \ { \ static int get(const T& e1, const U& e2) \ { \ return eval; \ } \ }; // Define an equals rule. #define FLINTXX_DEFINE_EQUALS(Base, eval) \ template \ struct equals, FLINTXX_COND_S(Base) > >::type> \ { \ static bool get(const T& e1, const U& e2) \ { \ return eval; \ } \ }; // Define a string assignment rule (c/f many polynomial classes). #define FLINTXX_DEFINE_ASSIGN_STR(Base, eval) \ template \ struct assignment, traits::is_string > >::type> \ { \ static void doit(T& to, const char* from) \ { \ eval; \ } \ }; #define FLINTXX_UNADORNED_MAKETYPES(Base, left, op, right) \ Base##_expression< op, tuple< left, tuple< right, empty_tuple> > > // Optimized evaluation rules using ternary arithmetic (addmul, submul) // NB: this has to be called in namespace flint, not flint::rules! #define FLINTXX_DEFINE_TERNARY(Base, addmuleval, submuleval, maketypes) \ namespace rules { \ /* a +- b*c */ \ template \ struct evaluation, \ mp::equal_types >, \ empty_tuple>::type> >, \ true, 1, \ typename tools::ternary_helper::enable::type> \ { \ /* Helpful for testing. */ \ static const unsigned TERNARY_OP_MARKER = 0; \ \ typedef Base return_t; \ typedef tools::ternary_helper th; \ typedef typename th::temporaries_t temporaries_t; \ typedef tuple > data_t; \ static const bool is_add = mp::equal_types::val; \ \ static void doit(const data_t& input, temporaries_t temps, return_t* res) \ { \ const Base* left = 0; \ const Base* right = 0; \ th::doit(input.first(), input.second()._data().first(), \ input.second()._data().second(), temps, res, right, left); \ const Base& e1 = *left; \ const Base& e2 = *right; \ Base& to = *res; \ if(is_add) \ { \ addmuleval; \ } \ else \ { \ submuleval; \ } \ } \ }; \ \ /* b*c + a */ \ template \ struct evaluation >, \ true, 1, \ typename tools::ternary_helper::enable::type> \ { \ /* Helpful for testing. */ \ static const unsigned TERNARY_OP_MARKER = 0; \ \ typedef Base return_t; \ typedef tools::ternary_helper th; \ typedef typename th::temporaries_t temporaries_t; \ typedef tuple > data_t; \ \ static void doit(const data_t& input, temporaries_t temps, return_t* res) \ { \ const Base* left = 0; \ const Base* right = 0; \ th::doit(input.second(), input.first()._data().first(), \ input.first()._data().second(), temps, res, right, left); \ const Base& e1 = *left; \ const Base& e2 = *right; \ Base& to = *res; \ addmuleval; \ } \ }; \ } /* rules */ \ \ /* TODO enable these with references on left hand side(?) */ \ /* a += b*c */ \ template \ inline typename flint_classes::enable_ternary_assign::type \ operator+=(Base& to, \ const maketypes(Base, Right1, operations::times, Right2)& other) \ { \ flint_classes::ternary_assign_helper tah( \ other._data()); \ const Base& e1 = tah.getleft(); \ const Base& e2 = tah.getright(); \ addmuleval; \ return to; \ } \ \ /* a -= b*c */ \ template \ inline typename flint_classes::enable_ternary_assign::type \ operator-=(Base& to, \ const maketypes(Base, Right1, operations::times, Right2)& other) \ { \ flint_classes::ternary_assign_helper tah( \ other._data()); \ const Base& e1 = tah.getleft(); \ const Base& e2 = tah.getright(); \ submuleval; \ return to; \ } #endif flint2-2.8.4/flintxx/flint_exception.h000066400000000000000000000022531414523752600177750ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FLINTXX_FLINT_EXCEPTION_H #define FLINTXX_FLINT_EXCEPTION_H #include #include namespace flint { // This is the common flintxx exception class, which is raised whenever the // C++ layer diagnoses a problem. // Note that the C layer will sometimes flint_abort() with a message (in this case // no exception is thrown). class flint_exception : public std::domain_error // ? { public: flint_exception(const std::string& what) : std::domain_error("FLINT: " + what) {} }; // Helper function. If worked is true, does nothing, else raises // flint_exception. inline void execution_check(bool worked, const std::string& where, const std::string& context) { if(!worked) throw flint_exception(context + " computation failed: " + where); } } // flint #endif flint2-2.8.4/flintxx/forwarding.h000066400000000000000000000145171414523752600167530ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_FORWARDING_H #define CXX_FORWARDING_H #include #include #include "evaluation_tools.h" #include "mp.h" #include "rules.h" #include "tuple.h" // XXX This file is UNFINISHED. It is/was meant to use for extending flintxx by // compisition, in particular for the NTL wrapper. // Ask Tom (e_mc_h2@web.de) if you want to use it. namespace flint { namespace forwarding { // Specialise this to enable forwarding of your class. template struct enable : mp::false_ { }; } // forwarding namespace rules { template struct print::underlying_t> > >::type> { static void doit(const T& t, std::ostream& o) { typedef typename forwarding::enable et; print::doit(et::get_underlying(t), o); } }; template struct to_string::underlying_t> > >::type> { static std::string get(const T& t, int base) { typedef typename forwarding::enable et; return to_string::get( et::get_underlying(t), base); } }; namespace rdetail { template struct maybe_forward { typedef T underlying_t; static const T& get_underlying(const T& t) {return t;} static T& get_underlying(T& t) {return t;} }; template struct maybe_forward >::type> : forwarding::enable { }; template class Wrapped, class T, class U> struct fwd_enable2 : mp::enable_if::underlying_t, typename maybe_forward::underlying_t, void> >, mp::or_< typename forwarding::enable, typename forwarding::enable > > > { typedef Wrapped< typename maybe_forward::underlying_t, typename maybe_forward::underlying_t, void> wrapped_t; }; } // rdetail template struct assignment::type> { static void doit(T& t, const U& u) { rdetail::fwd_enable2::wrapped_t::doit( rdetail::maybe_forward::get_underlying(t), rdetail::maybe_forward::get_underlying(u)); } }; template struct cmp::type> { static int get(const T& t, const U& u) { return rdetail::fwd_enable2::wrapped_t::get( rdetail::maybe_forward::get_underlying(t), rdetail::maybe_forward::get_underlying(u)); } }; template struct equals::type> { static bool get(const T& t, const U& u) { return rdetail::fwd_enable2::wrapped_t::get( rdetail::maybe_forward::get_underlying(t), rdetail::maybe_forward::get_underlying(u)); } }; template struct conversion::underlying_t> > >::type> { static T get(const U& u) { return conversion::underlying_t>::get( forwarding::enable::get_underlying(u)); } }; // TODO automatically convert fwd to fwd ? // TODO instantiate_temporaries ? namespace rdetail { template struct needs_forwarding : mp::false_ { }; template struct needs_forwarding : forwarding::enable { }; template struct needs_forwarding > : mp::or_, needs_forwarding > { }; template struct translate { typedef Data type; static type doit(const Data& d) {return d;} }; template struct translate { typedef maybe_forward fw; typedef typename fw::underlying_t type; static type doit(const Wrapped& d) { return fw::get_underlying(d); } }; template struct translate > { typedef translate htranslator; typedef translate ttranslator; typedef tuple type; static type doit(const tuple& d) { return type(htranslator::doit(d.head), ttranslator::doit(d.tail)); } }; template struct can_forward { typedef rdetail::translate translator; typedef typename translator::type translated_t; typedef typename mp::find_evaluation< Op, translated_t, result_is_temporary>::type rule_t; static const bool val = traits::is_implemented::val; }; template struct can_forward >::type> { static const bool val = false; }; } template struct evaluation >::type> { typedef rdetail::translate translator; typedef typename translator::type translated_t; typedef typename mp::find_evaluation< Op, translated_t, result_is_temporary>::type rule_t; typedef typename rule_t::temporaries_t temporaries_t; // TODO repackaging typedef typename rule_t::return_t return_t; static void doit(const Data& input, temporaries_t temps, return_t* output) { rule_t::doit(translator::doit(input), temps, output); } }; } //rules } // flint #endif flint2-2.8.4/flintxx/frandxx.h000066400000000000000000000015521414523752600162560ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_FRANDXX_H #define CXX_FRANDXX_H #include "../flint.h" // This class contains a first-class wrapper of flint_rand_t. // Note that frandxx is not copyable. namespace flint { class frandxx { private: flint_rand_t inner; // not copyable frandxx(const frandxx&); public: frandxx() {flint_randinit(inner);} ~frandxx() {flint_randclear(inner);} flint_rand_t& _data() {return inner;} const flint_rand_t& _data() const {return inner;} }; } // flint #endif flint2-2.8.4/flintxx/ltuple.h000066400000000000000000000313111414523752600161050ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // Lazy tuple class (for use in expression templates) // Note that assignment and comparison are performed elementwise, and types // need not match (even for equality) as long as the operations can be performed // on underlying types. #ifndef FLINTXX_LTUPLE_H #define FLINTXX_LTUPLE_H #ifndef FLINT_LTUPLE_PLACEHOLDER_NAME #define FLINT_LTUPLE_PLACEHOLDER_NAME _ #endif #include "expression.h" #include "tuple.h" namespace flint { // For lazy get, this operation type is created. namespace operations { template struct ltuple_get_op { }; } // operations namespace detail { // Empty marker type struct INSTANTIATE_FROM_TUPLE { }; // Traits for the ltuple expression template get<> operation. If the ltuple is // an immediate, return references. Else if the return type is an expression // template, return an expression template. Otherwise, evaluate the ltuple and // return a copy of the entry. template struct ltuple_get_traits { typedef unary_op_helper, Expr> uoh; typedef typename uoh::return_t type; typedef type ctype; static type get(const Expr& e) { return uoh::make(e); } }; template struct ltuple_get_traits { typedef mp::tuple_get getter; typedef typename getter::type btype; typedef typename traits::forwarding::type ctype; typedef typename traits::reference::type type; static type get(Expr& t) { return getter::get(t._data().inner); } static ctype get(const Expr& t) { return getter::get(t._data().inner); } }; template struct ltuple_get_traits >, mp::not_::type> > > >::type> { typedef mp::tuple_get getter; typedef typename getter::type type; typedef type ctype; static type get(const Expr& t) { return getter::get(t.evaluate()._data().inner); } }; // Instances of this can be passed to ltuple[ref]() and will be replaced by // temporaries of the right type before assigment. struct IGNORED_TYPE { }; template struct ltuple_instantiate_ignored_types; } // detail // The ltuple expression template class. Underlying is a tuple type. template class ltuple_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; // internal typedef void IS_LTUPLE_EXPRESSION; typedef Underlying underlying_t; ltuple_expression() {} template ltuple_expression(detail::INSTANTIATE_FROM_TUPLE i, const T& t) : base_t(i, t) {} template ltuple_expression& operator=(const T& t) { detail::ltuple_instantiate_ignored_types< ltuple_expression, T> inst(*this, t); inst.set(t); return *this; } template typename detail::ltuple_get_traits::type get() { return detail::ltuple_get_traits< n, Underlying, Operation, Data, ltuple_expression>::get(*this); } template typename detail::ltuple_get_traits::ctype get() const { return detail::ltuple_get_traits< n, Underlying, Operation, Data, ltuple_expression>::get(*this); } typename base_t::evaluated_t create_temporary() const { return typename base_t::evaluated_t(detail::INSTANTIATE_FROM_TUPLE(), mp::htuples::fill(tools::temporaries_filler(*this))); } protected: explicit ltuple_expression(const Data& d) : base_t(d) {} template friend class expression; }; namespace detail { template struct ltuple_data { Underlying inner; ltuple_data() {} template ltuple_data(INSTANTIATE_FROM_TUPLE, const T& t) : inner(t) {} }; template struct to_ref : traits::reference { }; template struct to_srcref : traits::reference::type> { }; templateclass Transform, class Tuple> struct transform_tuple { typedef tuple::type, typename transform_tuple::type> type; }; templateclass Transform> struct transform_tuple { typedef empty_tuple type; }; } // detail // Helper for building ltuple types. template struct make_ltuple { typedef ltuple_expression > type; typedef typename detail::transform_tuple::type Underlying_ref; typedef typename detail::transform_tuple::type Underlying_srcref; typedef ltuple_expression > ref_type; typedef ltuple_expression > srcref_type; }; namespace traits { template struct is_ltuple_expr : mp::false_ { }; template struct is_ltuple_expr : mp::true_ { }; // enable evaluation directly into tuple template struct can_evaluate_into, is_ltuple_expr, mp::not_ > > >::type> : mp::true_ { }; } // traits namespace detail { template struct ltuple_instantiate_ignored_types { // degenerate case: To is not a tuple Ltuple& saved; ltuple_instantiate_ignored_types(Ltuple& s, const To&) : saved(s) {} void set(const To& to) {saved.set(to);} }; template struct tuple_instantiate_ignored { typedef tuple_instantiate_ignored next_t; typedef typename traits::reference::type ref_t; typedef tuple type; next_t next; ref_t ref; template tuple_instantiate_ignored(ToTuple& to, const From& from) : next(to.tail, from), ref(to.head) {} type get() { return type(ref, next.get()); } }; template<> struct tuple_instantiate_ignored { typedef empty_tuple type; template tuple_instantiate_ignored(empty_tuple, const F&) {} empty_tuple get() {return empty_tuple();} }; template struct tuple_instantiate_ignored< tuple, tuple > { typedef tuple_instantiate_ignored next_t; typedef typename traits::reference::type ref_t; typedef tuple type; next_t next; From tmp; template tuple_instantiate_ignored(ToTuple& to, const FromExpr& from) : next(to.tail, from), tmp(rules::instantiate_temporaries::get(from)) {} type get() { return type(tmp, next.get()); } }; template struct ltuple_instantiate_ignored_types >::type> { typedef tuple_instantiate_ignored< typename Ltuple::underlying_t, typename T::underlying_t> tii_t; tii_t tii; ltuple_instantiate_ignored_types(Ltuple& l, const T& t) : tii(l._data().inner, t) {} void set(const T& t) { typename make_ltuple::type(INSTANTIATE_FROM_TUPLE(), tii.get()).set(t); } }; } namespace rules { template struct assignment, traits::is_ltuple_expr > >::type> { static void doit(Tuple1& to, const Tuple2& from) { to._data().inner.set(from._data().inner); } }; template struct equals, traits::is_ltuple_expr > >::type> { static bool get(const Tuple1& to, const Tuple2& from) { return to._data().inner.equals_elementwise(from._data().inner); } }; template struct unary_expression, Tuple, typename mp::enable_if, traits::is_immediate > >::type> { typedef typename mp::tuple_get::type return_t; template static void doit(R& to, const Tuple& from) { to = from.template get(); } }; } // rules // TODO we would really like variadic templates / lvalue references here // Helpers to build ltuples from (references to) arguments. template inline typename make_ltuple::type>::type ltuple(const T& t) { return typename make_ltuple::type>::type( detail::INSTANTIATE_FROM_TUPLE(), mp::make_tuple::make(t)); } template inline typename make_ltuple::type>::type ltuple(const T& t, const U& u) { return typename make_ltuple::type>::type( detail::INSTANTIATE_FROM_TUPLE(), mp::make_tuple::make(t, u)); } template inline typename make_ltuple::type>::type ltuple(const T& t, const U& u, const V& v) { return typename make_ltuple::type>::type( detail::INSTANTIATE_FROM_TUPLE(), mp::make_tuple::make(t, u, v)); } template inline typename make_ltuple::type>::type ltuple(const T& t, const U& u, const V& v, const W& w) { return typename make_ltuple::type>::type( detail::INSTANTIATE_FROM_TUPLE(), mp::make_tuple::make(t, u, v, w)); } template inline typename make_ltuple::type>::type ltupleref(T& t) { return typename make_ltuple::type>::type( detail::INSTANTIATE_FROM_TUPLE(), mp::make_tuple::make(t)); } template inline typename make_ltuple::type>::type ltupleref(T& t, U& u) { return typename make_ltuple::type>::type( detail::INSTANTIATE_FROM_TUPLE(), mp::make_tuple::make(t, u)); } template inline typename make_ltuple::type>::type ltupleref(T& t, U& u, V& v) { return typename make_ltuple::type>::type( detail::INSTANTIATE_FROM_TUPLE(), mp::make_tuple::make(t, u, v)); } template inline typename make_ltuple::type>::type ltupleref(T& t, U& u, V& v, W& w) { return typename make_ltuple::type>::type( detail::INSTANTIATE_FROM_TUPLE(), mp::make_tuple::make(t, u, v, w)); } // static placeholder static detail::IGNORED_TYPE FLINT_LTUPLE_PLACEHOLDER_NAME; namespace detail { void remove_compiler_warning( detail::IGNORED_TYPE* = &FLINT_LTUPLE_PLACEHOLDER_NAME); } // detail } // flint #endif flint2-2.8.4/flintxx/matrix.h000066400000000000000000000316631414523752600161160ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // Common code shared among matrix classes #ifndef FLINTXX_MATRIX_H #define FLINTXX_MATRIX_H #include "flint_classes.h" #include "mp.h" #include "rules.h" #include "stdmath.h" #include "ltuple.h" #include "traits.h" #include "tuple.h" #include "../permxx.h" namespace flint { FLINT_DEFINE_BINOP(solve) FLINT_DEFINE_BINOP(solve_fflu) FLINT_DEFINE_THREEARY(mat_at) FLINT_DEFINE_THREEARY(solve_fflu_precomp) FLINT_DEFINE_UNOP(charpoly) FLINT_DEFINE_UNOP(det) FLINT_DEFINE_UNOP(det_fflu) FLINT_DEFINE_UNOP(det_interpolate) FLINT_DEFINE_UNOP(nullspace) FLINT_DEFINE_UNOP(rref) FLINT_DEFINE_UNOP(trace) FLINT_DEFINE_UNOP(transpose) FLINT_DEFINE_THREEARY(fflu) FLINT_DEFINE_THREEARY_HERE_2DEFAULT(fflu, permxx*, 0, bool, false) template struct matrix_traits : rules::UNIMPLEMENTED { }; // override this for the non-reference type of your choice // { // template static slong rows(const M&); // template static slong cols(const M&); // template static ??? at(const M&, slong, slong); // template static ??? at(M&, slong, slong); // }; namespace traits { template struct is_mat : is_implemented< matrix_traits::type> > { }; template struct is_mat >::type> : mp::false_ { }; } // traits namespace matrices { namespace mdetail { // Some helper traits used below. template struct second_is_mat_data : mp::false_ { }; template struct second_is_mat_data > > : traits::is_mat::type> { }; template struct second_is_mat : second_is_mat_data { }; template struct both_mat : mp::and_< traits::is_mat< typename traits::basetype::type>, traits::is_mat< typename traits::basetype::type> > { }; // A more convenient way to obtain the traits associated to a non-immediate // or non-nonref expression. template struct immediate_traits : matrix_traits::type> { }; } // mdetail // For matrix expressions to create temporaries, it is necessary to know the // dimensions of the result of a computation. This is a generic implementation, // which assumes that the output dimensions are the same as the dimensions of // the first argument, which is assumed to be a matrix, except if there are // precisely two arguments only the second of which is a matrix, in which case // we assume its the dimension of that. // This implementation works correctly in many cases, e.g. matrix-addition or // matrix-scalar multiplication. template struct outsize_generic { template static slong rows(const Mat& m, typename mp::disable_if >::type* = 0) { return m._data().head.rows(); } template static slong cols(const Mat& m, typename mp::disable_if >::type* = 0) { return m._data().head.cols(); } template static slong rows(const Mat& m, typename mp::enable_if >::type* = 0) { return m._data().tail.head.rows(); } template static slong cols(const Mat& m, typename mp::enable_if >::type* = 0) { return m._data().tail.head.cols(); } }; // This is the expression template used for computing the dimensions of an // operation. Without further specialisation, it is just the generic // implementation described above. // If you introduce a new operation where the generic implementation is // incorrect, you must specialise this template. template struct outsize : outsize_generic { }; // Specialise immediates, where the dimensions are stored with the object. template<> struct outsize { template static slong rows(const Mat& m) { return mdetail::immediate_traits::rows(m); } template static slong cols(const Mat& m) { return mdetail::immediate_traits::cols(m); } }; // Specialise multiplication. For matrix-matrix multiplication, use // the usual formula. For matrix-scalar multiplication, use the generic // implementation. template<> struct outsize { template static slong rows(const Mat& m, typename mp::enable_if >::type* = 0) { return m._data().head.rows(); } template static slong cols(const Mat& m, typename mp::enable_if >::type* = 0) { return m._data().tail.head.cols(); } template static slong rows(const Mat& m, typename mp::disable_if >::type* = 0) { return outsize_generic::rows(m); } template static slong cols(const Mat& m, typename mp::disable_if >::type* = 0) { return outsize_generic::cols(m); } }; // Any particular multipication algorithm also has to be specialised. template<> struct outsize : outsize { }; // Specialise transpose. template<> struct outsize { template static slong rows(const Mat& m) { return m._data().head.cols(); } template static slong cols(const Mat& m) { return m._data().head.rows(); } }; // Specialise nullspace. Note that the nullspace computation functions in // flint return a matrix the columns of which span the nullspace. Since the // nullity is not known in advance in general, we have to allocate a square // matrix. template<> struct outsize { template static slong rows(const Mat& m) { return m._data().head.cols(); } template static slong cols(const Mat& m) { return m._data().head.cols(); } }; // This is a bit of a hack. Matrix operations returning a tuple typically // only return one matrix. We key outsize on the inner operation to find out // the dimensions. So e.g. solve(A, X).get<1>() (say) will invoke outsize // with ltuple_get_op<1> as argument, which then invokes outsize with solve_op // and (A, X) as argument. template struct outsize > { template static slong rows(const Mat& m) { return outsize< typename Mat::data_t::head_t::operation_t>::rows(m._data().head); } template static slong cols(const Mat& m) { return outsize< typename Mat::data_t::head_t::operation_t>::cols(m._data().head); } }; // This is not actually a matrix expression, but called by the above ... template<> struct outsize { template static slong rows(const Mat& m) { return m._data().second().rows(); } template static slong cols(const Mat& m) { return m._data().second().cols(); } }; template<> struct outsize : outsize { }; template<> struct outsize { template static slong rows(const Mat& m) { return m._data().tail.second().rows(); } template static slong cols(const Mat& m) { return m._data().tail.second().cols(); } }; namespace mdetail { struct base_traits { template static slong rows(const M& m) { return matrices::outsize::rows(m); } template static slong cols(const M& m) { return matrices::outsize::cols(m); } }; } // mdetail // These traits classes are useful for implementing unified coefficient access. // See fmpz_matxx etc for example usage. template struct generic_traits : mdetail::base_traits { template struct at { typedef FLINT_THREEARY_ENABLE_RETTYPE(mat_at, Mat, T, U) entry_ref_t; typedef entry_ref_t entry_srcref_t; static entry_srcref_t get(const Mat& m, T i, U j) { return mat_at(m, i, j); } }; }; template struct generic_traits_srcref : mdetail::base_traits { template struct at { typedef Srcref entry_ref_t; typedef Srcref entry_srcref_t; template static Srcref get(M m, T i, U j) { return mdetail::immediate_traits::at(m, i, j); } }; }; template struct generic_traits_ref : mdetail::base_traits { template struct at { typedef Ref entry_ref_t; typedef Ref entry_srcref_t; template static Ref get(M m, T i, U j) { return mdetail::immediate_traits::at(m, i, j); } }; }; template struct generic_traits_nonref : mdetail::base_traits { template struct at { typedef Ref entry_ref_t; typedef Srcref entry_srcref_t; template static Ref get(M& m, T i, U j) { return mdetail::immediate_traits::at(m, i, j); } template static Srcref get(const M& m, T i, U j) { return mdetail::immediate_traits::at(m, i, j); } }; }; } // matrices // immediate functions template inline typename mp::enable_if, slong>::type rank(const Mat& m) { return m.rank(); } template inline typename mp::enable_if, slong>::type find_pivot_any(const Mat& m, slong start, slong end, slong c) { return m.find_pivot_any(start, end, c); } template inline typename mp::enable_if, slong>::type find_pivot_partial(const Mat& m, slong start, slong end, slong c) { return m.find_pivot_partial(start, end, c); } } // flint // Define rows(), cols(), create_temporary() and at() methods. // For this to work, Traits must behave like the above generic traits. // Also your matrix class must have a static create_temporary_rowscols function. // See fmpz_mat for an example. #define FLINTXX_DEFINE_MATRIX_METHODS(Traits) \ template \ typename Traits::template at::entry_ref_t at(T i, U j) \ {return Traits::template at::get(*this, i, j);} \ template \ typename Traits::template at::entry_srcref_t at(T i, U j) const \ {return Traits::template at::get(*this, i, j);} \ \ slong rows() const {return Traits::rows(*this);} \ slong cols() const {return Traits::cols(*this);} \ evaluated_t create_temporary() const \ { \ return create_temporary_rowscols(*this, rows(), cols()); \ } // Disable temporary merging. Requires create_temporary_rowscols. // TODO do we really need the ltuple code everywhere? #define FLINTXX_DEFINE_TEMPORARY_RULES(Matrix) \ namespace traits { \ template<> struct use_temporary_merging : mp::false_ { }; \ } /* traits */ \ namespace rules { \ template \ struct use_default_temporary_instantiation : mp::false_ { }; \ template \ struct instantiate_temporaries >::type> \ { \ /* The only case where this should ever happen is if Expr is an ltuple */ \ /* TODO static assert this */ \ static Matrix get(const Expr& e) \ { \ typedef typename Expr::operation_t op_t; \ return Matrix::create_temporary_rowscols(e, \ matrices::outsize::rows(e), \ matrices::outsize::cols(e)); \ } \ }; \ template \ struct instantiate_temporaries >::type> \ { \ static Matrix get(const Expr& e) \ { \ return e.create_temporary(); \ } \ }; \ } /* rules */ // Add a fflu() member function to the matrix class. #define FLINTXX_DEFINE_MEMBER_FFLU \ template typename detail::nary_op_helper2::enable::type \ fflu(permxx* p, const T& t) const \ { \ return flint::fflu(*this, p, t); \ } #endif flint2-2.8.4/flintxx/mp.h000066400000000000000000000077651414523752600152340ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_MP_H #define CXX_MP_H namespace flint { namespace mp { ///////////////////////////////// // BASIC METAPROGRAMMING HELPERS ///////////////////////////////// // Most of these helpers *compute* something. In this case, they have a static // static const member "val" storing the result of the computation. The // arguments of the computation are template parameters, and are usually *not* // PODs, but instead themselves types with a static constant "val" member. // See value_of, true_ and false_ for how to pass in explicit values to your // computation. // Wrap the boolean value "v" into the static const member "val". template struct value_of { static const bool val = v; }; // Boolean inputs for computations. struct true_ : value_of { }; struct false_ : value_of { }; // Compute if two input *types* (not values!) are equal. template struct equal_types : false_ { }; template struct equal_types : true_ { }; // Compute logical negation of the input value. template struct not_ : value_of { }; // Compute logical and of the input values. template struct and_ : and_ > { }; template struct and_ : value_of { }; template struct and_v : and_ > { }; // Compute logical or of the input values. template struct or_ : or_ > { }; template struct or_ : value_of { }; // Compute V1 or V2, depending on C template struct if_v {typedef V1 type;}; template struct if_v {typedef V2 type;}; template struct if_ : if_v { }; // Choose a value depending on a sequence of conditions. // This has he same meaning as // int select(bool c1 = false, bool c2 = false, bool c3 = false) // { // if(c1) // return v1; // if(c2) // return v2; // if(c3) // return v3; // return d; // } template struct select : if_::type> { }; template struct select {typedef D type;}; // Conditional template enabling helper. (See below for explanation.) template struct enable_if_v { typedef U type; static const int val = 0; }; template struct enable_if_v { }; // Conditional template enabling. // // These two helpers (enable_if and disable_if) can be used wherever the // SFINAE rule applies to conditionally enable or disable template // specialisations. // // If T evaluaties to true, then enable_if has a member typedef "type", which // is the parameter U, and also a static const int member val (of zero). // If on the other hand T evaluates to false, then enable_if is empty. // The meaning of T is reversed for disable_if. // See e.g. [0] or the tests for how to use this. // // [0] https://www.boost.org/doc/libs/1_53_0/libs/utility/enable_if.html // template struct enable_if : public enable_if_v { }; template struct disable_if : public enable_if, U> { }; struct empty { }; } // mp } // flint #endif flint2-2.8.4/flintxx/rules.h000066400000000000000000000326541414523752600157450ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // This file contains the definitions of all rules used by the expression class. // (Some generally useful implementations can be found in default_rules.h.) // This file also contains some helper traits, metaprogramming tools and macros. #ifndef CXX_RULES_H #define CXX_RULES_H #include "mp.h" #include "traits.h" namespace flint { namespace rules { struct no_op { template static void doit(const U&) {} }; struct UNIMPLEMENTED { static const bool unimplemented_marker = true; }; template struct print : UNIMPLEMENTED { }; template struct to_string : UNIMPLEMENTED { }; // static std::string get(const T&, int base) template struct assignment : UNIMPLEMENTED { }; // C-style cmp. template struct cmp : UNIMPLEMENTED { }; // Rule for equals. Implemented in terms of cmp by default. template struct equals : UNIMPLEMENTED { }; // Rule for type conversion. template struct conversion { static To get(const From& from) { return To(from); } }; // Rule for c-style printing template struct cprint : UNIMPLEMENTED { }; // static int doit(FILE*, const T&) template struct print_pretty : UNIMPLEMENTED { }; // static int doit(FILE*, const T&) template struct read : UNIMPLEMENTED { }; // static int doit(FILE*, T&) // Rule for swapping template struct swap : UNIMPLEMENTED { }; // If result_is_temporary is true, then the result coincides with the // first temporary (provided these have the same type) // Priorities 2, 1, 0 can be used to resolve conflicts. template< class Op, class Data, bool result_is_temporary, unsigned priority, class Enable = void> struct evaluation : UNIMPLEMENTED { }; //{ // typedef X return_t; // typedef Y temporaries_t; // a tuple of *pointers* // static void doit(const T& input, temporaries_t temps, return_t* output); //}; // Instantiate temporaries for evaluation. The default implementation does the // following: // - find a subexpression t of e which evaluates to type T // -- return t.create_temporary() // - if no such subexpression can be found, return T() // Additionally, the expression class implements a version of create_temporary // which just returns T(), so if your class is default constructible, // everything works automatically. template struct instantiate_temporaries; //{ // static T get(const Expr& e); //}; // Convenience helpers, instantiate by evaluation if necessary // (needs default rules) template struct binary_expression : UNIMPLEMENTED { }; // typedef X return_t; // static void doit(return_t& to, const T&, const U&); template struct commutative_binary_expression : UNIMPLEMENTED { }; // similarly template struct unary_expression : UNIMPLEMENTED { }; // similarly // Rules for more arguments. template struct threeary_expression : UNIMPLEMENTED { }; template struct fourary_expression : UNIMPLEMENTED { }; template struct fiveary_expression : UNIMPLEMENTED { }; template struct sixary_expression : UNIMPLEMENTED { }; template struct sevenary_expression : UNIMPLEMENTED { }; } // rules /////////////////////////////////////////////////////////////////////////////////// // HELPER TRAITS /////////////////////////////////////////////////////////////////////////////////// namespace traits { // Compute if the rule T is implemented. template struct is_implemented : mp::not_<_is_convertible > { }; } // traits } // flint /////////////////////////////////////////////////////////////////////////////////// // HELPER MACROS /////////////////////////////////////////////////////////////////////////////////// // These macros should be called in namespace flint::rules // In general the easiest way to find out what they do is to read the // definition directly. // Specialise a getter called "name". The getter has one argument called "from" // of type "fromtype", and "eval" which should yield "totype". #define FLINT_DEFINE_GET2(name, totype, fromtype1, fromtype2, eval) \ template<> \ struct name \ { \ static totype get(const fromtype1& e1, const fromtype2& e2) \ { \ return eval; \ } \ }; #define FLINT_DEFINE_GET(name, totype, fromtype, eval) \ FLINT_DEFINE_GET2(name, totype, fromtype, fromtype, eval) #define FLINT_DEFINE_GET_COND(name, totype, cond, eval) \ template \ struct name >::type> \ { \ static totype get(const T& from) \ { \ return eval; \ } \ }; // Specialise a doit rule called "name" #define FLINT_DEFINE_DOIT(name, totype, fromtype, eval) \ template<> \ struct name \ { \ static void doit(totype& to, const fromtype& from) \ { \ eval; \ } \ }; // Specialise a doit rule called "name" which yields totype. It will // accept any type "T" which satisfies "cond". #define FLINT_DEFINE_DOIT_COND(name, totype, cond, eval) \ template \ struct name >::type> \ { \ static void doit(totype& to, const T& from) \ { \ eval; \ } \ }; #define FLINT_DEFINE_DOIT_COND2(name, cond1, cond2, eval) \ template \ struct name, cond2 > >::type> \ { \ static void doit(T& to, const U& from) \ { \ eval; \ } \ }; #define FLINT_DEFINE_PRINT_COND_(name, cond, eval) \ template \ struct name >::type> \ { \ static int doit(FILE* to, const T& from) \ { \ return eval; \ } \ }; #define FLINT_DEFINE_READ_COND_(name, cond, eval) \ template \ struct name >::type> \ { \ static int doit(FILE* from, T& to) \ { \ return eval; \ } \ }; #define FLINT_DEFINE_PRINT_COND(cond, eval) \ FLINT_DEFINE_PRINT_COND_(cprint, cond, eval) #define FLINT_DEFINE_PRINT_PRETTY_COND(cond, eval) \ FLINT_DEFINE_PRINT_COND_(print_pretty, cond, eval) #define FLINT_DEFINE_READ_COND(cond, eval) \ FLINT_DEFINE_READ_COND_(read, cond, eval) #define FLINT_DEFINE_PRINT_PRETTY_COND_2(cond, extratype, eval) \ template \ struct print_pretty >::type> \ { \ static int doit(FILE* to, const T& from, extratype extra) \ { \ return eval; \ } \ }; // Specialise the unary expression rule type->type. #define FLINT_DEFINE_UNARY_EXPR_(name, rtype, type, eval) \ template<> \ struct unary_expression \ { \ typedef rtype return_t; \ template \ static void doit(V& to, const type& from) \ { \ eval; \ } \ }; #define FLINT_DEFINE_UNARY_EXPR(name, type, eval) \ FLINT_DEFINE_UNARY_EXPR_(name, type, type, eval) #define FLINT_DEFINE_UNARY_EXPR_COND(name, ret_type, cond, eval) \ template \ struct unary_expression >::type> \ { \ typedef ret_type return_t; \ template \ static void doit(V& to, const T& from) \ { \ eval; \ } \ }; // Specialise the binary expression rule (type, type) -> type #define FLINT_DEFINE_BINARY_EXPR2(name, rtype, type1, type2, eval) \ template<> \ struct binary_expression \ { \ typedef rtype return_t; \ template \ static void doit(V& to, const type1& e1, const type2& e2) \ { \ eval; \ } \ }; #define FLINT_DEFINE_BINARY_EXPR(name, type, eval) \ FLINT_DEFINE_BINARY_EXPR2(name, type, type, type, eval) // Specialise the commutative binary expression rule (type, type) -> type #define FLINT_DEFINE_CBINARY_EXPR(name, type, eval) \ template<> \ struct commutative_binary_expression \ { \ typedef type return_t; \ template \ static void doit(V& to, const type& e1, const type& e2) \ { \ eval; \ } \ }; // Specialise the commutative binary expression rule (Type, T) -> Type, // where T must satisfy "cond". #define FLINT_DEFINE_CBINARY_EXPR_COND(name, Type, cond, eval) \ template \ struct commutative_binary_expression >::type> \ { \ typedef Type return_t; \ template \ static void doit(V& to, const Type& e1, const T& e2) \ { \ eval; \ } \ }; #define FLINT_DEFINE_CBINARY_EXPR_COND2(name, rettype, cond1, cond2, eval) \ template \ struct commutative_binary_expression, cond2 > >::type> \ { \ typedef rettype return_t; \ template \ static void doit(V& to, const T& e1, const U& e2) \ { \ eval; \ } \ }; // Specialise the (non-commutative) binary expression rule (Type, T) -> Type, // where T must satisfy "cond". #define FLINT_DEFINE_BINARY_EXPR_COND(name, Type, cond, eval) \ template \ struct binary_expression >::type> \ { \ typedef Type return_t; \ template \ static void doit(V& to, const Type& e1, const T& e2) \ { \ eval; \ } \ }; #define FLINT_DEFINE_BINARY_EXPR_COND2(name, rettype, cond1, cond2, eval) \ template \ struct binary_expression, cond2 > >::type> \ { \ typedef rettype return_t; \ template \ static void doit(V& to, const T& e1, const U& e2) \ { \ eval; \ } \ }; #define FLINT_DEFINE_THREEARY_EXPR_COND3(name, rettype, cond1, cond2, cond3, eval) \ template \ struct threeary_expression, cond2 , cond3 > >::type> \ { \ typedef rettype return_t; \ template \ static void doit(R& to, const T& e1, const U& e2, const V& e3) \ { \ eval; \ } \ }; #define FLINT_DEFINE_THREEARY_EXPR(name, rettype, T1, T2, T3, eval) \ template<> \ struct threeary_expression \ { \ typedef rettype return_t; \ template \ static void doit(R& to, const T1& e1, const T2& e2, const T3& e3) \ { \ eval; \ } \ }; #define FLINT_DEFINE_FOURARY_EXPR_COND4(name, rettype, cond1, cond2, cond3, cond4, eval) \ template \ struct fourary_expression, cond2 , cond3 , cond4 > >::type> \ { \ typedef rettype return_t; \ template \ static void doit(R& to, const T& e1, const U& e2, const V& e3, const W& e4) \ { \ eval; \ } \ }; #define FLINT_DEFINE_FIVEARY_EXPR_COND5(name, rettype, cond1, cond2, cond3, cond4, cond5, eval) \ template \ struct fiveary_expression, cond2 , cond3 , cond4 , cond5 > >::type> \ { \ typedef rettype return_t; \ template \ static void doit(R& to, const T& e1, const U& e2, const V& e3, const W& e4, const X& e5) \ { \ eval; \ } \ }; #define FLINT_DEFINE_SIXARY_EXPR_COND6(name, rettype, cond1, cond2, cond3, cond4, cond5, cond6, eval) \ template \ struct sixary_expression, cond2 , cond3 , cond4 , cond5 , cond6 > >::type> \ { \ typedef rettype return_t; \ template \ static void doit(R& to, const T& e1, const U& e2, const V& e3, const W& e4, const X& e5, const Y& e6) \ { \ eval; \ } \ }; #define FLINT_DEFINE_SEVENARY_EXPR_COND7(name, rettype, cond1, cond2, cond3, cond4, cond5, cond6, cond7, eval) \ template \ struct sevenary_expression, cond2 , cond3 , cond4 , cond5 , cond6, cond7 > >::type> \ { \ typedef rettype return_t; \ template \ static void doit(R& to, const T& e1, const U& e2, const V& e3, const W& e4, const X& e5, const Y& e6, const Z& e7) \ { \ eval; \ } \ }; #endif flint2-2.8.4/flintxx/stdmath.h000066400000000000000000000077371414523752600162630ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FLINT_CXX_STDMATH_H #define FLINT_CXX_STDMATH_H #include "expression.h" #include "expression_traits.h" // This file defines lazy operations which are used by several different flint // classes. namespace flint { FLINT_DEFINE_BINOP(pow) FLINT_DEFINE_BINOP(pow_binexp) FLINT_DEFINE_BINOP(root) FLINT_DEFINE_UNOP(abs) FLINT_DEFINE_UNOP(exp) FLINT_DEFINE_UNOP(log) FLINT_DEFINE_UNOP(sqrt) FLINT_DEFINE_UNOP(inv) FLINT_DEFINE_UNOP(sqr) FLINT_DEFINE_UNOP(sqr_classical) FLINT_DEFINE_UNOP(sqr_KS) FLINT_DEFINE_UNOP(height) FLINT_DEFINE_BINOP(divexact) FLINT_DEFINE_BINOP(divrem) FLINT_DEFINE_BINOP(fdiv_2exp) FLINT_DEFINE_BINOP(mul_2exp) FLINT_DEFINE_BINOP(mul_classical) FLINT_DEFINE_BINOP(mul_KS) FLINT_DEFINE_BINOP(tdiv) FLINT_DEFINE_BINOP(tdiv_2exp) FLINT_DEFINE_THREEARY(mulhigh) FLINT_DEFINE_THREEARY(mulhigh_classical) FLINT_DEFINE_THREEARY(mullow) FLINT_DEFINE_THREEARY(mullow_classical) FLINT_DEFINE_THREEARY(mullow_KS) FLINT_DEFINE_BINOP(smod) // "symmetric" % // poly functions FLINT_DEFINE_BINOP(compose) FLINT_DEFINE_BINOP(compose_divconquer) FLINT_DEFINE_BINOP(compose_horner) FLINT_DEFINE_BINOP(div_basecase) FLINT_DEFINE_BINOP(div_divconquer) FLINT_DEFINE_BINOP(divrem_basecase) FLINT_DEFINE_BINOP(divrem_divconquer) FLINT_DEFINE_BINOP(div_root) FLINT_DEFINE_BINOP(evaluate) FLINT_DEFINE_BINOP(bit_pack) FLINT_DEFINE_BINOP(shift_left) FLINT_DEFINE_BINOP(shift_right) FLINT_DEFINE_BINOP(rem_basecase) FLINT_DEFINE_BINOP(resultant) FLINT_DEFINE_BINOP(reverse) FLINT_DEFINE_BINOP(taylor_shift) FLINT_DEFINE_BINOP(taylor_shift_horner) FLINT_DEFINE_UNOP(content) FLINT_DEFINE_UNOP(derivative) FLINT_DEFINE_UNOP(integral) FLINT_DEFINE_UNOP(make_monic) FLINT_DEFINE_UNOP(twonorm) FLINT_DEFINE_UNOP(bound_roots) FLINT_DEFINE_UNOP(primitive_part) FLINT_DEFINE_BINOP(inv_series) FLINT_DEFINE_BINOP(inv_series_newton) FLINT_DEFINE_BINOP(revert_series) FLINT_DEFINE_BINOP(revert_series_lagrange) FLINT_DEFINE_BINOP(revert_series_lagrange_fast) FLINT_DEFINE_BINOP(revert_series_newton) FLINT_DEFINE_BINOP(sqrt_series) FLINT_DEFINE_BINOP(invsqrt_series) FLINT_DEFINE_BINOP(exp_series) FLINT_DEFINE_BINOP(log_series) FLINT_DEFINE_BINOP(atan_series) FLINT_DEFINE_BINOP(atanh_series) FLINT_DEFINE_BINOP(asin_series) FLINT_DEFINE_BINOP(asinh_series) FLINT_DEFINE_BINOP(tan_series) FLINT_DEFINE_BINOP(sin_series) FLINT_DEFINE_BINOP(cos_series) FLINT_DEFINE_BINOP(sinh_series) FLINT_DEFINE_BINOP(cosh_series) FLINT_DEFINE_BINOP(tanh_series) FLINT_DEFINE_THREEARY(compose_series) FLINT_DEFINE_THREEARY(compose_series_brent_kung) FLINT_DEFINE_THREEARY(compose_series_divconquer) FLINT_DEFINE_THREEARY(compose_series_horner) FLINT_DEFINE_THREEARY(div_series) FLINT_DEFINE_THREEARY(pow_trunc) FLINT_DEFINE_THREEARY(pow_trunc_binexp) FLINT_DEFINE_BINOP(compeval) // matrix functions in flintxx/matrix.h // chinese remaindering FLINT_DEFINE_FIVEARY(CRT) FLINT_DEFINE_FOURARY_HERE(CRT) // four argument version FLINT_DEFINE_THREEARY(multi_CRT) FLINT_DEFINE_BINOP_HERE(multi_CRT) // two argument version // implementation of compeval namespace rules { // implementation of compeval // TODO do at level of "struct evaluation" instead? template struct binary_expression >, traits::is_implemented > > >::type> : mp::if_< traits::is_implemented >, binary_expression, binary_expression >::type { }; } // rules } // flint #endif flint2-2.8.4/flintxx/test/000077500000000000000000000000001414523752600154075ustar00rootroot00000000000000flint2-2.8.4/flintxx/test/helpers.h000066400000000000000000000110421414523752600172200ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_TEST_HELPERS_H #define CXX_TEST_HELPERS_H #include #include #include #include #include #include "flintxx/flint_classes.h" #ifndef EXIT_STATEMENT #define EXIT_STATEMENT std::exit(1) #endif #define tassert(expr) do \ { \ if (!(expr)) \ { \ std::cout << "FAIL\n" __FILE__ ":" << __LINE__ << ": assertion " #expr " failed\n"; \ EXIT_STATEMENT; \ } \ } while (0) // Whether or not the compiler is good enough to compile all of t-fmpzxx.cpp // in reasonable time and space. #ifndef HAVE_FAST_COMPILER #ifdef __clang__ // clang 3.4 works; let's suppose all work until someone complains #define HAVE_FAST_COMPILER 1 #elif defined(__GNUC__) // gcc 4.7.3 is good enough, supposedly all higher ones are too #define HAVE_FAST_COMPILER \ (__GNUC__ > 4 || (__GNUC__ >= 4 && \ ((__GNUC_MINOR__ == 7 && __GNUC_PATCHLEVEL__ >= 3) \ || (__GNUC_MINOR__ > 7)))) #else #define HAVE_FAST_COMPILER 0 #endif #endif // Count the number of temporaries needed to evaluate an expression of type T template unsigned count_temporaries(const T&) { return T::ev_traits_t::rule_t::temporaries_t::len; } template bool typed_equals(const T&, const U&) { return false; } template bool typed_equals(const T& a, const T& b) { return a == b; } #define _assert_exception(expr, type) do \ { \ bool exception_occurred = false; \ try \ { \ expr; \ } \ catch(const type&) \ { \ exception_occurred = true; \ } \ if(!exception_occurred) \ { \ std::cout << "FAIL\n" __FILE__ ":" << __LINE__ \ << ": expression did not cause an exception: " #expr " \n"; \ EXIT_STATEMENT; \ } \ } while(0) #define assert_exception(expr) _assert_exception(expr, flint_exception) template void test_print_read(const T& t) { #if !defined (__WIN32) && !defined (__CYGWIN__) T tmp(t); tmp.set_zero(); FILE * f = std::fopen("test_print_read", "w+"); tassert(f); print(f, t+t); std::fflush(f); std::fclose(f); f = std::fopen("test_print_read", "r"); typename flint::flint_classes::to_ref::type tmpref(tmp); tassert(read(f, tmpref) > 0); tassert(t+t == tmp); tassert(std::remove("test_print_read") == 0); #endif } template void test_print_read_pretty(const T& t) { #if !defined (__WIN32) && !defined (__CYGWIN__) T tmp(t); tmp.set_zero(); FILE * f = std::fopen("test_print_read", "w+"); tassert(f); print_pretty(f, t+t, "x"); std::fflush(f); std::fclose(f); f = std::fopen("test_print_read", "r"); char* rvar; typename flint::flint_classes::to_ref::type tmpref(tmp); tassert(read_pretty(f, tmpref, &rvar) > 0); tassert(t+t == tmp); tassert(std::remove("test_print_read") == 0); flint_free(rvar); #endif } inline std::string readfile(const char* name) { std::ifstream t(name); return std::string(std::istreambuf_iterator(t), std::istreambuf_iterator()); } template void tassert_fprint(const T& t, const char* expected) { #if !defined (__WIN32) && !defined (__CYGWIN__) FILE * f = std::fopen("test_fprint", "w+"); tassert(f); print(f, t); std::fflush(f); std::fclose(f); tassert(readfile("test_fprint") == expected); tassert(std::remove("test_fprint") == 0); #endif } template void tassert_fprint_pretty(const T& t, const U& extra, const char* expected) { #if !defined (__WIN32) && !defined (__CYGWIN__) FILE * f = std::fopen("test_fprint_pretty", "w+"); tassert(f); print_pretty(f, t, extra); std::fflush(f); std::fclose(f); tassert(readfile("test_fprint_pretty") == expected); tassert(std::remove("test_fprint_pretty") == 0); #endif } template void tassert_fprint_pretty(const T& t, const char* expected) { #if !defined (__WIN32) && !defined (__CYGWIN__) FILE * f = std::fopen("test_fprint_pretty", "w+"); tassert(f); print_pretty(f, t); std::fflush(f); std::fclose(f); tassert(readfile("test_fprint_pretty") == expected); tassert(std::remove("test_fprint_pretty") == 0); #endif } #endif flint2-2.8.4/flintxx/test/make-compiler-errors-report.sh000077500000000000000000000021351414523752600233170ustar00rootroot00000000000000#!/bin/bash CC=$1 TESTS=$2 FLAGS="-Wall -pedantic" TMPF="/tmp/make-report.tmp" # make sure we are in the test directory cd $(dirname $0) if [ "$CC" = "" ] ; then CC=g++ fi if [ "$TESTS" = "" ] ; then TESTS="TEST_FMPZXX_INIT_WRONG TEST_FMPZXX_INIT_2 TEST_FMPZXX_ASSIGN_WRONG TEST_FMPZXX_CONVERT_WRONG TEST_FMPZXX_REF_INIT_WRONG_1 TEST_FMPZXX_REF_INIT_WRONG_2 TEST_FMPZXX_SRCREF_ASSIGN TEST_FMPZXX_ARITH_WRONG TEST_FMPZXX_ARITH_WRONG_DEEP TEST_FMPZXX_ARITHFUNC_WRONG_NARGS TEST_FMPZXX_ARITHFUNC_WRONG_TYPE TEST_FMPZXX_ARITHFUNC_WRONG_TYPE2 TEST_PADICXX_FORGET_EVAL" fi INCS=$(make -C ../../ print-INCS | grep 'INCS=' | sed 's/^INCS=//') for test in $TESTS ; do echo $test $CC -E $INCS $FLAGS t-compiler-errors.cc -D$test -DEXTRACTING_SAMPLE \ | grep -v '^#' | sed 's/^ //' $CC -c -o /dev/null $INCS $FLAGS t-compiler-errors.cc -D$test 2>$TMPF echo "Compiler error output is $(cat $TMPF | wc -l) line(s), $(cat $TMPF | wc -c) characters" echo "------START COMPILER ERROR OUTPUT-------" cat $TMPF echo "------END COMPILER ERROR OUTPUT---------" echo echo done flint2-2.8.4/flintxx/test/myint.h000066400000000000000000000256751414523752600167370ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_TEST_MYINT_H #define CXX_TEST_MYINT_H CXX_TEST_MYINT_H #include #include #include "flintxx/expression.h" namespace flint { template class my_expression : public expression, Operation, Data> { public: my_expression() {}; template explicit my_expression(const T& t) : expression, Operation, Data>(t) {} template my_expression& operator=(const T& t) { this->set(t); return *this; } protected: explicit my_expression(const Data& d) : expression, Operation, Data>(d) {} template friend class flint::expression; }; struct data { int payload; bool* destroyed; int extra; data() : payload(-1), destroyed(0), extra(42) {} ~data() { if(destroyed) *destroyed = true; } data(const data& d) : payload(d.payload), destroyed(0), extra(1) {} data(int i) : payload(i), destroyed(0), extra(2) {} data(char i) : payload(i), destroyed(0), extra(3) {} }; typedef my_expression myint; template class my_expression2 : public expression, Operation, Data> { public: // cannot have a default constructor typedef expression, Operation, Data> base_t; typedef typename base_t::evaluated_t evaluated_t; template explicit my_expression2(const T& t) : base_t(t) {} template explicit my_expression2(T& t) : base_t(t) {} template my_expression2& operator=(const T& t) { this->set(t); return *this; } evaluated_t create_temporary() const { return evaluated_t(WORD(0)); } protected: explicit my_expression2(const Data& d) : base_t(d) {} template friend class flint::expression; }; struct longref_data; struct longcref_data; struct long_data; typedef my_expression2 mylong; typedef my_expression2 mylong_ref; typedef my_expression2 mylong_cref; namespace traits { template<> struct can_evaluate_into : mp::true_ { }; } struct long_data { slong payload; // no default constructor long_data(slong d) : payload(d) {} long_data(const myint& m) : payload(m._data().payload) {} long_data(const mylong_ref&); long_data(const mylong_cref&); }; struct longref_data { slong& payload; longref_data(mylong& l) : payload(l._data().payload) {} }; struct longcref_data { const slong& payload; longcref_data(const mylong& l) : payload(l._data().payload) {} longcref_data(mylong_ref lr) : payload(lr._data().payload) {} }; inline long_data::long_data(const mylong_ref& mlr) : payload(mlr._data().payload) {} inline long_data::long_data(const mylong_cref& mlr) : payload(mlr._data().payload) {} namespace mylong_traits { template struct is_source : mp::false_ { }; template struct is_target : mp::false_ { }; template<> struct is_source : mp::true_ { }; template<> struct is_source : mp::true_ { }; template<> struct is_source : mp::true_ { }; template<> struct is_target : mp::true_ { }; template<> struct is_target : mp::true_ { }; } FLINT_DEFINE_FOURARY(fourary_test) FLINT_DEFINE_FIVEARY(fiveary_test) FLINT_DEFINE_SIXARY(sixary_test) FLINT_DEFINE_SEVENARY(sevenary_test) namespace rules { FLINT_DEFINE_FOURARY_EXPR_COND4(fourary_test_op, myint, traits::is_integer, traits::is_integer, traits::is_integer, traits::is_integer, to._data().payload = e1 + e2 + e3 + e4) FLINT_DEFINE_FIVEARY_EXPR_COND5(fiveary_test_op, myint, traits::is_integer, traits::is_integer, traits::is_integer, traits::is_integer, traits::is_integer, to._data().payload = e1 + e2 + e3 + e4 + e5) FLINT_DEFINE_SIXARY_EXPR_COND6(sixary_test_op, myint, traits::is_integer, traits::is_integer, traits::is_integer, traits::is_integer, traits::is_integer, traits::is_integer, to._data().payload = e1 + e2 + e3 + e4 + e5 + e6) FLINT_DEFINE_SEVENARY_EXPR_COND7(sevenary_test_op, myint, traits::is_integer, traits::is_integer, traits::is_integer, traits::is_integer, traits::is_integer, traits::is_integer, traits::is_integer, to._data().payload = e1 + e2 + e3 + e4 + e5 + e6 + e7) template<> struct print { static void doit(const myint& v, std::ostream& o) { o << v._data().payload; } }; template<> struct assignment { static void doit(myint& to, const myint& from) { to._data().payload = from._data().payload; to._data().extra = 4; } }; template<> struct assignment { static void doit(myint& to, slong from) { to._data().payload = from; to._data().extra = 5; } }; template<> struct to_string { static std::string get(const myint& i, int base /* ignored */) { std::ostringstream oss; oss << i; return oss.str(); } }; template<> struct equals { static bool get(const myint& i1, const myint& i2) { return i1._data().payload == i2._data().payload; } }; template<> struct equals { static bool get(const myint& i1, int i2) { return i1._data().payload == i2; } }; template<> struct conversion { static int get(const myint& from) { return from._data().payload; } }; template<> struct swap { static void doit(myint& e1, myint& e2) { int tmp; tmp = e1._data().payload; e1._data().payload = e2._data().payload; e2._data().payload = tmp; e1._data().extra = 1234; e2._data().extra = 1234; } }; template<> struct commutative_binary_expression { typedef myint return_t; static void doit(myint& to, const myint& a1, const myint& a2) { to._data().payload = a1._data().payload + a2._data().payload; } }; template struct commutative_binary_expression, operations::plus>::type, T> { typedef myint return_t; static void doit(myint& to, const myint& a1, T a2) { to._data().payload = a1._data().payload + a2; } }; template<> struct commutative_binary_expression { typedef myint return_t; static void doit(myint& to, const myint& a1, const myint& a2) { to._data().payload = a1._data().payload * a2._data().payload; } }; template<> struct binary_expression { typedef myint return_t; static void doit(myint& to, const myint& a1, const myint& a2) { to._data().payload = a1._data().payload - a2._data().payload; } }; template<> struct binary_expression { typedef myint return_t; static void doit(myint& to, const myint& a1, const myint& a2) { to._data().payload = a1._data().payload / a2._data().payload; } }; template<> struct binary_expression { typedef myint return_t; static void doit(myint& to, const myint& a1, const myint& a2) { to._data().payload = a1._data().payload % a2._data().payload; } }; template<> struct binary_expression { typedef myint return_t; static void doit(myint& to, const myint& a1, int a2) { if (a2 >= 0) to._data().payload = a1._data().payload << a2; else to._data().payload = a1._data().payload >> (-a2); } }; template<> struct unary_expression { typedef myint return_t; static void doit(myint& to, const myint& from) { to._data().payload = - from._data().payload; } }; ///////////////////////////////////////////////////////////////////////////// // Minimal rules for mylong ///////////////////////////////////////////////////////////////////////////// template struct equals, mylong_traits::is_source > >::type> { static bool get(const T& i1, const U& i2) { return i1._data().payload == i2._data().payload; } }; template struct equals >::type> { static bool get(const T& i1, slong i2) { return i1._data().payload == i2; } }; template struct commutative_binary_expression, mylong_traits::is_source >, operations::plus>::type, U> { typedef mylong return_t; template static void doit(V& to, const T& a1, const U& a2) { to._data().payload = a1._data().payload + a2._data().payload; } }; template struct commutative_binary_expression, myint>::type, operations::plus, U> { typedef mylong return_t; template static void doit(V& to, const myint& a1, const U& a2) { to._data().payload = a1._data().payload + a2._data().payload; } }; template struct assignment, mylong_traits::is_source > >::type> { static void doit(T& to, const U& from) { to._data().payload = from._data().payload; } }; template struct assignment >::type> { static void doit(T& to, slong from) { to._data().payload = from; } }; template struct assignment >::type> { static void doit(T& to, const myint& from) { to._data().payload = from._data().payload; } }; FLINT_DEFINE_READ_COND(mylong_traits::is_target, flint_fscanf(from, "%wd", &to._data().payload)) FLINT_DEFINE_PRINT_COND(mylong_traits::is_source, flint_fprintf(to, "%wd", from._data().payload)) FLINT_DEFINE_PRINT_PRETTY_COND(mylong_traits::is_source, flint_fprintf(to, "<%wd>", from._data().payload)) } // rules } // flint #endif flint2-2.8.4/flintxx/test/t-arithxx.cpp000066400000000000000000000146221414523752600200500ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "arithxx.h" #include "helpers.h" using namespace flint; void test_stirling() { #define STIRLING(func, matfunc, n, k) \ {\ tassert(func##_vec(n, k).size() == k); \ fmpz_vecxx v1(func##_vec(n, k).evaluate() /* test temporary alloc */); \ for(slong i = 0;i < v1.size();++i) \ tassert(v1[i] == func(n, i)); \ tassert(func##_vec_next(func##_vec(n, k), n+1).size() == k); \ fmpz_vecxx v2(func##_vec_next(v1, n+1)); \ for(slong i = 0;i < v2.size();++i) \ tassert(v2[i] == func(n+1, i)); \ fmpz_vecxx v3(func##_vec(n, n+1)); \ fmpz_vecxx v4(func##_vec_next(v3, n+1)); \ tassert(v4.size() == n+2 && v3.size() == n+1); \ for(slong i = 0;i < v4.size();++i) \ tassert(v4[i] == func(n+1, i)); \ tassert(matfunc(n, k).rows() == n && matfunc(n, k).cols() == k); \ fmpz_matxx M(matfunc(n, k).evaluate() /* test temporaries */); \ for(slong i = 0;i < M.rows();++i) \ for(slong j = 0;j < M.cols();++j) \ tassert(M.at(i, j) == func(i, j)); \ } STIRLING(stirling_number_1u, stirling_matrix_1u, 10, 6) STIRLING(stirling_number_1, stirling_matrix_1, 10, 6) STIRLING(stirling_number_2, stirling_matrix_2, 10, 6) } void test_bell() { tassert(bell_number_vec(10).size() == 10); fmpz_vecxx v(bell_number_vec(10)); tassert(v == bell_number_vec_recursive(10)); tassert(v == bell_number_vec_multi_mod(10)); for(slong i = 0;i < v.size();++i) tassert(v[i] == bell_number(static_cast(i))); tassert(bell_number(10u) == bell_number_bsplit(10u)); tassert(bell_number(10u) == bell_number_multi_mod(10u)); nmodxx_ctx p(1031); tassert(bell_number_nmod(10u, p) == nmodxx::red(bell_number(10u), p)); nmod_vecxx v2(bell_number_nmod_vec(10u, p)); tassert(v2.size() == 10); for(slong i = 0;i < v2.size();++i) tassert(v2[i] == nmodxx::red(v[i], p)); tassert(v2 == bell_number_nmod_vec_series(10u, p)); tassert(v2 == bell_number_nmod_vec_recursive(10u, p)); tassert(fmpzxx(2).pow( static_cast (bell_number_size(10u))) > bell_number(10u)); } void test_bernoulli() { tassert(bernoulli_number(10u).den() == bernoulli_number_denom(10u)); tassert(fmpqxx(2, 1u).pow( static_cast (bernoulli_number_size(10u))) > bernoulli_number(10u)); fmpq_polyxx poly(bernoulli_polynomial(10u)); tassert(poly.degree() == 10); for(slong i = 0;i < poly.length();++i) tassert(poly.get_coeff(i) == fmpqxx(bin(10u, (unsigned) i)*bernoulli_number(10u - (unsigned) i))); tassert(bernoulli_number_vec(10u).size() == 10); for(unsigned i = 0;i < 10;++i) tassert(bernoulli_number_vec(10u)[i] == bernoulli_number(i)); } void test_euler() { tassert(fmpzxx(2).pow( static_cast (euler_number_size(10u))) > euler_number(10u)); fmpq_polyxx poly(euler_polynomial(10u)); tassert(poly.degree() == 10); tassert(poly(fmpqxx(1, 2u))*fmpqxx(2, 1u).pow(10) == fmpqxx(euler_number(10u).evaluate(), fmpzxx(1))); tassert(euler_number_vec(10u).size() == 10); for(unsigned i = 0;i < 10;++i) tassert(euler_number_vec(10u)[i] == euler_number(i)); } void test_legendre() { const unsigned short N = 10; fmpq_polyxx f; f = "3 -1 0 1"; f = f.pow(N); for(unsigned i = 0;i < N;++i) f = f.derivative(); tassert(legendre_polynomial(N) == f * fmpqxx(fmpzxx(1), (fmpzxx(2).pow(N)*fac(N)).evaluate())); fmpq_polyxx x; x = "2 0 1"; f = chebyshev_t_polynomial(N); f = f(cos_series(x, N)); f.truncate(N); tassert(f == cos_series(N*x, N)); tassert(chebyshev_u_polynomial(N)*(N + 1) == chebyshev_t_polynomial(N+1u).derivative()); } void test_multiplicative() { fmpzxx p(1031); tassert(euler_phi(p) == p-1u); tassert(moebius_mu(p) == -1); tassert(divisor_sigma(p, 4u) == 1u + p.pow(4u)); tassert(divisors(p).to_string() == "2 1 " + p.to_string()); fmpz_polyxx q, one; q = "2 0 1"; one = "1 1"; fmpz_polyxx res(q * (one - q).pow(24u) * (one - q*q).pow(24u)); for(unsigned i = 3;i < 10;++i) res *= (one - q.pow(i)).pow(24u); res.truncate(10); tassert(res == ramanujan_tau_series(10)); for(int i = 0;i < 10;++i) tassert(ramanujan_tau_series(i+1).get_coeff(i) == ramanujan_tau(fmpzxx(i))); } void test_polys() { // just very basic tests ... ulong N = 1234; tassert(cyclotomic_polynomial(N).degree() == euler_phi(fmpzxx(N))); tassert(cos_minpoly(N).degree() == euler_phi(fmpzxx(N))/2); tassert(swinnerton_dyer_polynomial(8u).degree() == fmpzxx(2).pow(8u)); } void test_dedekind() { frandxx state; fmpzxx h = fmpzxx::randtest_unsigned(state, 10); fmpzxx k = fmpzxx::randtest_unsigned(state, 10); tassert(dedekind_sum_naive(h, k) == dedekind_sum(h, k)); k /= gcd(h, k); tassert(dedekind_sum_naive(h, k) == dedekind_sum(h, k)); } void test_number_of_partitions() { unsigned short N = 15; nmodxx_ctx p(1031); fmpz_vecxx v1(number_of_partitions_vec(N)); nmod_vecxx v2(number_of_partitions_nmod_vec(N, p)); tassert(v1.size() == v2.size() && v1.size() == N); for(unsigned i = 0;i < N;++i) { tassert(v1[i] == number_of_partitions(i)); tassert(nmodxx::red(v1[i], p) == v2[i]); } } void test_sum_of_squares() { unsigned short N = 15; fmpz_vecxx v(sum_of_squares_vec(7u, N)); tassert(v.size() == N); for(unsigned i = 0;i < N;++i) tassert(v[i] == sum_of_squares(7u, fmpzxx(i))); } int main() { std::cout << "arithxx...."; tassert(primorial(4) == 2*3); tassert(harmonic_number(3) == fmpqxx(1, 1u) + fmpqxx(1, 2u) + fmpqxx(1, 3u)); test_stirling(); test_bell(); test_bernoulli(); test_euler(); test_legendre(); test_multiplicative(); test_polys(); test_dedekind(); test_number_of_partitions(); test_sum_of_squares(); tassert(landau_function_vec(9)[8] == 15); std::cout << "PASS\n"; return 0; } flint2-2.8.4/flintxx/test/t-codegen.cpp000066400000000000000000000571211414523752600177660ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include // whether or not the compiler suppors __attribute__(__optimize__(..)) #ifndef HAVE_OPTIMIZE_ATTRIBUTE #ifdef __GNUC__ #define HAVE_OPTIMIZE_ATTRIBUTE (__GNUC__ >= 4 && __GNUC_MINOR__ >= 4) #else #define HAVE_OPTIMIZE_ATTRIBUTE 0 #endif #endif #ifndef DO_CODEGEN_CHECKS #if !HAVE_OPTIMIZE_ATTRIBUTE #define DO_CODEGEN_CHECKS 0 #elif defined(__GNUC__) // XXX this will need tweaking - look here if things break // b/c of compiler versions #define DO_CODEGEN_CHECKS \ (__GNUC__ == 4 && __GNUC_MINOR__ == 7 && __GNUC_PATCHLEVEL__ == 3 \ && __x86_64__) #else #define DO_CODEGEN_CHECKS 0 #endif #endif #if !DO_CODEGEN_CHECKS #define EXIT_STATEMENT throw skippable_exception("did not expect pass anyway") #endif #include #include // Exception class to indicate that this test cannot proceed, e.g. because // binutils is not installed or because we cannot interpret the disassembled // code. // This should not cause the test to fail, since it is not portable. class skippable_exception : public std::runtime_error { public: skippable_exception(const std::string& n) : std::runtime_error(n) {} }; #include "flintxx/test/helpers.h" #include "fmpz_matxx.h" #include "fmpz_polyxx.h" #include "fmpzxx.h" #include "nmod_matxx.h" #include "nmod_polyxx.h" #include "nmod_vecxx.h" #include "flintxx/tuple.h" #include "flintxx/vector.h" // Run a command and recver the output. std::string exec(const std::string& cmd) { FILE* pipe = popen(cmd.c_str(), "r"); if (!pipe) throw skippable_exception("cannot execute command" + cmd); char buffer[128]; std::string result = ""; while(!feof(pipe)) { if(fgets(buffer, 128, pipe) != NULL) result += buffer; } pclose(pipe); return result; } // Disassembled a function contained in the binary "program". std::string disass(const char* program, const std::string& function) { std::string all = exec(std::string("objdump -d ") + program); std::string marker = "<" + function + ">:"; std::size_t start = all.find(marker); if(start == std::string::npos) throw skippable_exception("cannot find function " + function); all = all.substr(start + marker.size()); std::size_t len = all.find("\n\n"); if(len == std::string::npos) throw skippable_exception("cannot find end of function " + function); return all.substr(0, len); } std::vector& split(const std::string &s, char delim, std::vector& elems) { std::stringstream ss(s); std::string item; while (std::getline(ss, item, delim)) { elems.push_back(item); } return elems; } std::vector lines(const std::string& input) { std::vector result; return split(input, '\n', result); } // Strip addresses from disassembly, to allow comparison. E.g. // // 401790: 45 0f be c9 movsbl %r9b,%r9d // 401794: 44 89 07 mov %r8d,(%rdi) // // --> // // movsbl %r9b,%r9d // mov %r8d,(%rdi) // std::string stripaddr(const std::string& input) { std::string result; std::vector ls = lines(input); for(unsigned i = 0;i < ls.size();++i) { if(ls[i] == "") continue; std::size_t pos = ls[i].find(":\t"); if(pos == std::string::npos) result += ls[i]; else { std::string tmp = ls[i].substr(pos+2); pos = tmp.find("\t"); if(pos == std::string::npos) result += tmp; result += tmp.substr(pos+1); } result += '\n'; } return result; } std::string stripnop(const std::string& input) { std::string result; std::vector ls = lines(input); for(unsigned i = 0;i < ls.size();++i) { if(ls[i].find("\tnop") != std::string::npos) continue; result += ls[i]; result += '\n'; } return result; } // Count the number of occurrences of a substring. int count(const std::string& str, const std::string& sub) { if(sub.length() == 0) return 0; int count = 0; for(size_t offset = str.find(sub); offset != std::string::npos; offset = str.find(sub, offset + sub.length())) ++count; return count; } // Check if two quantities are equal up to a certain percentage of error. template bool fuzzy_equals(T v1, T v2, double perc) { double d1 = double(v1); double d2 = double(v2); return d1*(1-perc) <= d2 && d2 <= d1*(1+perc); } using namespace flint; using namespace mp; typedef make_vector_n::type fmpzxx_vector; extern "C" { #if HAVE_OPTIMIZE_ATTRIBUTE #define DEFINE_FUNC(name, args) \ void name args __attribute__((__optimize__("no-exceptions"))); \ void name args #else #define DEFINE_FUNC(name, args) \ void name args #endif DEFINE_FUNC(test_tuple_merge_1, (int& o1, int& o2, int& o3, int i1, slong i2, char i3, int i4)) { typedef make_tuple make3; typedef make_tuple make2; typedef merge_tuple merge; merge::type merged; // merged.head = i3; merged.tail.head = i1; merged.tail.tail.head = i2; merged.tail.tail.tail.head = i4; make3::type extract = merge::get_first(merged); o1 = extract.head; // i2 o2 = extract.tail.head; // i1 o3 = extract.tail.tail.head; // i3 } DEFINE_FUNC(test_tuple_merge_2, (int& o1, int& o2, int& o3, int i1, slong i2, char i3, int i4)) { o1 = i2; o2 = i1; o3 = i3; } DEFINE_FUNC(test_tuple_concat_1, (tuple::type>& out, const make_tuple::type& in1, const make_tuple::type& in2)) { out = concat_tuple< make_tuple::type, make_tuple::type >::doit(in1, in2); } DEFINE_FUNC(test_tuple_concat_2, (tuple::type>& out, const make_tuple::type& in1, const make_tuple::type& in2)) { out.head = in1.head; out.tail.head = in1.tail.head; out.tail.tail.head = in2.head; out.tail.tail.tail.head = in2.tail.head; } DEFINE_FUNC(test_tuple_back_1, (make_tuple::type& out, int i1, slong i2, char i3)) { typedef make_tuple::type type; type pointers; back_tuple::init(pointers, out, 0); *pointers.head = i1; *pointers.tail.head = i2; *pointers.tail.tail.head = i3; } DEFINE_FUNC(test_tuple_back_2, (make_tuple::type& out, int i1, slong i2, char i3)) { out.head = i1; out.tail.head = i2; out.tail.tail.head = i3; } DEFINE_FUNC(test_tuple_extract_1, (make_homogeneous_tuple::type& out, const make_homogeneous_tuple::type& in)) { out = htuples::extract<4>(in); } DEFINE_FUNC(test_tuple_extract_2, (make_homogeneous_tuple::type& out, const make_homogeneous_tuple::type& in)) { out.head = in.head; out.tail.head = in.tail.head; out.tail.tail.head = in.tail.tail.head; out.tail.tail.tail.head = in.tail.tail.tail.head; } DEFINE_FUNC(test_tuple_removeres_1, (make_homogeneous_tuple::type& out, int in1, int in2)) { make_homogeneous_tuple::type tmp = make_tuple::make(1, in1, in2); out = htuples::removeres(tmp, 1); } DEFINE_FUNC(test_tuple_removeres_2, (make_homogeneous_tuple::type& out, int in1, int in2)) { out.head = in1; out.tail.head = in2; } DEFINE_FUNC(test_fmpzxx_symadd_1, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { out = ((a + b) + (c + d)) + ((a + c) + (b + d)); } DEFINE_FUNC(test_fmpzxx_symadd_2, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { fmpz_t tmp1, tmp2, tmp3; fmpz_init(tmp1); fmpz_init(tmp2); fmpz_init(tmp3); fmpz_add(tmp1, a._fmpz(), b._fmpz()); fmpz_add(tmp2, c._fmpz(), d._fmpz()); fmpz_add(tmp3, tmp1, tmp2); fmpz_add(tmp1, a._fmpz(), c._fmpz()); fmpz_add(tmp2, b._fmpz(), d._fmpz()); fmpz_add(tmp1, tmp1, tmp2); fmpz_add(out._fmpz(), tmp1, tmp3); fmpz_clear(tmp1); fmpz_clear(tmp2); fmpz_clear(tmp3); } DEFINE_FUNC(test_fmpzxx_asymadd_1, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { out = (a + (((b + (c + (a + b))) + c) + d)); } DEFINE_FUNC(test_fmpzxx_asymadd_2, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { fmpz_t tmp; fmpz_init(tmp); fmpz_add(tmp, a._fmpz(), b._fmpz()); fmpz_add(tmp, c._fmpz(), tmp); fmpz_add(tmp, b._fmpz(), tmp); fmpz_add(tmp, tmp, c._fmpz()); fmpz_add(tmp, tmp, d._fmpz()); fmpz_add(out._fmpz(), a._fmpz(), tmp); fmpz_clear(tmp); } DEFINE_FUNC(test_fmpzxx_asymadd_3, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { out = a + b + c + a + b + c + d; } DEFINE_FUNC(test_fmpzxx_ternary_1, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { out = a + ((a+b) + c*d); } DEFINE_FUNC(test_fmpzxx_ternary_2, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { fmpz_t tmp; fmpz_init(tmp); fmpz_add(tmp, a._fmpz(), b._fmpz()); fmpz_addmul(tmp, c._fmpz(), d._fmpz()); fmpz_add(out._fmpz(), a._fmpz(), tmp); fmpz_clear(tmp); } DEFINE_FUNC(test_fmpzxx_ternary_3, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { out = a + ((a+b) + ((c+a) + (a+d))*d); } DEFINE_FUNC(test_fmpzxx_ternary_4, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { fmpz_t tmp1, tmp2; fmpz_init(tmp1);fmpz_init(tmp2); fmpz_add(tmp1, c._fmpz(), a._fmpz()); fmpz_add(tmp2, a._fmpz(), d._fmpz()); fmpz_add(tmp1, tmp1, tmp2); fmpz_add(tmp2, a._fmpz(), b._fmpz()); fmpz_addmul(tmp2, tmp1, d._fmpz()); fmpz_add(out._fmpz(), a._fmpz(), tmp2); fmpz_clear(tmp1);fmpz_clear(tmp2); } DEFINE_FUNC(test_fmpzxx_ternary_5, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { out += a*b; } DEFINE_FUNC(test_fmpzxx_ternary_6, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { fmpz_addmul(out._fmpz(), a._fmpz(), b._fmpz()); } DEFINE_FUNC(test_fmpzxx_ternary_7, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { out += a*(b+c); } DEFINE_FUNC(test_fmpzxx_ternary_8, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { fmpz_t tmp; fmpz_init(tmp); fmpz_add(tmp, b._fmpz(), c._fmpz()); fmpz_addmul(out._fmpz(), a._fmpz(), tmp); fmpz_clear(tmp); } DEFINE_FUNC(test_fmpzxx_ternary_9, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { out += (a+d)*(b+c); } DEFINE_FUNC(test_fmpzxx_ternary_10, (fmpzxx& out, const fmpzxx& a, const fmpzxx& b, const fmpzxx& c, const fmpzxx& d)) { fmpz_t tmp1, tmp2; fmpz_init(tmp1); fmpz_init(tmp2); fmpz_add(tmp1, b._fmpz(), c._fmpz()); fmpz_add(tmp2, a._fmpz(), d._fmpz()); fmpz_addmul(out._fmpz(), tmp1, tmp2); fmpz_clear(tmp1); fmpz_clear(tmp2); } DEFINE_FUNC(test_fmpzxx_ref_1, (fmpzxx_ref out, fmpzxx_srcref in1, fmpzxx_srcref in2)) { out = in1 + in2; } DEFINE_FUNC(test_fmpzxx_ref_2, (fmpzxx_ref out, fmpzxx_srcref in1, fmpzxx_srcref in2)) { fmpz_add(out._fmpz(), in1._fmpz(), in2._fmpz()); } DEFINE_FUNC(test_fmpzxx_ltuple_comp_1, (bool& out, const fmpzxx& in1, const fmpzxx& in2)) { out = (ltupleref(in1, in2) == ltuple(1, 2)); } DEFINE_FUNC(test_fmpzxx_ltuple_comp_2, (bool& out, const fmpzxx& in1, const fmpzxx& in2)) { out = ((fmpz_cmp_si(in1._fmpz(), 1) == 0) && (fmpz_cmp_si(in2._fmpz(), 2) == 0)); } DEFINE_FUNC(test_fmpzxx_vec_1, (fmpzxx_vector& out, const fmpzxx_vector& in1, const fmpzxx_vector& in2)) { out = in1 + in2; } DEFINE_FUNC(test_fmpzxx_vec_2, (fmpz* out, const fmpz* in1, const fmpz* in2)) { fmpz_add(out + 0, in1 + 0, in2 + 0); fmpz_add(out + 1, in1 + 1, in2 + 1); fmpz_add(out + 2, in1 + 2, in2 + 2); fmpz_add(out + 3, in1 + 3, in2 + 3); fmpz_add(out + 4, in1 + 4, in2 + 4); fmpz_add(out + 5, in1 + 5, in2 + 5); fmpz_add(out + 6, in1 + 6, in2 + 6); fmpz_add(out + 7, in1 + 7, in2 + 7); fmpz_add(out + 8, in1 + 8, in2 + 8); fmpz_add(out + 9, in1 + 9, in2 + 9); } DEFINE_FUNC(test_fmpz_matxx_1, (fmpzxx& to, const fmpz_matxx& A)) { to = trace(transpose(A)*A); } DEFINE_FUNC(test_fmpz_matxx_2, (fmpzxx& to, const fmpz_matxx& A)) { fmpz_mat_t tmp1, tmp2; fmpz_mat_init(tmp1, fmpz_mat_nrows(A._mat()), fmpz_mat_ncols(A._mat())); fmpz_mat_init(tmp2, fmpz_mat_ncols(A._mat()), fmpz_mat_ncols(A._mat())); fmpz_mat_transpose(tmp1, A._mat()); fmpz_mat_mul(tmp1, tmp2, A._mat()); fmpz_mat_trace(to._fmpz(), tmp2); fmpz_mat_clear(tmp1); fmpz_mat_clear(tmp2); } DEFINE_FUNC(test_fmpz_matxx_manip_1, (fmpz_matxx& A)) { A.at(0, 0) += 2u; } DEFINE_FUNC(test_fmpz_matxx_manip_2, (fmpz_matxx& A)) { fmpz_add_ui(fmpz_mat_entry(A._mat(), 0, 0), fmpz_mat_entry(A._mat(), 0, 0), 2u); } DEFINE_FUNC(test_fmpz_polyxx_divrem_1, (fmpz_polyxx& A, fmpz_polyxx& B, const fmpz_polyxx& f, const fmpz_polyxx& g)) { ltupleref(A, B) = divrem(f, g); } DEFINE_FUNC(test_fmpz_polyxx_divrem_2, (fmpz_polyxx& A, fmpz_polyxx& B, const fmpz_polyxx& f, const fmpz_polyxx& g)) { fmpz_poly_divrem(A._poly(), B._poly(), f._poly(), g._poly()); } DEFINE_FUNC(test_fmpz_polyxx_divrem_3, (fmpz_polyxx& A, const fmpz_polyxx& f, const fmpz_polyxx& g)) { ltupleref(A, _) = divrem(f, g); } DEFINE_FUNC(test_fmpz_polyxx_divrem_4, (fmpz_polyxx& A, const fmpz_polyxx& f, const fmpz_polyxx& g)) { fmpz_poly_t tmp; fmpz_poly_init(tmp); fmpz_poly_divrem(A._poly(), tmp, f._poly(), g._poly()); fmpz_poly_clear(tmp); } DEFINE_FUNC(test_nmodxx_1, (mp_limb_t& to, mp_limb_t a_, mp_limb_t b_, nmod_t nm)) { nmodxx_ctx_srcref ctx = nmodxx_ctx_srcref::make(nm); nmodxx a = nmodxx::make_nored(a_, ctx); nmodxx b = nmodxx::make_nored(b_, ctx); to = inv((a + b) * (a * b)).to(); } DEFINE_FUNC(test_nmodxx_2, (mp_limb_t& to, mp_limb_t a, mp_limb_t b, nmod_t nm)) { mp_limb_t tmp1, tmp2; tmp1 = nmod_add(a, b, nm); tmp2 = nmod_mul(a, b, nm); tmp1 = nmod_mul(tmp1, tmp2, nm); tmp1 = nmod_inv(tmp1, nm); to = tmp1; } DEFINE_FUNC(test_nmod_polyxx_1, (nmod_polyxx& to, const nmod_polyxx& p1, const nmod_polyxx& p2)) { to = (p1*p1) + (p2*p2); } DEFINE_FUNC(test_nmod_polyxx_2, (nmod_polyxx& to, const nmod_polyxx& p1, const nmod_polyxx& p2)) { nmod_poly_t tmp1, tmp2; nmod_poly_init_preinv(tmp1, p1.modulus(), p1.estimate_ctx()._nmod().ninv); nmod_poly_init_preinv(tmp2, p1.modulus(), p1.estimate_ctx()._nmod().ninv); nmod_poly_mul(tmp1, p1._poly(), p1._poly()); nmod_poly_mul(tmp2, p2._poly(), p2._poly()); nmod_poly_add(to._poly(), tmp1, tmp2); nmod_poly_clear(tmp1); nmod_poly_clear(tmp2); } DEFINE_FUNC(test_nmod_polyxx_3, (nmod_polyxx& to, const nmod_polyxx& p1, const nmod_polyxx& p2)) { to = ((p1*p1) + (p2*p2)) + ((p1*p2) + (p2*p1)); } DEFINE_FUNC(test_nmod_polyxx_4, (nmod_polyxx& to, const nmod_polyxx& p1, const nmod_polyxx& p2)) { nmod_poly_t tmp1, tmp2, tmp3; nmod_poly_init_preinv(tmp1, p1.modulus(), p1.estimate_ctx()._nmod().ninv); nmod_poly_init_preinv(tmp2, p1.modulus(), p1.estimate_ctx()._nmod().ninv); nmod_poly_init_preinv(tmp3, p1.modulus(), p1.estimate_ctx()._nmod().ninv); nmod_poly_mul(tmp1, p1._poly(), p1._poly()); nmod_poly_mul(tmp2, p2._poly(), p2._poly()); nmod_poly_add(tmp1, tmp1, tmp2); nmod_poly_mul(tmp2, p1._poly(), p2._poly()); nmod_poly_mul(tmp3, p2._poly(), p1._poly()); nmod_poly_add(tmp2, tmp2, tmp3); nmod_poly_add(to._poly(), tmp1, tmp2); nmod_poly_clear(tmp1); nmod_poly_clear(tmp2); nmod_poly_clear(tmp3); } DEFINE_FUNC(test_nmod_matxx_1, (nmodxx& to, const nmod_matxx& A)) { to = trace(transpose(A)*A); } DEFINE_FUNC(test_nmod_matxx_2, (nmodxx& to, const nmod_matxx& A)) { nmod_mat_t tmp1, tmp2; nmod_mat_init(tmp1, nmod_mat_nrows(A._mat()), nmod_mat_ncols(A._mat()), A.modulus()); nmod_mat_init(tmp2, nmod_mat_ncols(A._mat()), nmod_mat_ncols(A._mat()), A.modulus()); nmod_mat_transpose(tmp1, A._mat()); nmod_mat_mul(tmp1, tmp2, A._mat()); nmod_mat_clear(tmp1); to.set_nored(nmod_mat_trace(tmp2)); nmod_mat_clear(tmp2); } } // extern "C" // Global variable, initialized by main. const char* program = 0; void test_tuple() { std::string ass1 = disass(program, "test_tuple_merge_1"); std::string ass2 = disass(program, "test_tuple_merge_2"); // XXX is this deterministic? tassert(stripaddr(ass1) == stripaddr(ass2)); ass1 = disass(program, "test_tuple_concat_1"); ass2 = disass(program, "test_tuple_concat_2"); tassert(count(ass1, "\n") == count(ass2, "\n")); tassert(count(ass1, "mov") == count(ass2, "mov")); tassert(count(ass1, "call") == count(ass2, "call")); // 0 ass1 = disass(program, "test_tuple_back_1"); ass2 = disass(program, "test_tuple_back_2"); // XXX is this deterministic? tassert(stripaddr(ass1) == stripaddr(ass2)); ass1 = disass(program, "test_tuple_extract_1"); ass2 = disass(program, "test_tuple_extract_2"); tassert(count(ass1, "\n") == count(ass2, "\n")); tassert(count(ass1, "mov") == count(ass2, "mov")); tassert(count(ass1, "call") == count(ass2, "call")); // 0 ass1 = disass(program, "test_tuple_removeres_1"); ass2 = disass(program, "test_tuple_removeres_2"); // XXX is this deterministic? tassert(stripaddr(ass1) == stripaddr(ass2)); } void test_fmpzxx() { std::string ass1 = disass(program, "test_fmpzxx_symadd_1"); std::string ass2 = disass(program, "test_fmpzxx_symadd_2"); tassert(count(ass1, "call") == count(ass2, "call")); tassert(fuzzy_equals(count(stripnop(ass1), "\n"), count(stripnop(ass2), "\n"), 0.1)); ass1 = disass(program, "test_fmpzxx_asymadd_1"); ass2 = disass(program, "test_fmpzxx_asymadd_2"); std::string ass3 = disass(program, "test_fmpzxx_asymadd_3"); tassert(count(ass1, "call") == count(ass2, "call")); tassert(count(ass1, "mov") == count(ass2, "mov")); tassert(count(ass3, "call") == count(ass2, "call")); tassert(count(ass3, "mov") == count(ass2, "mov")); // This is probably not the best idea. // (Actually the same code is generated, up to jump targets, register names // and addresses.) tassert(count(ass1, "\n") == count(ass2, "\n")); tassert(count(ass3, "\n") == count(ass2, "\n")); ass1 = disass(program, "test_fmpzxx_ternary_1"); ass2 = disass(program, "test_fmpzxx_ternary_2"); tassert(count(ass1, "call") == count(ass2, "call")); tassert(count(ass1, "mov") == count(ass2, "mov")); tassert(count(ass1, "\n") == count(ass2, "\n")); // XXX ass1 = disass(program, "test_fmpzxx_ternary_3"); ass2 = disass(program, "test_fmpzxx_ternary_4"); tassert(count(ass1, "call") == count(ass2, "call")); tassert(count(ass1, "je") == count(ass2, "je")); tassert(count(ass1, "jmp") == count(ass2, "jmp")); tassert(fuzzy_equals(count(ass1, "mov") + count(ass1, "lea"), count(ass2, "mov") + count(ass2, "lea"), 0.1)); tassert(fuzzy_equals(count(ass1, "\n"), count(ass2, "\n"), 0.1)); ass1 = disass(program, "test_fmpzxx_ternary_6"); ass2 = disass(program, "test_fmpzxx_ternary_5"); tassert(count(ass1, "\n") == count(ass2, "\n")); // XXX ass1 = disass(program, "test_fmpzxx_ternary_7"); ass2 = disass(program, "test_fmpzxx_ternary_8"); tassert(count(ass1, "call") == count(ass2, "call")); // NB: ass1 is actually shorter?!? tassert(fuzzy_equals(count(ass1, "\n"), count(ass2, "\n"), 0.1)); ass1 = disass(program, "test_fmpzxx_ternary_9"); ass2 = disass(program, "test_fmpzxx_ternary_10"); tassert(count(ass1, "call") == count(ass2, "call")); // NB: ass1 is actually shorter?!? tassert(fuzzy_equals(count(ass1, "\n"), count(ass2, "\n"), 0.1)); ass1 = disass(program, "test_fmpzxx_ref_1"); ass2 = disass(program, "test_fmpzxx_ref_2"); tassert(count(ass1, "\n") == count(ass2, "\n")); ass1 = disass(program, "test_fmpzxx_ltuple_comp_1"); ass2 = disass(program, "test_fmpzxx_ltuple_comp_2"); tassert(count(ass1, "\n") == count(ass2, "\n")); } void test_vector() { std::string ass1 = disass(program, "test_fmpzxx_vec_1"); std::string ass2 = disass(program, "test_fmpzxx_vec_2"); tassert(stripaddr(ass1) == stripaddr(ass2)); } void test_mat() { std::string ass1 = disass(program, "test_fmpz_matxx_1"); std::string ass2 = disass(program, "test_fmpz_matxx_2"); tassert(count(ass1, "call") == count(ass2, "call")); tassert(fuzzy_equals(count(stripnop(ass1), "\n"), count(stripnop(ass2), "\n"), 0.1)); ass1 = disass(program, "test_fmpz_matxx_manip_1"); ass2 = disass(program, "test_fmpz_matxx_manip_2"); tassert(count(ass1, "call") == count(ass2, "call")); // 1 tassert(count(ass1, "\n") == count(ass2, "\n")); } void test_poly() { std::string ass1 = disass(program, "test_fmpz_polyxx_divrem_1"); std::string ass2 = disass(program, "test_fmpz_polyxx_divrem_2"); tassert(stripaddr(ass1) == stripaddr(ass2)); ass1 = disass(program, "test_fmpz_polyxx_divrem_1"); ass2 = disass(program, "test_fmpz_polyxx_divrem_2"); tassert(count(ass1, "call") == count(ass2, "call")); tassert(fuzzy_equals(count(ass1, "\n"), count(ass2, "\n"), 0.1)); } void test_nmod() { std::string ass1 = disass(program, "test_nmodxx_1"); std::string ass2 = disass(program, "test_nmodxx_2"); tassert(stripaddr(ass1) == stripaddr(ass2)); ass1 = disass(program, "test_nmod_polyxx_1"); ass2 = disass(program, "test_nmod_polyxx_2"); tassert(fuzzy_equals(count(ass1, "\n"), count(ass2, "\n"), 0.2)); tassert(count(ass1, "call") == count(ass2, "call")); ass1 = disass(program, "test_nmod_polyxx_3"); ass2 = disass(program, "test_nmod_polyxx_4"); tassert(fuzzy_equals(count(stripnop(ass1), "\n"), count(stripnop(ass2), "\n"), 0.2)); tassert(count(ass1, "call") == count(ass2, "call")); ass1 = disass(program, "test_nmod_matxx_1"); ass2 = disass(program, "test_nmod_matxx_2"); tassert(fuzzy_equals(count(stripnop(ass1), "\n"), count(stripnop(ass2), "\n"), 0.05)); tassert(count(ass1, "call") == count(ass2, "call")); } int main(int argc, char** argv) { std::cout << "codegen...."; program = argv[0]; try { test_tuple(); test_fmpzxx(); test_vector(); test_mat(); test_poly(); test_nmod(); } catch(skippable_exception e) { std::cout << "SKIP (" << e.what() << ")\n"; return 0; } std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-compiler-errors.cc000066400000000000000000000042461414523752600213110ustar00rootroot00000000000000#ifndef EXTRACTING_SAMPLE /* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // This file does not actually meant compile. It is used to check compiler error // outputs. NB: File extension .cc to stop the build system from trying to compile // this. #include "fmpzxx.h" #ifdef TEST_PADICXX_FORGET_EVAL #include "padicxx.h" #endif struct newtype { }; using namespace flint; int main() { #endif // EXTRACTING_SAMPLE #ifdef TEST_FMPZXX_INIT_WRONG { newtype n; fmpzxx a(n); } #endif #ifdef TEST_FMPZXX_INIT_2 { fmpzxx a(3, 4); } #endif #ifdef TEST_FMPZXX_ASSIGN_WRONG { fmpzxx a; newtype n; a = n; } #endif #ifdef TEST_FMPZXX_CONVERT_WRONG { fmpzxx a; a.to(); } #endif #ifdef TEST_FMPZXX_REF_INIT_WRONG_1 { const fmpzxx a; fmpzxx_ref ar(a); } #endif #ifdef TEST_FMPZXX_REF_INIT_WRONG_2 { const fmpzxx a; fmpzxx_srcref asr(a); fmpzxx_ref ar(asr); } #endif #ifdef TEST_FMPZXX_SRCREF_ASSIGN { fmpzxx a; fmpzxx_srcref b(a); b = a; } #endif #ifdef TEST_FMPZXX_ARITH_WRONG { fmpzxx a; newtype n; a + n; } #endif #ifdef TEST_FMPZXX_ARITH_WRONG_DEEP { fmpzxx a; newtype n; a + (a*a + (a / n) + a)*a; } #endif #ifdef TEST_FMPZXX_ARITHFUNC_WRONG_NARGS { fmpzxx a; gcd(a); } #endif #ifdef TEST_FMPZXX_ARITHFUNC_WRONG_TYPE { newtype n; dlog(n); } #endif #ifdef TEST_FMPZXX_ARITHFUNC_WRONG_TYPE2 { fmpzxx a; fac(a); } #endif #ifdef TEST_PADICXX_FORGET_EVAL { padicxx_ctx ctx(fmpzxx(5), 1, 2, PADIC_TERSE); padicxx a(ctx); (a + a).unit(); } #endif #ifndef EXTRACTING_SAMPLE // TODO: assignment through tuple with wrong type } #endif flint2-2.8.4/flintxx/test/t-dummy.c000066400000000000000000000001071414523752600171450ustar00rootroot00000000000000/* Empty file to keep MinGW happy */ int main(void) { return 0; } flint2-2.8.4/flintxx/test/t-expression.cpp000066400000000000000000000207241414523752600205600ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flintxx/expression.h" #include "flintxx/tuple.h" #include "flintxx/test/helpers.h" #include "flintxx/test/myint.h" using namespace flint; using namespace mp; using namespace traits; void test_initialization() { myint a; tassert(a._data().payload == -1 && a._data().extra == 42); a._data().payload = 17; myint b = a; tassert(b._data().payload == 17); myint c(8); tassert(c._data().payload == 8 && c._data().extra == 2); myint d('a'); tassert(d._data().payload == 'a' && d._data().extra == 3); myint e(c + c); tassert(e._data().payload == 16); } void test_destruction() { bool destroyed = false; { myint a; a._data().destroyed = &destroyed; } tassert(destroyed); } void test_printing() { std::ostringstream o; myint a(4); o << a; tassert(o.str() == "4"); } void test_assignment() { myint a; myint b(43); a = b; tassert(a._data().payload == 43); tassert(a._data().extra == 4); a = WORD(44); tassert(a._data().payload == 44 && a._data().extra == 5); mylong c(0); c = a + b; tassert(c == WORD(87)); } void test_swap() { myint a(2), b(3); swap(a, b); tassert(a == 3 && b == 2 && a._data().extra == 1234); } void test_traits() { typedef myint immediate_expression; typedef int immediate_nonexpression; typedef my_expression< operations::plus, make_tuple::type > lazy_expression; tassert(is_expression::val == true); tassert(is_expression::val == false); tassert(is_expression::val == true); tassert(is_immediate_expr::val == true); tassert(is_immediate_expr::val == false); tassert(is_immediate_expr::val == false); tassert(is_immediate::val == true); tassert(is_immediate::val == true); tassert(is_immediate::val == false); tassert(is_lazy_expr::val == false); tassert(is_lazy_expr::val == false); tassert(is_lazy_expr::val == true); tassert(is_lazy_expr::val == false); } void test_equals() { myint a(3); myint b(4); myint c(3); tassert(a != b); tassert(a == c); tassert(a == 3); tassert(3 == a); tassert(a != 4); tassert(4 != a); tassert((a + b) == (a + 4)); } void test_arithmetic() { myint a(3); myint b(4); myint c(7); myint d(1); myint e(2); tassert((a + b).evaluate() == 7); tassert(a + b == c); tassert(a + b == 7); tassert(a - b == -1); tassert(a * b == 12); tassert(c / e == 3); tassert(c % e == 1); tassert(-a == -3); // Test arithmetic with immediates tassert(a + 4 == 7); tassert(4 + a == 7); tassert(a + WORD(4) == 7); tassert(4u + a == 7); // Test composite arithmetic tassert((a + 1) + (b + 2) == 10); tassert((a + d) + (b + 2) == 10); tassert((a + d) + (b + e) == 10); tassert((3 + d) + (b + e) == 10); tassert((3 + d) + (4 + e) == 10); tassert(a + (b + c) == 14); tassert(3 + (b + c) == 14); tassert(3 + (4 + c) == 14); tassert(3 + (b + 7) == 14); tassert(a + (b + 7) == 14); tassert((b + c) + a == 14); tassert((b + c) + 3 == 14); tassert((4 + c) + 3== 14); tassert((b + 7) + 3== 14); tassert((b + 7) + a== 14); // test combining unary and binary arithmetic tassert(-(-a) == 3); tassert(-(a - b) == b - a); tassert(-((-a) + (-b)) == a + b); // Test mixed arithmetic mylong al(WORD(3)); mylong bl(WORD(4)); mylong cl(WORD(7)); tassert(al + bl == cl); tassert(al + bl == WORD(7)); tassert(al + b == WORD(7)); tassert(a + bl == WORD(7)); tassert((a + bl) + cl == WORD(14)); tassert((a + b) + cl == WORD(14)); tassert((al + b) + c == WORD(14)); tassert(cl + (a + bl) == WORD(14)); tassert(cl + (a + b) == WORD(14)); tassert(c + (al + b) == WORD(14)); tassert((a + bl) + (cl + d) == WORD(15)); tassert((a + bl) + (c + d) == WORD(15)); tassert((a << 2) == 12); tassert(((a << 2) >> 2) == a); } void test_conversion() { myint a(4); mylong b(WORD(4)); tassert(typed_equals(a.to(), 4)); tassert(typed_equals(a.to(), b)); tassert(typed_equals((a + a).to(), 8)); } void test_assignment_arith() { myint a(1); myint b(2); a += b; tassert(a == 3 && b == 2); a += a*b; tassert(a == 9); a += 1; tassert(a == 10); } template bool is_subexpr(const Expr& e) { return tools::has_subexpr, Expr>::val; } void test_tools() { typedef tools::equal_types_pred intpred; myint a(1); mylong b(WORD(2)); tassert(tools::find_subexpr(a) == 1); tassert(tools::find_subexpr(a + b) == 1); tassert(tools::find_subexpr_T(a + b) == WORD(2)); tassert(tools::find_subexpr(b + (a + 2) + b) == 1); tassert(is_subexpr(a+b)); tassert(!is_subexpr(a+a)); } void test_temporaries() { myint a(1); #define T2 ((a + a) + (a + a)) #define T3 (T2 + T2) tassert(count_temporaries(T2) == 2); tassert(count_temporaries(T3) == 3); tassert(count_temporaries(T3 + T2) == 3); tassert(count_temporaries(T2 + T3) == 3); } void test_references() { mylong a(4); mylong_ref ar(a); mylong_cref acr(a); tassert(a == ar); tassert(a == acr); tassert(ar == acr); tassert(ar == WORD(4) && acr == WORD(4)); ar = WORD(5); tassert(a == WORD(5) && acr == WORD(5) && ar == WORD(5)); mylong b(6); ar = b; tassert(a == b); mylong_cref bcr(b); b = WORD(7); ar = bcr; tassert(a == b); a = WORD(4); b = WORD(5); tassert(a + bcr == WORD(9)); tassert(ar + bcr == WORD(9)); a = acr + b; tassert(a == WORD(9)); ar = acr + bcr; tassert(a == WORD(14)); a = WORD(4); tassert((a + a) + bcr == WORD(13)); tassert((acr + acr) + b == WORD(13)); tassert(((a + bcr) + acr + (ar + bcr)) + ((a + a) + (bcr + bcr)) == WORD(40)); a = ((a + bcr) + acr + (ar + bcr)) + ((a + a) + (bcr + bcr)); tassert(a == WORD(40)); a = WORD(4); ar = ((a + bcr) + acr + (ar + bcr)) + ((a + a) + (bcr + bcr)); tassert(a == WORD(40)); } struct S { }; S operator+(const S& s, const S&) {return s;} S operator-(const S&s) {return s;} template S operator*(const S& s, const T&) {return s;} void test_unrelated_overload() { // Test a bug in our operator overloading logic which used to not allow // this to compile. S s; s = s + s; s = -s; s = s * (myint(5) + myint(5)); } void test_multiary() { tassert(fourary_test(1, 2, 3, 4) == myint(1 + 2 + 3 + 4)); tassert(fiveary_test(1, 2, 3, 4, 5u) == 1 + 2 + 3 + 4 + 5); tassert(sixary_test(1, 2, 3, 4, 5, 6) == 1 + 2 + 3 + 4 + 5 + 6); tassert(sevenary_test(1, 2, 3, 4, 5, 6, 7) == 1 + 2 + 3 + 4 + 5 + 6 + 7); } void test_cstyle_io() { #if !defined (__WIN32) && !defined (__CYGWIN__) mylong c(17), d(0); FILE * f = std::fopen("expression_test", "w+"); tassert(f); print(f, c); std::fprintf(f, "\n"); print_pretty(f, c); std::fflush(f); std::fclose(f); f = std::fopen("expression_test", "r"); tassert(read(f, d) > 0); tassert(d == c); d = WORD(0); tassert(std::fscanf(f, "\n") == 0); fclose(f); tassert(std::remove("expression_test") == 0); #endif } int main() { std::cout << "expression...."; test_traits(); test_initialization(); test_destruction(); test_printing(); test_assignment(); test_swap(); test_equals(); test_arithmetic(); test_conversion(); test_assignment_arith(); test_tools(); test_temporaries(); test_references(); test_multiary(); test_cstyle_io(); test_unrelated_overload(); std::cout << "PASS" << std::endl; // TODO test that certain things *don't* compile? return 0; } flint2-2.8.4/flintxx/test/t-flint_classes.cpp000066400000000000000000000033531414523752600212110ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flintxx/test/helpers.h" #include "fmpzxx.h" using namespace flint; void test_traits() { using namespace flint_classes; tassert((mp::equal_types::type, fmpzxx>::val)); tassert((mp::equal_types::type, fmpzxx>::val)); tassert((mp::equal_types::type, fmpzxx>::val)); tassert((mp::equal_types::type, fmpzxx_ref>::val)); tassert((mp::equal_types::type, fmpzxx_srcref>::val)); tassert((mp::equal_types::type, fmpzxx_ref>::val)); tassert((is_ref::val)); tassert((is_ref::val)); tassert((!is_ref::val)); tassert((!is_ref::val)); tassert((is_srcref::val)); tassert((!is_srcref::val)); tassert((!is_srcref::val)); tassert(is_nonref::val); tassert(!is_nonref::val); tassert(!is_nonref::val); } fmpzxx_ref make_ref(fmpzxx& a) {return fmpzxx_ref(a);} void test_ref_lvalues() { fmpzxx a(1); fmpzxx_ref b(a); b *= 2; make_ref(a) *= 2; tassert(a == 4); } int main() { std::cout << "flint_classes...."; test_traits(); test_ref_lvalues(); std::cout << "PASS" << std::endl; } flint2-2.8.4/flintxx/test/t-fmpq_matxx.cpp000066400000000000000000000223631414523752600205460ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpq_matxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_init() { fmpq_matxx A(3, 4); tassert(A.rows() == 3 && A.cols() == 4); tassert(A.at(0, 0).is_zero()); A.at(0, 0) = 1; fmpq_matxx B(A); tassert(B.rows() == 3 && B.cols() == 4); tassert(B.at(0, 0).is_one()); B.at(0, 0) = 0; tassert(A.at(0, 0).is_one()); tassert(fmpq_matxx::zero(3, 4).is_zero()); fmpq_matxx eye = fmpq_matxx::one(4, 4); for(slong i = 0;i < eye.rows();++i) for(slong j = 0;j < eye.cols();++j) tassert(eye.at(i, j) == fmpqxx::integer(int(i == j))); } void test_assignment() { frandxx state; fmpz_matxx A = fmpz_matxx::randtest(3, 4, state, 10); fmpq_matxx Aq(A.rows(), A.cols()); Aq = A; tassert(Aq == fmpq_matxx::integer_matrix(A)); } void test_conversion() { frandxx state; fmpz_matxx A = fmpz_matxx::randtest(3, 4, state, 10); fmpq_matxx Aq = fmpq_matxx::integer_matrix(A); tassert(Aq.rows() == A.rows() && Aq.cols() == A.cols()); for(slong i = 0;i < A.rows();++i) for(slong j = 0;j < A.cols();++j) tassert(Aq.at(i, j) == fmpqxx::integer(A.at(i, j))); tassert(A == fmpz_matxx::from_integral_fraction(Aq)); Aq.at(0, 0) = fmpqxx::frac(1, 2); assert_exception(fmpz_matxx::from_integral_fraction(Aq)); tassert(Aq.numden_entrywise().get<0>().rows() == A.rows() && Aq.numden_entrywise().get<0>().cols() == A.cols() && Aq.numden_entrywise().get<1>().rows() == A.rows() && Aq.numden_entrywise().get<1>().cols() == A.cols()); tassert(Aq.numden_matwise().get<0>().rows() == A.rows() && Aq.numden_matwise().get<0>().cols() == A.cols()); tassert(Aq.numden_rowwise().get<0>().rows() == A.rows() && Aq.numden_rowwise().get<0>().cols() == A.cols() && Aq.numden_rowwise().get<1>().size() == A.rows()); tassert(Aq.numden_colwise().get<0>().rows() == A.rows() && Aq.numden_colwise().get<0>().cols() == A.cols() && Aq.numden_colwise().get<1>().size() == A.cols()); fmpz_matxx den(A.rows(), A.cols()); for(slong i = 0;i < A.rows();++i) for(slong j = 0;j < A.cols();++j) den.at(i, j) = 1u; den.at(0, 0) = 2u; A.at(0, 0) = 1; tassert(Aq.numden_entrywise() == ltupleref(A, den)); tassert(Aq.num_rowwise().at(0, 0) == 1); tassert(Aq.num_colwise().at(0, 0) == 1); tassert(Aq.numden_matwise().get<1>() == 2); fmpz_vecxx rowdens(A.rows()); rowdens[0] = 2; for(slong i = 1;i < A.rows();++i) rowdens[i] = 1; for(slong i = 1;i < A.cols();++i) A.at(0, i) *= 2; tassert(Aq.numden_rowwise() == ltupleref(A, rowdens)); tassert(Aq.numden_colwise().get<1>()[0] == 2); } template bool has_explicit_temporaries(const Expr&) { return Expr::ev_traits_t::rule_t::temporaries_t::len != 0; } void test_arithmetic() { fmpq_matxx A(10, 10); fmpq_matxx v(10, 1); for(int i = 0;i < 10;++i) v.at(i, 0) = i; fmpzxx two(2); tassert(transpose(v).rows() == 1); tassert(v.transpose().cols() == 10); tassert((two*v).rows() == 10); tassert((v*two).rows() == 10); tassert((v*transpose(v)).rows() == 10 && (v*transpose(v)).cols() == 10); tassert(!has_explicit_temporaries(trace(transpose(v)))); tassert(!has_explicit_temporaries(trace(A + v*transpose(v)))); tassert(!has_explicit_temporaries(A + v*transpose(v))); tassert(!has_explicit_temporaries(trace((v*transpose(v) + A)))); tassert(!has_explicit_temporaries(trace(v*transpose(v) + v*transpose(v)))); tassert(!has_explicit_temporaries(v*transpose(v) + v*transpose(v))); tassert(trace(transpose(v)).is_zero()); tassert(trace(A + v*transpose(v)) == fmpqxx(285, 1u)); tassert(trace(v*transpose(v) + A) == fmpqxx(285, 1u)); tassert(trace(v*transpose(v) + v*transpose(v)) == fmpqxx(2*285, 1u)); tassert(trace((A+A)*(two + two)).is_zero()); for(int i = 0;i < 10; ++i) for(int j = 0; j < 10; ++j) A.at(i, j) = i*j; tassert(A == v*transpose(v)); tassert(A != transpose(v)*v); A.at(0, 0) = 15; tassert(A != v*transpose(v)); A.at(0, 0) = 0; for(unsigned i = 0;i < 10; ++i) for(unsigned j = 0; j < 10; ++j) A.at(i, j) *= two; tassert(A == v*transpose(v) + v*transpose(v)); tassert(A - v*transpose(v) == v*transpose(v)); tassert(((-A) + A).is_zero()); tassert((A + A).at(0, 0) == A.at(0, 0) + A.at(0, 0)); tassert((A + A) == A*two); tassert((two*A) / two == A); frandxx state; A.set_randtest(state, 15); fmpz_matxx B(A.rows(), A.cols()); B.set_randtest(state, 15); fmpq_matxx C(A.rows(), A.cols()); for(slong i = 0;i < A.rows();++i) for(slong j = 0;j < A.cols();++j) C.at(i, j).num() = B.at(i, j); tassert(C*A == B*A && A*C == A*B); tassert(C.mul_direct(A) == C*A && C.mul_cleared(A) == C*A); } void test_functions() { fmpq_matxx A(2, 3), B(2, 2), empty(0, 15); B.at(0, 0) = 1; tassert(A.is_zero() && !A.is_empty() && !A.is_square()); tassert(!B.is_zero() == B.is_square()); tassert(empty.is_zero() && empty.is_empty()); // transpose tested in arithmetic // mul tested in arithmetic // trace tested in arithmetic tassert(hilbert_matrix(4, 6).rows() == 4); tassert(hilbert_matrix(4, 6).cols() == 6); A.set_hilbert_matrix(); fmpq_matxx H(hilbert_matrix(2, 3)); tassert(A == H); for(slong i = 0;i < A.rows();++i) for(slong j = 0;j < A.rows();++j) tassert(A.at(i, j).num() == 1 && A.at(i, j).den() == i + j + 1); tassert(A.is_integral() == false); frandxx rand; fmpz_matxx Bp(B.rows(), B.cols()); Bp.set_randtest(rand, 10); for(slong i = 0;i < B.rows();++i) for(slong j = 0;j < B.rows();++j) B.at(i, j) = fmpqxx(Bp.at(i, j), fmpzxx(1)); tassert(B.det().num() == Bp.det() && B.det().den() == 1); B.at(0, 0) = fmpqxx::randtest_not_zero(rand, 10); B.at(0, 1) = 0; B.at(1, 0) = fmpqxx::randtest(rand, 10); B.at(1, 1) = fmpqxx::randtest_not_zero(rand, 10); tassert(B*B.solve_fraction_free(A) == A); tassert(B*B.solve_dixon(A) == A); fmpq_matxx eye(B.rows(), B.cols()); for(slong i = 0;i < B.rows();++i) eye.at(i, i) = 1; tassert(B*B.inv() == eye); assert_exception(fmpq_matxx(2, 2).solve_fraction_free(A).evaluate()); assert_exception(fmpq_matxx(2, 2).solve_dixon(A).evaluate()); // make sure this compiles if(0) print(B); } void test_extras() { fmpq_matxx A(10, 10), B(10, 10); frandxx rand; A.set_randtest(rand, 15); B.set_randtest(rand, 15); A.at(0, 0) = B.at(0, 0) + fmpqxx(1, 1u); fmpq_matxx_srcref Asr(A); fmpq_matxx_ref Br(B); tassert((A + A) + (B + B) == (Asr + Asr) + (Br + Br)); Br = Asr; tassert(A == B); fmpq_matxx C(Asr); tassert(C == A); C.at(0, 0) += fmpqxx(2, 1u); tassert(C != A); } void test_randomisation() { frandxx rand; fmpq_matxx A(2, 2); A.set_randbits(rand, 5); tassert(height(A.at(0, 0)) <= 31); A.set_randtest(rand, 5); tassert(height(A.at(0, 0)) <= 31); frandxx rand2, rand3; A.set_randbits(rand2, 5); tassert(A == fmpq_matxx::randbits(2, 2, rand3, 5)); A.set_randtest(rand2, 5); tassert(A == fmpq_matxx::randtest(2, 2, rand3, 5)); } void test_reduction_reconstruction() { fmpq_matxx A(4, 7); frandxx state; A.set_randtest(state, 4); fmpzxx M(UWORD(123457891)); fmpz_matxx Ar = fmpz_matxx::reduce(A, M); tassert(Ar.rows() == A.rows() && Ar.cols() == A.cols()); for(slong i = 0;i < A.rows();++i) for(slong j = 0;j < A.cols();++j) tassert(Ar.at(i, j) == A.at(i, j) % M); tassert(A == fmpq_matxx::reconstruct(Ar, M)); // TODO test exception } void test_row_reduction() { frandxx state; fmpq_matxx A = fmpq_matxx::randtest(5, 5, state, 15); slong rank1, rank2; permxx p1(5), p2(5); fmpq_matxx res1(A.rows(), A.cols()), res2(A.rows(), A.cols()); fmpq_matxx B(A); tassert(B.pivot(1, 1, &p1) == fmpq_mat_pivot(p1._data(), A._mat(), 1, 1)); tassert(A == B); ltupleref(rank1, res1) = rref(A); rank2 = fmpq_mat_rref(res2._mat(), A._mat()); tassert(rank1 == rank2 && res1 == res2); tassert(rref_classical(A) == rref(A) && rref_fraction_free(A) == rref(A)); } void test_unified_access() { fmpq_matxx A(2, 2); const fmpq_matxx& Ar = A; const fmpq_matxx_ref Ar2(A); Ar2.at(0, 0) = fmpqxx::one(); tassert(Ar.at(0, 0).is_one()); } int main() { std::cout << "fmpq_matxx...."; test_init(); test_assignment(); test_conversion(); test_arithmetic(); test_functions(); test_extras(); test_randomisation(); test_reduction_reconstruction(); test_row_reduction(); test_unified_access(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-fmpq_polyxx.cpp000066400000000000000000000177711414523752600207570ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpq_polyxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_init() { fmpq_polyxx p(10); tassert(p.length() == 0); tassert(fmpq_polyxx::zero().is_zero()); tassert(fmpq_polyxx::one().is_one()); } void test_manipulation() { fmpq_polyxx p, q; p.set_coeff(5, 17); p.den() = 2; tassert(p.degree() == 5); q.set_coeff(5, fmpqxx(17, 2u)); tassert((q + fmpq_polyxx()).get_coeff(5) == fmpqxx(17, 2u)); p.set_coeff(0, fmpzxx(1)); q.get_coeff_numref(0) = 2; tassert(p == q); tassert(q.is_canonical()); tassert(p.length() == 6); p.realloc(0); tassert(p.is_zero() && !p.is_one()); p.set_coeff(0, 1); tassert(p.is_one()); tassert((p*q).den() == 2); } void test_assignment() { fmpq_polyxx p, q; p = 1; tassert(p.is_one()); q = UWORD(0); tassert(q.is_zero()); tassert(p != q); p = q; tassert(p == q); p = "4 0 0 0 1"; q.set_coeff(3, 1); tassert(p == q); tassert(p == fmpq_polyxx("4 0 0 0 1")); // TODO XXX this does not always fail? //assert_exception(p = "4 1 2"); assert_exception(p = "2 1 2"); assert_exception(fmpq_polyxx("2 1 2")); fmpz_polyxx pz; pz = 1; p = pz; tassert(p.is_one()); p = fmpzxx(0); tassert(p.is_zero()); p = fmpqxx(1, UWORD(1)); tassert(p.is_one()); } void test_conversion() { fmpq_polyxx p; p.set_coeff(3, fmpqxx(1, 2u)); tassert(p.to_string() == "4 0 0 0 1/2"); tassert(p.pretty("x") == "1/2*x^3"); } void test_arithmetic() { fmpq_polyxx p, q; p = 1; q = 2; tassert(p < q); p.set_coeff(1, 1); tassert(q < p); p = -2; tassert(p == -q); q = fmpqxx(-1, 2u); tassert(inv(p) == q); p = 1; q = "4 0 0 0 1"; tassert((p + q).to_string() == "4 1 0 0 1"); tassert((p - q).to_string() == "4 1 0 0 -1"); tassert((-p).to_string() == "1 -1"); fmpzxx two(2); fmpqxx twoq(2, 1u); tassert(two * q == 2 * q && 2u * q == q * 2 && twoq * q == 2 * q && (two * q).to_string() == "4 0 0 0 2"); q *= 2; tassert(q / two == q / 2u && q / 2 == q / two && q / twoq == q / 2u && (q / two).to_string() == "4 0 0 0 1"); // q == "4 0 0 0 2" q.set_coeff(1, 17); // q == "4 0 17 0 2" p = "3 1 0 1"; tassert((p*q).to_string() == "6 0 17 0 19 0 2"); tassert((p*q) / p == q); tassert(p + q % q == p); fmpqxx five(5, 1u), one(1, 1u); tassert(p(one + one) == five); tassert(p(fmpzxx(2)) == five); q = "3 0 0 1"; tassert(p(q).to_string() == "5 1 0 0 0 1"); tassert(p(q) == compose(p, q)); tassert(p(one) == evaluate(p, one)); tassert(p(fmpzxx(1)) == evaluate(p, fmpzxx(1))); } // Won't compile if the expression is not done using addmul template bool is_ternary(const T&) { return T::ev_traits_t::temp_rule_t::TERNARY_OP_MARKER + 1; } // test stuff which we should get automatically - addmul, references etc void test_extras() { // TODO addmul when implemented // forwarded member functions fmpq_polyxx f, g; f = "4 1 2 3 4"; g = "5 0 4 3 2 1"; tassert(g.exp_series(10) == exp_series(g, 10)); tassert(f.make_monic() == make_monic(f)); tassert(f.derivative() == derivative(f)); tassert(f.content() == content(f)); tassert(f.divrem(g) == divrem(f, g)); tassert(f.compose_series(g, 5) == compose_series(f, g, 5)); } void test_functions() { fmpq_polyxx f, g, res, x; x = "2 0 1"; f.set_coeff(5, 1); f.set_coeff(0, 1); tassert(fmpq_polyxx::get_slice(f, 0, 5).is_one()); f.truncate(3); tassert(f.is_one()); f = "4 1 2 3 4"; g = "5 5 4 3 2 1"; res = f*g; res.truncate(4); tassert(res == mullow(f, g, 4)); tassert(reverse(g, 5).to_string() == "5 1 2 3 4 5"); tassert(pow(f, 5u) == f*f*f*f*f); tassert(shift_left(f, 5) == f*pow(x, 5u)); tassert(f == shift_right(shift_left(f, 5), 5)); fmpq_polyxx Q, R; ltupleref(Q, R) = divrem(g, f); tassert(Q*f + R == g); f = "2 1 -1"; tassert(inv_series(f, 10).to_string() == "10 1 1 1 1 1 1 1 1 1 1"); tassert(inv_series_newton(f, 20) == inv_series(f, 20)); tassert(div_series(g, f, 10) * f % pow(x, 10u) == g); f = "4 2 0 0 1"; g = "5 1 2 3 4 5"; tassert(resultant(f, g) == fmpqxx(1797, 1u)); tassert(gcd(f, g).is_one()); tassert(lcm(f, g) == f*g / 5); fmpq_polyxx r, s, extra; ltupleref(extra, r, s) = xgcd(f, g); tassert(extra.is_one() && (r*f + s*g).is_one()); res = "6 0 1 1 1 1 1"; tassert(derivative(res) == g); tassert(integral(g) == res); tassert(pow(sqrt_series(g, 10), 2u) % pow(x, 7u) == g); tassert((pow(invsqrt_series(g, 10), 2u)*g % pow(x, 7u)).is_one()); tassert(rescale(f, fmpqxx(2, 1u)).to_string() == "4 2 0 0 8"); fmpq_polyxx inner;inner = "3 0 -1 5"; res = g(inner); res.truncate(10); tassert(compose_series(g, inner, 10) == res); tassert(compose_series_horner(g, inner, 10) == res); tassert(compose_series_brent_kung(g, inner, 10) == res); res = "2 0 1"; tassert(compose_series(inner, revert_series(inner, 10), 10) == res); tassert(compose_series(inner, revert_series_lagrange(inner, 10), 10) == res); tassert(compose_series(inner, revert_series_lagrange_fast(inner, 10), 10) == res); tassert(compose_series(inner, revert_series_newton(inner, 10), 10) == res); tassert(content(2*g) == fmpqxx(2, 1u)); tassert(primitive_part(2*g) == g); tassert(f.is_monic() && !g.is_monic()); tassert(make_monic(2*f) == f); tassert((4*g).is_squarefree());tassert(!(g*g).is_squarefree()); // test static functions frandxx state; tassert(fmpq_polyxx::randtest(state, 4, 10).length() <= 4); tassert(fmpq_polyxx::randtest_unsigned(state, 4, 10).get_coeff_numref(0) >= 0); tassert(fmpq_polyxx::randtest_not_zero(state, 4, 10).is_zero() == false); fmpz_vecxx xs(3), ys(3); xs[0] = 0; xs[1] = 1; xs[2] = -1; ys[0] = 0; ys[1] = 1; ys[2] = 1; tassert(fmpq_polyxx::interpolate(xs, ys).to_string() == "3 0 0 1"); } void test_transcendental_series() { fmpq_polyxx x, xp1; x = "2 0 1"; xp1 = "2 1 1"; tassert(log_series(xp1, 5).to_string() == "5 0 1 -1/2 1/3 -1/4"); tassert(atan_series(x, 5).to_string() == "4 0 1 0 -1/3"); tassert(atanh_series(x, 5).to_string() == "4 0 1 0 1/3"); tassert(asin_series(x, 5).to_string() == "4 0 1 0 1/6"); tassert(asinh_series(x, 5).to_string() == "4 0 1 0 -1/6"); tassert(log_series(exp_series(x, 10), 10) % pow(x, 10u) == x); tassert(sin_series(asin_series(x, 10), 10) % pow(x, 10u) == x); tassert(tan_series(atan_series(x, 10), 10) % pow(x, 10u) == x); tassert(sinh_series(asinh_series(x, 10), 10) % pow(x, 10u) == x); tassert(((pow(cos_series(x, 10), 2u) + pow(sin_series(x, 10), 2u)) % pow(x, 10u)).is_one()); tassert(((pow(cosh_series(x, 10), 2u) - pow(sinh_series(x, 10), 2u)) % pow(x, 10u)).is_one()); } void test_printing() { frandxx state; fmpq_polyxx f = fmpq_polyxx::randtest(state, 4, 10); test_print_read(f); f = "2 3 1"; tassert_fprint_pretty(f, "x", "x+3"); } void test_unified_access() { fmpq_polyxx f; const fmpq_polyxx& g = f; tassert(g.den().is_one()); } int main() { std::cout << "fmpq_polyxx...."; test_init(); test_manipulation(); test_assignment(); test_conversion(); test_arithmetic(); test_functions(); test_transcendental_series(); test_extras(); test_printing(); test_unified_access(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-fmpqxx.cpp000066400000000000000000000165331414523752600177070ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpqxx.h" #include "fmpz_vecxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_init() { fmpqxx a, b = fmpqxx::frac(6, fmpzxx(10)), c = fmpqxx::frac((unsigned short)6, 10u); tassert(a.num() == 0 && a.den() == 1); tassert(b.num() == 3 && b.den() == 5); tassert(c.num() == 3 && c.den() == 5); a.num() = -2; a.den() = 4; tassert(!a.is_canonical()); a.canonicalise(); tassert(a.num() == -1 && a.den() == 2); tassert(fmpqxx::frac("4", 2) == fmpqxx::integer(-fmpzxx(-2))); tassert(fmpqxx::zero().is_zero() && fmpqxx::one().is_one()); } void test_assignment() { fmpqxx a; fmpqxx b = fmpqxx::frac("100000000000000000000", "100000000000000000001"); fmpqxx c(b); a = b; tassert(a == b && c == b); tassert(a.num()._fmpz()[0] != b.num()._fmpz()[0]); tassert(a.den()._fmpz()[0] != b.den()._fmpz()[0]); tassert(c.num()._fmpz()[0] != b.num()._fmpz()[0]); tassert(c.den()._fmpz()[0] != b.den()._fmpz()[0]); a = 7; tassert(a.num() == 7 && a.den() == 1); a = (unsigned short)8; tassert(a.num() == 8 && a.den() == 1); } void test_conversion() { fmpqxx a = fmpqxx::frac(3, 5); tassert(a.to_string() == "3/5"); tassert(a.to_string(5) == "3/10"); tassert(0.59 < a.to() && a.to() < 0.61); std::ostringstream oss; oss << a; tassert(oss.str() == "3/5"); tassert((a + a).num() == 6); tassert((a * a).den() == 25); } void test_order() { fmpqxx a(0, 1u), b(1, 1u); fmpzxx c(2), d(-2); tassert(a < b); tassert(a <= a); tassert(b > a); tassert(b >= b); tassert(a == a); tassert(a != b); tassert(c > a); tassert(c >= a + b); tassert(c != a); tassert(c > a); tassert(a <= c); tassert(a + b >= d); tassert(a - b != d); tassert(a - b > d); tassert(d <= b); tassert(b < 2u); tassert(a + b < c); tassert(a + b < 2u); tassert(a + b < c.to()); tassert(a + b < 2); tassert(a + b < c.to()); tassert(1u <= a + b); tassert(1 <= b); tassert(b == 1u); tassert(a + b == 1); tassert(2 != b); tassert(2u != b); } void test_arithmetic() { fmpqxx a(3, 5u), b(2, 7u); fmpzxx c(2); tassert(a + b == fmpqxx::frac(3*7 + 2*5, 35u)); tassert(a + c == fmpqxx::frac(13, 5u)); tassert(a + c.to() == a + c); tassert(a + c.to() == a + c); tassert(a + 2u == a + c); tassert(a + 2 == a + c); tassert(c + a == a + c); tassert(c.to() + a == a + c); tassert(c.to() + a == a + c); tassert(2u + a == a + c); tassert(2 + a == a + c); tassert(a * b == fmpqxx::frac(6, 35u)); tassert(a * c == a + a); tassert(a * c.to() == a + a); tassert(a * c.to() == a + a); tassert(c * a == a + a); tassert(c.to() * a == a + a); tassert(c.to() * a == a + a); tassert(a * 2u == a + a); tassert(a * 2 == a + a); tassert(2u * a == a + a); tassert(2 * a == a + a); tassert(a - b == fmpqxx::frac(3*7 - 5*2, 35u)); tassert(a - c == fmpqxx::frac(-7, 5u)); tassert(a - c.to() == a - c); tassert(a - c.to() == a - c); tassert(a - 2u == a - c); tassert(a - 2 == a - c); tassert(a / b == fmpqxx::frac(3*7, 10u)); tassert((a+a) * (c+c) == fmpqxx::frac(24, 5u)); tassert(c * a == fmpqxx::frac(6, 5u)); tassert(a / c == fmpqxx::frac(3, 10u)); tassert(-a == fmpqxx::frac(-3, 5u)); tassert(((a << 5) >> 4) == fmpzxx(2)*a); } // Won't compile if the expression is not done using addmul template bool is_ternary(const T&) { return T::ev_traits_t::temp_rule_t::TERNARY_OP_MARKER + 1; } // test stuff which we should get automatically - addmul, references etc void test_extras() { fmpqxx a(3, 5u), b(2, 7u), c(3, 1u); tassert(is_ternary((a+a) - b*c)); tassert(is_ternary(b*c + (a+a))); tassert((a+a) - b*c == fmpqxx::frac(6*7 - 5*6, 5u*7u)); tassert(b*c + (a+a) == fmpqxx::frac(6*7 + 5*6, 5u*7u)); fmpqxx_ref ar(a); fmpqxx_srcref asr(a); tassert(a == ar && ar == asr); ar = 3; tassert(a == c && asr == c); tassert((-a) + a == fmpqxx::frac(0, 0u)); tassert(a.pow(3) == pow(a, 3)); tassert(a.height() == height(a)); } void test_functions() { fmpqxx a(-3, 5u); // test lazy functions tassert(abs(a) == -a); tassert(height(a) == 5); tassert(a % fmpzxx(7) == 5); assert_exception((a % fmpzxx(5)).evaluate()); // test immediate functions tassert(height_bits(a) == 3); tassert((inv(a)*a).is_one()); tassert(sgn(a) == -1 && sgn(-a) == 1 && sgn(fmpqxx::frac(0, 0u)) == 0); // test member functions const fmpqxx zero(0, 0u), one(1, 1u); tassert(zero.is_zero() && !zero.is_one()); tassert(!one.is_zero() && one.is_one()); tassert(pow(a, -3) == inv(a*a*a)); tassert(zero.next_minimal().next_minimal().next_minimal() == fmpqxx::frac(2, 1u)); tassert(zero.next_signed_minimal().next_signed_minimal() == fmpqxx::frac(-1, 1u)); tassert(zero.next_calkin_wilf().next_calkin_wilf() == fmpqxx::frac(1, 2u)); tassert(zero.next_signed_calkin_wilf().next_signed_calkin_wilf() == fmpqxx::frac(-1, 1u)); // test static member functions frandxx rand; tassert(abs(fmpqxx::randbits(rand, 5).den()) <= 31); // NB: rand stuff comes from a single macro, no need for further testing tassert(a == fmpqxx::reconstruct( a % fmpzxx(41), fmpzxx(41), fmpzxx(3), fmpzxx(5))); assert_exception(fmpqxx::reconstruct( a % fmpzxx(7), fmpzxx(7), fmpzxx(1), fmpzxx(1)).evaluate()); tassert(a == fmpqxx::reconstruct(a % fmpzxx(71), fmpzxx(71))); assert_exception(fmpqxx::reconstruct(a % fmpzxx(7), fmpzxx(7)).evaluate()); // test partial fractions fmpz_vecxx v(5); fmpqxx tmp(7, 5u); fmpqxx rem; tassert(tmp == fmpqxx::from_cfrac(v, get_cfrac(v, rem, tmp))); tassert(rem.is_zero()); tassert(3 <= tmp.cfrac_bound()); // test swap a = 1; fmpqxx b(zero); swap(a, b); tassert(a.is_zero() && b.is_one()); tassert_fprint(fmpqxx::frac(7, 29), "7/29"); } void test_vector() { fmpq_vecxx v1(10), v2(10), v3(1); tassert(v1 == v2); tassert(v1 != v3); v1[0] = fmpqxx::frac(1, 1u); tassert(v1 != v2); v2[0] = v1[0]; tassert(v1 == v2); } void test_unified_access() { fmpqxx a = fmpqxx::frac(1, 2); const fmpqxx& b = a; tassert(b.num() == 1); const fmpqxx_ref c(a); c.num() = 3; tassert(c.num() == 3); } int main() { std::cout << "fmpqxx...."; test_init(); test_assignment(); test_conversion(); test_order(); test_arithmetic(); test_functions(); test_extras(); test_vector(); test_unified_access(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-fmpz_matxx.cpp000066400000000000000000000205661414523752600205620ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_matxx.h" #include "fmpz_vecxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_init() { fmpz_matxx A(3, 4); tassert(A.rows() == 3 && A.cols() == 4); tassert(A.at(0, 0) == 0); A.at(0, 0) = 1; fmpz_matxx B(A); tassert(B.rows() == 3 && B.cols() == 4); tassert(B.at(0, 0) == 1); B.at(0, 0) = 0; tassert(A.at(0, 0) == 1); tassert(fmpz_matxx::zero(3, 4).is_zero()); fmpz_matxx eye = fmpz_matxx::one(4, 4); for(slong i = 0;i < eye.rows();++i) for(slong j = 0;j < eye.cols();++j) tassert(eye.at(i, j) == int(i == j)); } template bool has_explicit_temporaries(const Expr&) { return Expr::ev_traits_t::rule_t::temporaries_t::len != 0; } template bool compare_temporaries(const Expr&) { return mp::equal_types::val; } void test_arithmetic() { fmpz_matxx A(10, 10); fmpz_matxx v(10, 1); for(unsigned i = 0;i < 10;++i) v.at(i, 0) = i; tassert(transpose(v).rows() == 1); tassert(v.transpose().cols() == 10); tassert((2*v).rows() == 10); tassert((v*2).rows() == 10); tassert((v*transpose(v)).rows() == 10 && (v*transpose(v)).cols() == 10); tassert(mul_classical(v, transpose(v)).rows() == 10); tassert(mul_multi_mod(v, transpose(v)).cols() == 10); tassert(!has_explicit_temporaries(trace(transpose(v)))); tassert(!has_explicit_temporaries(trace(A + v*transpose(v)))); tassert(!has_explicit_temporaries(A + v*transpose(v))); tassert(!has_explicit_temporaries(trace((v*transpose(v) + A)))); tassert(!has_explicit_temporaries(trace(v*transpose(v) + v*transpose(v)))); tassert(!has_explicit_temporaries(v*transpose(v) + v*transpose(v))); tassert((compare_temporaries >( ((A+A)*(fmpzxx(1)+fmpzxx(1)))))); tassert(trace(transpose(v)) == 0); tassert(trace(A + v*transpose(v)) == 285); tassert(trace(v*transpose(v) + A) == 285); tassert(trace(v*transpose(v) + v*transpose(v)) == 2*285); tassert(trace((A+A)*(fmpzxx(1) + fmpzxx(1))) == 0); for(unsigned i = 0;i < 10; ++i) for(unsigned j = 0; j < 10; ++j) A.at(i, j) = i*j; tassert(A == v*transpose(v)); tassert(A != transpose(v)*v); A.at(0, 0) = 15; tassert(A != v*transpose(v)); A.at(0, 0) = 0; for(unsigned i = 0;i < 10; ++i) for(unsigned j = 0; j < 10; ++j) A.at(i, j) *= 2; tassert(A == v*transpose(v) + v*transpose(v)); tassert(A - v*transpose(v) == v*transpose(v)); tassert(((-A) + A).is_zero()); tassert((A + A).at(0, 0) == A.at(0, 0) + A.at(0, 0)); tassert((A + A) == 2*A && A*2 == A*2u && fmpzxx(2)*A == 2u*A); tassert((2*A).divexact(2) == A); tassert((2*A).divexact(2u) == A); tassert((2*A).divexact(fmpzxx(2)) == A); } void test_functions() { fmpz_matxx A(2, 3), B(2, 2), empty(0, 15); B.at(0, 0) = 1; tassert(A.is_zero() && !A.is_empty() && !A.is_square()); tassert(!B.is_zero() == B.is_square()); tassert(empty.is_zero() && empty.is_empty()); // transpose tested in arithmetic // mul tested in arithmetic // trace tested in arithmetic frandxx rand; A.set_randtest(rand, 10); B.set_randtest(rand, 10); tassert(B*A == mul_classical(B, A)); tassert(B*A == mul_multi_mod(B, A)); tassert(sqr(B) == B*B); tassert(B.sqr().sqr() == pow(B, 4u)); B.set_randrank(rand, 1, 10); tassert(!inv(B).get<0>()); B.set_randdet(rand, fmpzxx(2*3*5)); tassert(B.det() == 2*3*5); fmpz_matxx Binv(2, 2); bool worked; fmpzxx d; ltupleref(worked, Binv, d) = inv(B); tassert(worked && d.divisible(fmpzxx(2*3*5))); fmpz_matxx eye(2, 2);eye.at(0, 0) = 1;eye.at(1, 1) = 1; tassert((Binv * B).divexact(d) == eye); B.set_randdet(rand, fmpzxx(105)); tassert(B.det() == B.det_bareiss()); tassert(B.det() == B.det_cofactor()); tassert(abs(B.det()) <= B.det_bound()); tassert(B.det().divisible(B.det_divisor())); tassert(B.det() == B.det_modular(true)); tassert(B.det() == B.det_modular_accelerated(true)); tassert(B.det() == B.det_modular_given_divisor(fmpzxx(1), true)); tassert(B.charpoly().get_coeff(0) == B.det()); tassert(charpoly(B).get_coeff(1) == -B.trace()); tassert(charpoly(B).lead() == 1); A.set_randrank(rand, 2, 10); tassert(rank(A) == 2); fmpz_matxx X(2, 3); ltupleref(worked, X, d) = solve(B, A); tassert(worked == true && (B*X).divexact(d) == A); ltupleref(worked, X, d) = B.solve_fflu(A); tassert(worked == true && (B*X).divexact(d) == A); ltupleref(worked, X, d) = B.solve_cramer(A); tassert(worked == true && (B*X).divexact(d) == A); tassert(solve(B, A).get<1>() == X); slong nullity;fmpz_matxx C(3, 3); tassert(nullspace(A).get<1>().rows() == 3); tassert(nullspace(A).get<1>().cols() == 3); ltupleref(nullity, C) = nullspace(A); tassert(nullity == 3 - rank(A)); tassert(C.rank() == nullity); tassert((A*C).is_zero()); // TODO test solve_dixon, solve_bound } void test_extras() { fmpz_matxx A(10, 10), B(10, 10); frandxx rand; A.set_randtest(rand, 15); B.set_randtest(rand, 15); A.at(0, 0) = B.at(0, 0) + 1u; fmpz_matxx_srcref Asr(A); fmpz_matxx_ref Br(B); tassert((A + A) + (B + B) == (Asr + Asr) + (Br + Br)); Br = Asr; tassert(A == B); fmpz_matxx C(Asr); tassert(C == A); C.at(0, 0) += 2u; tassert(C != A); } void test_randomisation() { frandxx rand; fmpz_matxx A = fmpz_matxx::randbits(2, 2, rand, 5); tassert(abs(A.at(0, 0)) <= 31 && abs(A.at(0, 0)) >= 16); A.set_randtest(rand, 5); tassert(abs(A.at(0, 0)) <= 31); fmpz_matxx::randtest(2, 2, rand, 5); fmpz_matxx B(2, 3); B.set_randintrel(rand, 5); tassert(abs(B.at(0, 0)) <= 31); A.set_randsimdioph(rand, 5, 6); tassert(A.at(0, 0) == 64 && abs(A.at(0, 1)) <= 31); tassert(A.at(1, 0) == 0 && A.at(1, 1) == 32); // TODO set_randntrulike, set_randntrulike2, set_randajtai fmpz_vecxx v(2);v[0] = 5;v[1] = 7; A.set_randpermdiag(rand, v); tassert(A.at(0, 0) + A.at(0, 1) + A.at(1, 0) + A.at(1, 1) == 5 + 7); A.set_randrank(rand, 1, 5); tassert(abs(A.at(0, 0)) <= 31 && A.rank() == 1); tassert(rank(fmpz_matxx::randrank(5, 6, rand, 3, 10)) == 3); A.apply_randops(rand, 17); tassert(abs(A.at(0, 0)) <= 31 && A.rank() == 1); A.set_randdet(rand, fmpzxx(17)); tassert(det(A) == 17); tassert(fmpz_matxx::randdet(5, 5, rand, fmpzxx(123)).det() == 123); } void test_row_reduction() { frandxx state; fmpz_matxx A = fmpz_matxx::randtest(5, 5, state, 15); slong rank1, rank2; fmpzxx den1, den2; fmpz_matxx res1(A.rows(), A.cols()), res2(A.rows(), A.cols()); tassert(find_pivot_any(A, 2, 4, 1) == fmpz_mat_find_pivot_any(A._mat(), 2, 4, 1)); tassert(A.fflu(0, false).get<1>().rows() == A.rows()); permxx p1(5), p2(5); ltupleref(rank1, res1, den1) = fflu(A, &p1); rank2 = fmpz_mat_fflu(res2._mat(), den2._fmpz(), p2._data(), A._mat(), false); tassert(rank1 == rank2 && res1 == res2 && p1 == p2 && den1 == den2); tassert(rank1 == A.fflu(0, false).get<0>()); ltupleref(rank1, res1, den1) = rref(A); rank2 = fmpz_mat_rref(res2._mat(), den2._fmpz(), A._mat()); tassert(rank1 == rank2 && res1 == res2 && den1 == den2); fmpz_matxx B(A); fmpzxx n(1031); A.set_rref_mod(n, &p1); fmpz_mat_rref_mod(p2._data(), B._mat(), n._fmpz()); tassert(A == B && p1 == p2); } void test_printing() { frandxx rand; fmpz_matxx A = fmpz_matxx::randtest(2, 2, rand, 5); test_print_read(A); A.set_one(); tassert_fprint_pretty(A, "[[1 0]\n[0 1]\n]"); } int main() { std::cout << "fmpz_matxx...."; test_init(); test_arithmetic(); test_functions(); test_extras(); test_randomisation(); test_row_reduction(); test_printing(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-fmpz_mod_polyxx.cpp000066400000000000000000000234241414523752600216170ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_mod_polyxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_init(fmpz_modxx_ctx& M) { M.set_modulus(2003); fmpz_mod_polyxx p(M); tassert(p.length() == 0); tassert(p.modulus() == 2003); tassert(fmpz_mod_polyxx::zero(M).is_zero()); } void test_manipulation(fmpz_modxx_ctx& M) { M.set_modulus(1031); fmpz_mod_polyxx p(M), q(M); p.set_coeff(5, 17u + M.modulus()); tassert(p.degree() == 5); q.set_coeff(5, fmpzxx(16) + fmpzxx(1)); tassert((q + fmpz_mod_polyxx(M)).get_coeff(5) == 17); p.set_coeff(0, 1); tassert(p != q); p.set_coeff(0, 0); tassert(p == q); tassert((p + p).lead() == 2*p.lead()); q.lead() = 0; q._normalise(); tassert(q.is_zero()); p.realloc(0); tassert(p.is_zero()); } void test_assignment(fmpz_modxx_ctx& M) { M.set_modulus(31); fmpz_mod_polyxx p(M), q(M); p.set_coeff(0, 1); tassert(p != q); p = q; tassert(p == q); } void test_conversion(fmpz_modxx_ctx& M) { M.set_modulus(1031); fmpz_mod_polyxx p(M); p = 4u + 1031; tassert(p.length() == 1 && p.get_coeff(0) == 4); p = fmpzxx(5) + M.modulus(); tassert(p.length() == 1 && p.get_coeff(0) == 5); frandxx rand; fmpz_polyxx P = fmpz_polyxx::randtest(rand, 10, 20); p = P; for(slong i = 0;i < P.length();++i) tassert(P.get_coeff(i) % M.modulus() == p.get_coeff(i)); fmpz_polyxx Pp = p.to(); for(slong i = 0;i < P.length();++i) tassert(P.get_coeff(i) % M.modulus() == Pp.get_coeff(i)); } void test_arithmetic(fmpz_modxx_ctx& M) { M.set_modulus(1031); fmpz_mod_polyxx g(M), h(M); g.set_coeff(0, 17); h.set_coeff(0, 15u + M.modulus()); tassert((g + h).get_coeff(0) == 15 + 17); frandxx state; g.set_randtest(state, 10); h.set_randtest(state, 10); tassert(((-g) + g).is_zero()); tassert(g - h == g + (-h)); tassert(g*fmpzxx(3) == g + g + g); tassert(g.make_monic() == g*g.lead().invmod(M.modulus())); fmpz_mod_polyxx f(M);f = 15u; tassert(f*g == fmpzxx(15)*g); f = h*g;f.truncate(7); tassert(f == mullow(h, g, 7)); f = h / g; tassert(f*g + (h % g) == h); tassert(((h*g) % h).is_zero()); f.set_randtest(state, 10); tassert(h.mulmod(g, f) == ((h*g) % f)); fmpz_mod_polyxx X(M);X.set_coeff(1, 1); fmpz_mod_polyxx one(M);one.set_coeff(0, 1); f = X*X + one; fmpzxx x(7); tassert(evaluate(f, x) == x*x + 1u); tassert(f(x) == evaluate(f, x)); fmpz_mod_polyxx seven(M); seven.set_coeff(0, x); tassert(compose(f, seven).get_coeff(0) == f(x)); tassert(f(seven).length() == 1); } void test_functions(fmpz_modxx_ctx& M) { M.set_modulus(1031); fmpz_mod_polyxx g(M), res(M); g.set_coeff(5, 15); g.truncate(3); tassert(g.is_zero()); g.set_coeff(15, 1); fmpz_mod_polyxx one(M);one = 1u; tassert(g.shift_right(15) == one); tassert(g.shift_right(15).shift_left(15) == g); frandxx rand; g.set_randtest(rand, 15); tassert(g.length() <= 15); g.set_randtest_irreducible(rand, 15); tassert(g.length() <= 15); g.set_randtest_not_zero(rand, 15); tassert(g.length() <= 15 && !g.is_zero()); g.set_coeff(15, 1); g.zero_coeffs(14, 15); tassert(g.get_coeff(14) == 0); // multiplication, division, modulo tested in arithmetic tassert(g.pow(3u) == g*g*g); res = g.pow(15u);res.truncate(12); tassert(res == g.pow_trunc(15u, 12)); tassert(res == g.pow_trunc_binexp(15u, 12)); fmpz_mod_polyxx f(M);f.set_randtest(rand, 10); res = g.pow(10u) % f; tassert(res == g.powmod_binexp(10u, f)); tassert(res == g.powmod_binexp(fmpzxx(10), f)); fmpz_mod_polyxx tmp(M); ltupleref(res, tmp) = f.gcdinv(g); tassert(res == gcd(f, g) && tmp*f % g == res); g.set_randtest_irreducible(rand, 5); tassert(f.invmod(g)*f % g == one); assert_exception((f*g).invmod(g).evaluate()); res = g*f; res.remove(f); tassert(res == g); fmpz_polyxx lift; lift = "5 1 1 1 1 1"; res = lift; tassert(res.derivative().to().to_string() == "4 1 2 3 4"); tassert(f.divrem(g) == ltuple(f / g, f % g)); tassert(f.divrem_basecase(g) == f.divrem(g)); tassert(f.divrem_divconquer(g) == f.divrem(g)); tassert(f.divrem_f(g) == ltuple(1, f / g, f % g)); tassert(f.div_basecase(g) == f / g); tassert(f.rem_basecase(g) == f % g); f.set_coeff(0, 17); res = f*f.inv_series_newton(15);res.truncate(15); tassert(res == one); tassert(f(g) == f.compose_divconquer(g)); tassert(f(g) == f.compose_horner(g)); fmpz_mod_polyxx h(M); h.set_randtest(rand, 15); tassert(f.compose_mod(g, h) == f(g) % h); tassert(f.compose_mod(g, h) == f.compose_mod_horner(g, h)); tassert(f.compose_mod(g, h) == f.compose_mod_brent_kung(g, h)); h.set_randtest_irreducible(rand, 12); tassert(h.gcd(f) == one); tassert(f.gcd_euclidean(f) == f.make_monic()); tassert(f.gcd_f(g) == ltuple(1, f.gcd(g))); tassert(f.gcd_euclidean_f(g) == ltuple(1, f.gcd(g))); fmpz_mod_polyxx R(M), S(M); ltupleref(res, R, S) = f.xgcd(g); tassert(res == R*f + S*g && res == gcd(f, g)); tassert(f.xgcd(g) == f.xgcd_euclidean(g)); } bool equiv_fac(const fmpz_mod_poly_factorxx& fac1, const fmpz_mod_poly_factorxx& fac2) { tassert(fac1.size() == 2); if(fac1.exp(0) == fac1.exp(1)) { if(fac2.exp(0) != fac1.exp(0) || fac2.exp(1) != fac1.exp(0)) return false; return (fac1.p(0) == fac2.p(0) && fac1.p(1) == fac2.p(1)) || (fac1.p(1) == fac2.p(0) && fac1.p(0) == fac2.p(1)); } if(fac1.size() != fac2.size()) return false; if(fac1.exp(0) == fac2.exp(0)) return fac1.exp(1) == fac2.exp(1) && fac1.p(0) == fac2.p(0) && fac1.p(1) == fac2.p(1); else return fac1.exp(0) == fac2.exp(1) && fac1.exp(1) == fac2.exp(0) && fac1.p(0) == fac2.p(1) && fac1.p(1) == fac2.p(0); } void test_factoring(fmpz_modxx_ctx& M) { M.set_modulus(1031); fmpz_mod_polyxx f(M), g(M); frandxx state; f.set_randtest_irreducible(state, 4); f = f.make_monic(); g.set_randtest_irreducible(state, 5); g = g.make_monic(); fmpz_mod_poly_factorxx fac(M); fac = factor(f*f*g); tassert(fac.size() == 2); if(fac.exp(0) == 1) { tassert(fac.p(0) == g); tassert(fac.p(1) == f && fac.exp(1) == 2); } else { tassert(fac.p(0) == f && fac.exp(0) == 2); tassert(fac.p(1) == g && fac.exp(1) == 1); } fmpz_mod_poly_factorxx fac2(M);fac2 = fac;fac2.pow(2); fac.insert(g, 1); fac.insert(f, 2); tassert(fac == fac2); fmpz_mod_polyxx prod(f*f*f*g*g); fac = factor(prod); tassert(equiv_fac(fac, factor_cantor_zassenhaus(prod))); tassert(equiv_fac(factor(f*g), factor_berlekamp(f*g))); tassert(equiv_fac(fac, factor_kaltofen_shoup(prod))); std::vector degs(2); fac.realloc(0);fac.set_factor_distinct_deg(f*g, degs); tassert(degs.size() == 2); tassert((degs[0] == f.degree() && degs[1] == g.degree()) || (degs[1] == f.degree() && degs[0] == g.degree())); tassert(f.is_irreducible() && f.is_irreducible_ddf() && f.is_irreducible_rabin()); tassert(f.is_squarefree()); // TODO test set_factor_equal_deg* if(0) print(fac); // test this compiles } void test_randomisation(fmpz_modxx_ctx& M) { frandxx state, state2; M.set_modulus(1031); fmpz_mod_polyxx p(M); p.set_randtest(state, 10); tassert(p == fmpz_mod_polyxx::randtest(M, state2, 10)); p.set_randtest_irreducible(state, 10); tassert(p == fmpz_mod_polyxx::randtest_irreducible(M, state2, 10)); p.set_randtest_not_zero(state, 10); tassert(p == fmpz_mod_polyxx::randtest_not_zero(M, state2, 10)); } void test_radix(fmpz_modxx_ctx& M) { M.set_modulus(1031); fmpz_mod_poly_vecxx v1(10, M), v2(10, M); v1[0].set_coeff(7, 1); tassert(v1 != v2); fmpz_mod_poly_vecxx v3(v1); tassert(v3 == v1); v3[0].set_coeff(1, 1); tassert(v3 != v1); v2[0].set_coeff(7, 1); tassert(v1 == v2); frandxx rand; fmpz_mod_polyxx F = fmpz_mod_polyxx::randtest(M, rand, 10); fmpz_mod_polyxx R = fmpz_mod_polyxx::randtest(M, rand, 3); fmpz_mod_poly_vecxx b(F.degree() / R.degree() + 1, M); fmpz_mod_poly_radixxx rad(R, 15); b = F.radix(rad); tassert(b == F.radix(rad)); fmpz_mod_polyxx f(M); for(slong i = 0;i < b.size();++i) f += b[i]*R.pow(static_cast(i)); tassert(f == F); } void test_printing(fmpz_modxx_ctx& M) { frandxx state; M.set_modulus(7); fmpz_mod_polyxx f = fmpz_mod_polyxx::randtest(M, state, 4); test_print_read(f); f.set_zero(); f.set_coeff(0, 3); f.set_coeff(1, 1); tassert_fprint_pretty(f, "x", "x+3"); } void test_unified_access(fmpz_modxx_ctx& M) { M.set_modulus(1031); fmpz_mod_polyxx p(M); p.set_coeff(0, 1); const fmpz_mod_polyxx& q = p; tassert(q.lead() == 1); } int main() { std::cout << "fmpz_mod_polyxx...."; fmpz_modxx_ctx M(2); test_init(M); test_manipulation(M); test_assignment(M); test_conversion(M); test_arithmetic(M); test_functions(M); test_factoring(M); test_randomisation(M); test_radix(M); test_printing(M); test_unified_access(M); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-fmpz_poly_matxx.cpp000066400000000000000000000211651414523752600216210ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_matxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_init() { fmpz_poly_matxx A(3, 4); tassert(A.rows() == 3 && A.cols() == 4); tassert(A.at(0, 0) == fmpz_polyxx::from_ground(0)); A.at(0, 0) = fmpz_polyxx::from_ground(1); fmpz_poly_matxx B(A); tassert(B.rows() == 3 && B.cols() == 4); tassert(B.at(0, 0) == fmpz_polyxx::from_ground(1)); B.at(0, 0) = fmpz_polyxx::from_ground(0); tassert(A.at(0, 0) == fmpz_polyxx::from_ground(1)); tassert(fmpz_poly_matxx::zero(3, 3).is_zero()); tassert(fmpz_poly_matxx::one(3, 3).is_one()); } template bool has_explicit_temporaries(const Expr&) { return Expr::ev_traits_t::rule_t::temporaries_t::len != 0; } void test_arithmetic() { fmpz_poly_matxx A(10, 10); fmpz_poly_matxx v(10, 1); for(unsigned i = 0;i < 10;++i) v.at(i, 0) = fmpz_polyxx::from_ground(i); tassert(transpose(v).rows() == 1); tassert(v.transpose().cols() == 10); tassert((fmpzxx(2)*v).rows() == 10); tassert((v*fmpzxx(2)).rows() == 10); tassert((v*transpose(v)).rows() == 10 && (v*transpose(v)).cols() == 10); tassert(mul_classical(v, transpose(v)).rows() == 10); tassert(mul_KS(v, transpose(v)).cols() == 10); tassert(!has_explicit_temporaries(trace(transpose(v)))); tassert(!has_explicit_temporaries(trace(A + v*transpose(v)))); tassert(!has_explicit_temporaries(A + v*transpose(v))); tassert(!has_explicit_temporaries(trace((v*transpose(v) + A)))); tassert(!has_explicit_temporaries(trace(v*transpose(v) + v*transpose(v)))); tassert(!has_explicit_temporaries(v*transpose(v) + v*transpose(v))); tassert((transpose(v)).trace() == fmpz_polyxx::from_ground(0)); tassert(trace(A + v*transpose(v)) == fmpz_polyxx::from_ground(285)); tassert(trace(v*transpose(v) + A) == fmpz_polyxx::from_ground(285)); tassert(trace(v*transpose(v) + v*transpose(v)) == fmpz_polyxx::from_ground(2*285)); tassert(trace((A+A)*(fmpz_polyxx(1) + fmpz_polyxx(1))).is_zero()); for(unsigned i = 0;i < 10; ++i) for(unsigned j = 0; j < 10; ++j) A.at(i, j) = fmpz_polyxx::from_ground(i*j); tassert(A == v*transpose(v)); tassert(A != transpose(v)*v); A.at(0, 0) = fmpz_polyxx::from_ground(15); tassert(A != v*transpose(v)); A.at(0, 0) = fmpz_polyxx::from_ground(0); for(unsigned i = 0;i < 10; ++i) for(unsigned j = 0; j < 10; ++j) A.at(i, j) *= 2; tassert(A == v*transpose(v) + v*transpose(v)); tassert(A - v*transpose(v) == v*transpose(v)); tassert(((-A) + A).is_zero()); tassert((A + A).at(0, 0) == A.at(0, 0) + A.at(0, 0)); tassert((A + A) == fmpzxx(2)*A && fmpz_polyxx::from_ground(2)*A == (A + A)); frandxx rand; fmpzxx x(17); A.set_randtest(rand, 3, 5); fmpz_matxx B(A.rows(), A.cols()); B = A(x); for(slong i = 0;i < A.rows();++i) for(slong j = 0;j < A.cols();++j) tassert(B.at(i, j) == A.at(i, j)(x)); tassert(A(x) == evaluate(A, x)); } void test_functions() { fmpz_poly_matxx A(2, 3), B(2, 2), empty(0, 15); B.at(0, 0) = fmpz_polyxx::from_ground(1); tassert(A.is_zero() && !A.is_empty() && !A.is_square() && !A.is_one()); tassert(!B.is_zero() == B.is_square()); tassert(empty.is_zero() && empty.is_empty()); // transpose tested in arithmetic // mul tested in arithmetic // trace tested in arithmetic A.at(0, 0).set_coeff(35, 17); tassert(A.max_length() == 36); tassert(A.max_bits() == 5); frandxx rand; A.set_randtest(rand, 4, 10); B.set_randtest(rand, 4, 10); tassert(B*A == B.mul_classical(A)); tassert(B*A == B.mul_KS(A)); fmpz_poly_matxx tmp(B*A); tmp.truncate(3); tassert(tmp == B.mullow(A, 3)); tassert(sqr(B) == B*B); tassert(B.sqr().sqr() == pow(B, 4u)); tassert(B.sqrlow(3) == B.mullow(B, 3)); tmp = pow(B, 5u); tmp.truncate(7); tassert(tmp == B.pow_trunc(5u, 7)); B.set_randtest(rand, 4, 10); tassert(B.det() == B.det_fflu()); tassert(B.det()(fmpzxx(123)) == B(fmpzxx(123)).det()); tassert(B.det() == B.det_interpolate()); fmpz_matxx Bp(2, 2); Bp.set_randdet(rand, fmpzxx(2*3*5)); tassert(fmpz_poly_matxx::from_ground(Bp).det() == fmpz_polyxx::from_ground(2*3*5)); fmpz_poly_matxx C(3, 3); C.at(0, 0).set_coeff(0, 1); C.at(1, 1).set_coeff(0, 1); tassert(rank(C) == 2); Bp.set_randrank(rand, 1, 10); B = fmpz_poly_matxx::from_ground(Bp); tassert(!inv(B).get<0>()); Bp.set_randrank(rand, 2, 10); B = fmpz_poly_matxx::from_ground(Bp); fmpz_poly_matxx Binv(2, 2); bool worked; fmpz_polyxx d; ltupleref(worked, Binv, d) = inv(B); tassert(worked); fmpz_poly_matxx eye(2, 2); eye.at(0, 0).set_coeff(0, 1);eye.at(1, 1).set_coeff(0, 1); tassert(eye.is_one()); tassert(Binv * B == d*eye); fmpz_poly_matxx X(2, 3); ltupleref(worked, X, d) = solve(B, A); tassert(worked == true && (B*X) == A*d); ltupleref(worked, X, d) = B.solve_fflu(A); tassert(worked == true && (B*X) == A*d); tassert(solve(B, A).get<1>() == X); permxx perm(B.rows()); fmpz_poly_matxx F(B.rows(), B.rows()); fmpz_polyxx Fd, Xd; slong rk; // Note: fflu has a (false?) dependency on perm - need perm = id before call ltupleref(rk, F, Fd) = B.fflu(&perm, false); ltupleref(worked, X, Xd) = B.solve_fflu(A); tassert(worked && Xd*solve_fflu_precomp(perm, F, A) == Fd * X); slong nullity; tassert(nullspace(A).get<1>().rows() == 3); tassert(nullspace(A).get<1>().cols() == 3); ltupleref(nullity, C) = nullspace(A); tassert(nullity == 3 - rank(A)); tassert(C.rank() == nullity); tassert((A*C).is_zero()); if(0) print_pretty(A, "x"); // make sure this compiles } void test_extras() { fmpz_poly_matxx A(2, 2); A.at(0, 0).set_coeff(0, 1); fmpz_poly_matxx_srcref Asr(A); const fmpz_poly_matxx& Acr = A; tassert(A.at(0, 0) == Acr.at(0, 0)); tassert(A.at(0, 0) == Asr.at(0, 0)); } void test_randomisation() { frandxx rand, rand2; fmpz_poly_matxx A(2, 2); A.set_randtest(rand, 4, 5); tassert(abs(A.at(0, 0).get_coeff(0)) <= 31); tassert(A == fmpz_poly_matxx::randtest(2, 2, rand2, 4, 5)); A.set_randtest_unsigned(rand, 4, 5); tassert(A.at(0, 0).get_coeff(0) >= 0); tassert(A == fmpz_poly_matxx::randtest_unsigned(2, 2, rand2, 4, 5)); A.set_randtest_sparse(rand, 4, 5, 0.5); tassert(abs(fmpz_polyxx_get_coeff(A.at(0, 0), 0)) <= 31); tassert(A == fmpz_poly_matxx::randtest_sparse(2, 2, rand2, 4, 5, 0.5)); } void test_row_reduction() { frandxx state; fmpz_poly_matxx A = fmpz_poly_matxx::randtest(5, 5, state, 7, 15); slong rank1, rank2; fmpz_polyxx den1, den2; fmpz_poly_matxx res1(A.rows(), A.cols()), res2(A.rows(), A.cols()); tassert(find_pivot_any(A, 2, 4, 1) == fmpz_poly_mat_find_pivot_any(A._mat(), 2, 4, 1)); tassert(find_pivot_partial(A, 2, 4, 1) == fmpz_poly_mat_find_pivot_partial(A._mat(), 2, 4, 1)); tassert(A.fflu(0, false).get<1>().rows() == A.rows()); permxx p1(5), p2(5); ltupleref(rank1, res1, den1) = fflu(A, &p1); rank2 = fmpz_poly_mat_fflu(res2._mat(), den2._poly(), p2._data(), A._mat(), false); tassert(rank1 == rank2 && res1 == res2 && p1 == p2 && den1 == den2); tassert(rank1 == A.fflu(0, false).get<0>()); ltupleref(rank1, res1, den1) = rref(A); rank2 = fmpz_poly_mat_rref(res2._mat(), den2._poly(), A._mat()); tassert(rank1 == rank2 && res1 == res2 && p1 == p2 && den1 == den2); } void test_prod() { fmpz_poly_mat_vecxx v1(10, 3, 3), v2(10, 3, 3), v3(9, 3, 3), v4(v1); tassert(v1 == v2); tassert(v1 != v3); v1[0].at(0, 0).set_coeff(0, 7u); tassert(v1 != v4); frandxx rand; fmpz_poly_matxx prod = fmpz_poly_matxx::one(3, 3); for(slong i = 0;i < v1.size();++i) { v1[i].set_randtest(rand, 4, 17); prod *= v1[i]; } tassert(flint::prod(v1) == prod); } int main() { std::cout << "fmpz_poly_matxx...."; test_init(); test_arithmetic(); test_functions(); test_extras(); test_randomisation(); test_row_reduction(); test_prod(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-fmpz_poly_qxx.cpp000066400000000000000000000072741414523752600213050ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_qxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_manipulation() { fmpz_poly_qxx f; f.num() = "3 0 1 1"; f.den() = "3 0 -1 1"; tassert(!f.is_canonical()); f.canonicalise(); tassert(f.num().to_string() == "2 1 1"); tassert(f.den().to_string() == "2 -1 1"); tassert(fmpz_poly_qxx::zero().is_zero()); tassert(fmpz_poly_qxx::one().is_one()); } void test_assignment_conversion() { fmpz_poly_qxx f, g; f = 1; tassert(f.is_one()); g = 0; f = g; tassert(f.is_zero()); tassert(f.to_string() == "0"); f = "4 1 0 0 1"; tassert(f.num().to_string() == "4 1 0 0 1"); tassert(f.den().to_string() == "1 1"); f.den() = "2 -1 1"; tassert(f.to_string() == "4 1 0 0 1/2 -1 1"); g = "4 1 0 0 1/2 -1 1"; tassert(f == g); tassert(f == fmpz_poly_qxx("4 1 0 0 1/2 -1 1")); tassert(f.pretty("x") == "(x^3+1)/(x-1)"); } void test_arithmetic() { fmpz_poly_qxx f, g; g = "4 1 0 0 1/2 -1 1"; f = "1 1"; tassert((f + g).to_string() == "4 0 1 0 1/2 -1 1"); tassert((g - f).to_string() == "4 2 -1 0 1/2 -1 1"); tassert(g - f == g + (-f)); tassert(inv(g).to_string() == "2 -1 1/4 1 0 0 1"); tassert(2 * g == g * 2); f = 2*g; tassert(f.num() == 2*g.num() && f.den() == g.den()); f /= 2; tassert(f == g); f = "1 1"; tassert((f*g).num() == f.num()*g.num()); tassert((f*g).den() == f.den()*g.den()); tassert((f/g).num() == f.num()*g.den()); tassert((f/g).den() == f.den()*g.num()); } // Won't compile if the expression is not done using addmul template bool is_ternary(const T&) { return T::ev_traits_t::temp_rule_t::TERNARY_OP_MARKER + 1; } // test stuff which we should get automatically - addmul, references etc void test_extras() { // TODO } void test_functions() { fmpz_poly_qxx f; tassert(f.is_zero() && !f.is_one()); f.num() = 1; tassert(f.is_one()); f = "4 1 0 0 1/2 -1 1"; tassert(pow(f, 4u) == f*f*f*f); tassert(derivative(f).to_string() == "4 -1 0 -3 2/3 1 -2 1"); // test static methods frandxx rand; tassert(fmpz_poly_qxx::randtest(rand, 10, 8, 10, 8).num().degree() < 10); tassert(fmpz_poly_qxx::randtest(rand, 10, 8, 10, 8).den().degree() < 10); tassert(flog(height(fmpz_poly_qxx::randtest( rand, 10, 8, 10, 8).num()), 2u) < 8); tassert(flog(height(fmpz_poly_qxx::randtest( rand, 10, 8, 10, 8).den()), 2u) < 8); tassert(!fmpz_poly_qxx::randtest_not_zero(rand, 10, 8, 10, 8).is_zero()); tassert(f.derivative() == derivative(f)); tassert(f.inv() == inv(f)); tassert(f.pow(7u) == pow(f, 7u)); } void test_printing() { if(0) { // make sure these compile fmpz_poly_qxx f; print(f); print_pretty(f, "x"); } } void test_unified_access() { fmpz_poly_qxx a; const fmpz_poly_qxx& b = a; tassert(b.num().is_zero() && b.den().is_one()); } int main() { std::cout << "fmpz_poly_qxx...."; test_manipulation(); test_assignment_conversion(); test_arithmetic(); test_functions(); test_extras(); test_printing(); test_unified_access(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-fmpz_polyxx.cpp000066400000000000000000000322321414523752600207550ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_polyxx.h" #include "nmod_polyxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_init() { fmpz_polyxx p(10); tassert(p.length() == 0); tassert(fmpz_polyxx::zero().is_zero()); tassert(fmpz_polyxx::one().is_one()); } void test_manipulation() { fmpz_polyxx p, q; tassert(p.get_coeff(5) == 0); p.set_coeff(5, 17); tassert(p.degree() == 5); q.set_coeff(5, 17u); p.set_coeff(0, fmpzxx(1)); q.coeff(0) = 1; tassert(p == q); tassert(p.lead() == 17); tassert(p.length() == 6); p.zero_coeffs(0, 6); tassert(p.is_zero() && !p.is_one() && !p.is_unit()); p.set_coeff(0, 1); tassert(p.is_one() && p.is_unit()); p.set_coeff(0, -1); tassert(p.is_unit()); const fmpz_polyxx pc = p; tassert(p.get_coeff(0) == pc.get_coeff(0)); tassert((p*q).coeff(0) == p.get_coeff(0)*q.get_coeff(0)); tassert((p*q).lead() == p.lead()*q.lead()); } void test_assignment() { fmpz_polyxx p, q; p = 1; tassert(p.is_one()); q = UWORD(0); tassert(q.is_zero()); tassert(p != q); p = q; tassert(p == q); p = "4 0 0 0 1"; q.set_coeff(3, 1); tassert(p == q); // TODO XXX this does not always fail? //assert_exception(p = "4 1 2"); assert_exception(p = "2 1 2"); } void test_conversion() { fmpz_polyxx p; p.set_coeff(3, 1); tassert(p.to_string() == "4 0 0 0 1"); tassert(p.pretty("x") == "x^3"); tassert(p == fmpz_polyxx("4 0 0 0 1")); } void test_arithmetic() { fmpz_polyxx p, q; p = 1; q = "4 0 0 0 1"; tassert((p + q).to_string() == "4 1 0 0 1"); tassert((p - q).to_string() == "4 1 0 0 -1"); tassert((-p).to_string() == "1 -1"); fmpzxx two(2); tassert(two * q == 2 * q && 2u * q == q * 2 && (two * q).to_string() == "4 0 0 0 2"); q *= 2; tassert(q / two == q / 2u && q / 2 == q / two && (q / two).to_string() == "4 0 0 0 1"); // q == "4 0 0 0 2" q.set_coeff(1, 17); // q == "4 0 17 0 2" tassert((q % fmpzxx(5)).to_string() == "4 0 2 0 2"); p = "3 1 0 1"; tassert((p*q).to_string() == "6 0 17 0 19 0 2"); tassert((p*q) / p == q); tassert(p + q % q == p); tassert(p(fmpzxx(1) + fmpzxx(1)) == 5); q = "3 0 0 1"; tassert(p(q).to_string() == "5 1 0 0 0 1"); } // Won't compile if the expression is not done using addmul template bool is_ternary(const T&) { return T::ev_traits_t::temp_rule_t::TERNARY_OP_MARKER + 1; } // test stuff which we should get automatically - addmul, references etc void test_extras() { // TODO addmul when we have it } ulong pow(ulong base, ulong exp) { ulong res = 1; while(exp-- > 0) res *= base; return base; } void test_functions() { // test swap fmpz_polyxx p, q; p = 1; q = 0; swap(p, q); tassert(p.is_zero() && q.is_one()); // p = 0, q = 1 fmpz_polyxx f, g, xp1; f = "4 2 0 0 1"; // f = x^3 + 2 g = "5 1 2 3 4 5"; xp1 = "2 1 1"; fmpzxx two(2); // test lazy functions tassert(reverse(q, 4).pretty("x") == "x^3"); tassert(mul_2exp(f, 3u) == f * 8); tassert(f == fdiv_2exp(mul_2exp(f, 3u), 3u)); tassert(tdiv(-f, two) == tdiv(-f, 2) && tdiv(-f, 2) == tdiv(-f, 2u) && tdiv(-f, two).to_string() == "4 -1 0 0 0"); tassert(f == divexact(2*f, two) && f == divexact(2*f, 2u) && f == divexact(2*f, 2)); tassert(-f == tdiv_2exp(-8*f - q, 3u)); tassert(smod(5*f, fmpzxx(3)).to_string() == "4 1 0 0 -1"); tassert(f == fmpz_polyxx::bit_unpack(bit_pack(f, 10u), 10u)); tassert(f == fmpz_polyxx::bit_unpack_unsigned(bit_pack(f, 10u), 10u)); tassert(mul_classical(f, g) == f*g); tassert(mul_karatsuba(f, g) == f*g); tassert(mul_SS(f, g) == f*g); tassert(mul_KS(f, g) == f*g); fmpz_polyxx res; res = f*g; res.truncate(3); tassert(mullow_classical(f, g, 3) == res); tassert(mullow_karatsuba_n(f, g, 3) == res); tassert(mullow_KS(f, g, 3) == res); tassert(mullow_SS(f, g, 3) == res); tassert(mullow(f, g, 3) == res); res = f*g; res.zero_coeffs(0, 5); tassert(mulhigh_classical(f, g, 5) == res); tassert(mulhigh_karatsuba_n(f, g, 6) == res); res = mulhigh_n(f, g, 5); res.zero_coeffs(0, 5); tassert(res == mulhigh_classical(f, g, 5)); tassert(mulmid_classical(g, f).to_string() == "2 9 12"); tassert(sqr(f) == f*f); tassert(sqr_KS(f) == f*f); tassert(sqr_karatsuba(f) == f*f); tassert(sqr_classical(f) == f*f); res = sqr(f);res.truncate(4); tassert(sqrlow(f, 4) == res); tassert(sqrlow_KS(f, 4) == res); tassert(sqrlow_karatsuba_n(f, 4) == res); tassert(sqrlow_classical(f, 4) == res); tassert(pow(f, 3u) == f*f*f); tassert(pow_multinomial(f, 3u) == f*f*f); tassert(pow_binexp(f, 3u) == f*f*f); tassert(pow_addchains(f, 3u) == f*f*f); res = pow(f, 10u); res.truncate(10); tassert(pow_trunc(f, 10u, 10) == res); fmpz_polyxx binomial; binomial = "2 1 2"; tassert(pow_binomial(binomial, 3u) == binomial*binomial*binomial); fmpz_polyxx x; x = "2 0 1"; tassert(shift_left(f, 5) == f*pow(x, 5u)); tassert(shift_right(shift_left(f, 5), 5) == f); tassert(height(g) == 5); tassert(twonorm(g) == 7); tassert(resultant(f, g) == 1797); tassert(gcd(f, g).is_one()); tassert(gcd_subresultant(f, g).is_one()); tassert(gcd_heuristic(f, g).is_one()); tassert(gcd_modular(f, g).is_one()); fmpz_polyxx r, s;fmpzxx number; res = 1797; ltupleref(number, r, s) = xgcd(f, g); tassert(r*f + s*g == res && number == 1797); r = 0; s = 0; number = 0; ltupleref(number, r, s) = xgcd_modular(f, g); tassert(r*f + s*g == res && number == 1797); tassert(lcm(f, g) == f*g); tassert(content(2*g) == 2); tassert(primitive_part(2*g) == g); tassert(div_basecase(f*g, g) == f); tassert(div_divconquer(f*g, g) == f); tassert(rem_basecase(f + g, g) == f); res = 1; tassert(div_root(f*(x - res), fmpzxx(1)) == f); tassert(inv_series(xp1, 5).to_string() == "5 1 -1 1 -1 1"); tassert(inv_series(xp1, 10) == inv_series_newton(xp1, 10)); tassert(derivative(xp1).is_one()); tassert((compose(xp1, f) - f).is_one()); tassert((compose_divconquer(xp1, f) - f).is_one()); tassert((compose_horner(xp1, f) - f).is_one()); tassert(evaluate(xp1, fmpzxx(1)) == 2); tassert(evaluate_horner(xp1, fmpzxx(1)) == 2); tassert(evaluate_divconquer(xp1, fmpzxx(1)) == 2); tassert(evaluate_mod(xp1, 1u, 10u) == 2); fmpz_vecxx xs(3), ys(3); xs[0] = 0; xs[1] = 1; xs[2] = 2; ys[0] = 1; ys[1] = 2; ys[2] = 3; tassert(evaluate(xp1, xs) == ys); tassert(f(xp1) == taylor_shift(f, fmpzxx(1))); tassert(f(xp1) == taylor_shift_horner(f, fmpzxx(1))); tassert(f(xp1) == taylor_shift_divconquer(f, fmpzxx(1))); fmpz_polyxx inner;inner = "3 0 -1 5"; res = g(inner); res.truncate(10); tassert(compose_series(g, inner, 10) == res); tassert(compose_series_horner(g, inner, 10) == res); tassert(compose_series_brent_kung(g, inner, 10) == res); res = "2 0 1"; tassert(compose_series(inner, revert_series(inner, 10), 10) == res); tassert(compose_series(inner, revert_series_lagrange(inner, 10), 10) == res); tassert(compose_series(inner, revert_series_lagrange_fast(inner, 10), 10) == res); tassert(compose_series(inner, revert_series_newton(inner, 10), 10) == res); tassert(sqrt(f*f) == f); tassert(sqrt_classical(f*f) == f); assert_exception(sqrt(f*f + xp1).evaluate()); assert_exception(sqrt_classical(f*f + xp1).evaluate()); res = "5 32 0 0 0 1"; tassert(bound_roots(res) >= 2); // test immediate functions p.set_coeff(3, 1); p.truncate(2); tassert(p.is_zero()); tassert(f.max_limbs() == 1); tassert(g.max_bits() == 3); r = 0; s = 0; ltupleref(r, s) = divrem(g, f); tassert(r*f + s == g); tassert(r.to_string() == "2 4 5"); r = 0; s = 0; ltupleref(r, s) = divrem_basecase(g, f); tassert(r*f + s == g); tassert(r.to_string() == "2 4 5"); r = 0; s = 0; ltupleref(r, s) = divrem_divconquer(g, f); tassert(r*f + s == g); tassert(r.to_string() == "2 4 5"); bool does_divide; ltupleref(does_divide, res) = divides(f*g, g); tassert(does_divide && res == f); tassert(div_series(f, xp1, 10) * xp1 % pow(x, 10u) == f); f *= 2; ulong d = 0; ltupleref(r, s, d) = pseudo_divrem(g, f); tassert(r*f + s == g*fmpzxx(pow(2, d) + 0.5)); r = 0; r = 0; d = 0; ltupleref(r, s, d) = pseudo_divrem_basecase(g, f); tassert(r*f + s == g*fmpzxx(pow(2, d) + 0.5)); r = 0; r = 0; d = 0; ltupleref(r, s, d) = pseudo_divrem_divconquer(g, f); tassert(r*f + s == g*fmpzxx(pow(2, d) + 0.5)); tassert(pseudo_div(g, f).get<0>() == r); tassert(pseudo_rem(g, f).get<0>() == s); r = 0; r = 0; ltupleref(r, s) = pseudo_divrem_cohen(g, f); tassert(r*f + s == g*4); tassert(pseudo_rem_cohen(g, f).to_string() == "3 -28 -32 12"); f = "4 1 0 0 1"; slong r1, r2; f.signature(r1, r2); tassert(r1 == 1 && r2 == 1); // test static functions frandxx state; tassert(fmpz_polyxx::randtest(state, 4, 10).length() <= 4); tassert(fmpz_polyxx::randtest_unsigned(state, 4, 10).get_coeff(0) >= 0); tassert(fmpz_polyxx::randtest_not_zero(state, 4, 10).is_zero() == false); tassert(fmpz_polyxx::interpolate(xs, ys) == xp1); xs[0] = 0;xs[1] = -1; xs[2] = -1; tassert(fmpz_polyxx::product_roots(xs) == x*xp1*xp1); } void test_member_functions() { // just a sample, since they all come from macros fmpz_polyxx f, g; f = "4 2 0 0 1"; g = "5 1 2 3 4 5"; tassert(f.bit_pack(17u) == bit_pack(f, 17u)); tassert(f.divrem(g) == divrem(f, g)); tassert(f.derivative() == derivative(f)); tassert(f.bound_roots() == bound_roots(f)); tassert(f.content() == content(f)); tassert(f.pow_trunc(15u, 10) == pow_trunc(f, 15u, 10)); } void test_factoring() { fmpz_polyxx f, g; // two irreducible polynomials f = "4 1 17 0 1"; g = "6 2 0 2 0 0 1"; // TODO are these deterministic? fmpz_poly_factorxx f1, f2; f1.insert(f, 1); f2.insert(g, 2); f1.content() = 7; f1.concat(f2); tassert(f1 == factor_zassenhaus(7*f*g*g)); f1.realloc(0); f1.insert(f, 1); f1.insert(g, 2); f1.content() = 1; tassert(f1 == factor_squarefree(f*g*g)); // TODO test set_factor_zassenhaus_recombination if(0) print(f1); // make sure this compiles } void test_hensel() { mp_limb_t pl = 1031; frandxx state; nmod_polyxx gl(nmod_polyxx::randtest_irreducible(pl, state, 5).make_monic()); nmod_polyxx hl(nmod_polyxx::randtest_irreducible(pl, state, 6).make_monic()); while(gl.length() != 5) gl = nmod_polyxx::randtest_irreducible(pl, state, 5).make_monic(); while(hl.length() != 5) hl = nmod_polyxx::randtest_irreducible(pl, state, 5).make_monic(); nmod_polyxx al(pl), bl(pl); ltupleref(_, al, bl) = xgcd(gl, hl); tassert((al*gl + bl*hl).is_one()); fmpz_polyxx f = fmpz_polyxx::lift(gl*hl); fmpz_polyxx g = fmpz_polyxx::lift(gl); fmpz_polyxx h = fmpz_polyxx::lift(hl); fmpz_polyxx a = fmpz_polyxx::lift(al); fmpz_polyxx b = fmpz_polyxx::lift(bl); fmpz_polyxx G, H, A, B; fmpzxx p(pl), p1(1031); tassert(((f - g*h) % p).is_zero()); //ltupleref(G, H, A, B) = hensel_lift(f, g, h, a, b, p, p1); fmpz_poly_hensel_lift(G._poly(), H._poly(), A._poly(), B._poly(), f._poly(), g._poly(), h._poly(), a._poly(), b._poly(), p._fmpz(), p1._fmpz()); tassert(((f - G*H) % (p1*p)).is_zero()); tassert(((A*G + B*H) % (p1*p)).is_one()); tassert(ltupleref(G, H) == hensel_lift_without_inverse(f, g, h, a, b, p, p1)); tassert(ltupleref(A, B) == hensel_lift_only_inverse(G, H, a, b, p, p1)); nmod_poly_factorxx local_fac = factor(gl*hl); fmpz_poly_factorxx lifted_fac = hensel_lift_once(f, local_fac, 3); tassert(lifted_fac.size() == 2 && lifted_fac.exp(0) == 1 && lifted_fac.exp(1) == 1); tassert(((lifted_fac.p(0)*lifted_fac.p(1) - f) % p.pow(3u)).is_zero()); } void test_printing() { frandxx state; fmpz_polyxx f = fmpz_polyxx::randtest(state, 4, 10); test_print_read(f); test_print_read_pretty(f); } void test_unified_access() { fmpz_polyxx a = fmpz_polyxx::from_ground(1); const fmpz_polyxx& b = a; tassert(b.lead() == 1 && b.coeff(0) == 1); } int main() { std::cout << "fmpz_polyxx...."; test_init(); test_manipulation(); test_assignment(); test_conversion(); test_arithmetic(); test_functions(); test_member_functions(); test_extras(); test_factoring(); test_hensel(); test_printing(); test_unified_access(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-fmpzxx.cpp000066400000000000000000000404751414523752600177220ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpzxx.h" #include "flintxx/test/helpers.h" #if !HAVE_FAST_COMPILER #warning "Some tests are disabled because your compiler is slow." #endif using namespace flint; void test_printing() { fmpzxx a(31); tassert(a.to_string() == "31"); tassert(a.to_string(2) == "11111"); std::ostringstream oss; oss << a << '\n' << std::oct << a << '\n' << std::hex << a << '\n' << std::dec << a; tassert(oss.str() == "31\n37\n1f\n31"); fmpzxx b(-15); tassert((a + b).to_string() == "16"); char astr[] = "15"; tassert(fmpzxx(astr) == 15); } void test_order() { fmpzxx a(0); fmpzxx b(1); fmpzxx c(0); fmpzxx d(-1); #define TO(xzero, zero, one, mone) \ tassert(xzero == zero); \ tassert(xzero != one); \ tassert(!(xzero == one)); \ tassert(!(xzero != zero)); \ tassert(xzero < one); \ tassert(xzero <= one); \ tassert(xzero <= zero); \ tassert(!(xzero < zero)); \ tassert(!(xzero <= mone)); \ tassert(xzero > mone); \ tassert(xzero >= mone); \ tassert(xzero >= zero); \ tassert(!(xzero > zero)); \ tassert(!(xzero >= one)); TO(a, c, b, d); TO(a, 0, 1, -1); TO(a, 0u, 1u, -1); TO(a, (signed short)(0), (signed short)(1), (signed short)(-1)); TO(a, (unsigned short)(0), (unsigned short)(1), -1); TO(a, WORD(0), WORD(1), WORD(-1)); TO(0, c, b, d); TO(0u, c, b, d); TO(WORD(0), c, b, d); TO((short)0, c, b, d); TO((unsigned short)0, c, b, d); } void test_conversion() { fmpzxx a(4); tassert(a.to() == 4); tassert(a.to() == 4); tassert(a.to() == 4.0); // NB: to_string is tested in test_printing } void test_initialisation_assignment() { fmpzxx a(4), b(WORD(4)), c(4u), d("4"); fmpzxx e(a); fmpzxx f, g, h, i; f = 4; g = WORD(4); h = 4u; i = fmpzxx("4"); tassert(a == b && a == c&& a == d && a == e && a == f && a == g && a == h && a == i); // test deep copying of fmpzxx with more than one digit a = fmpzxx("100000000000000000000"); b = a; tassert(a._fmpz()[0] != b._fmpz()[0]); fmpzxx j(a); tassert(a._fmpz()[0] != j._fmpz()[0]); tassert(a == b && a == j); // just here to test our assumptions on data format tassert(c._fmpz()[0] == d._fmpz()[0]); // some more exotic "assignments" a.set_ui_smod(15, 16); tassert(a == -1); a.set_uiui(27, 15); tassert(a % (fmpzxx(1) << FLINT_BITS) == 15); tassert((a >> FLINT_BITS) == 27); b.neg_uiui(27, 15); tassert(b == -a); } void test_arithmetic() { #define TAC(seven, three) \ tassert(seven + three == 10); \ tassert(seven * three == 21); #define TA(seven, three) \ TAC(seven, three); \ tassert(seven - three == 4); \ tassert(seven / three == 2); \ tassert(seven % three == 1) TA(fmpzxx(7), fmpzxx(3)); TA(fmpzxx(7), 3u); TAC(UWORD(7), fmpzxx(3)); // test signed builtins tassert(-7 + fmpzxx(3) == -fmpzxx(4)); tassert(fmpzxx(3) + 7 == fmpzxx(10)); tassert(7 + fmpzxx(3) == fmpzxx(10)); tassert(fmpzxx(3) + (-7) == -fmpzxx(4)); tassert(fmpzxx(3) - 7 == -4); tassert(-7 * fmpzxx(3) == -21); tassert(fmpzxx(7) * (WORD(-3)) == -21); tassert(fmpzxx(21) / -3 == -7); // test composite arithmetic fmpzxx a(3), b(7); tassert(3*(a + b) - (b + (a - 4u)) + ((-(a - b)) % (b / 2)) == 25); // test unary minus tassert(-a == -3); // test assignment arithmetic #define TAA(op, res) \ { \ fmpzxx tmp1(10), tmp2(10), tmp3(10); \ fmpzxx three(3); \ tmp1 op three; \ tmp2 op 3u; \ tmp3 op three*1; \ tassert(tmp1 == res); \ tassert(tmp2 == res); \ tassert(tmp3 == res); \ } TAA(+=, 13); TAA(*=, 30); TAA(/=, 3); TAA(%=, 1); // shifting tassert((fmpzxx(1) << 10) == 1024); tassert((fmpzxx(1024) >> 9) == 2); // binary logic tassert((fmpzxx(1) | fmpzxx(2)) == 3); tassert((fmpzxx(3) & fmpzxx(5)) == 1); tassert((fmpzxx(17) ^ fmpzxx(23)) == (UWORD(17) ^ UWORD(23))); tassert(~fmpzxx(17) == ~WORD(17)); } void test_functions() { fmpzxx a(2); fmpzxx b(16); fmpzxx_srcref c(a); tassert(sgn(a) == 1); tassert(size(b) == 1); tassert(val2(b) == 4); tassert(bits(b) == 5); tassert(sizeinbase(b, 2) == 5); tassert(b.tstbit(0) == false); tassert(pow(a, 4u) == 16); tassert(root(b, 4) == 2); tassert(root(b, (unsigned short)4) == 2); tassert(sqrt(b) == 4); tassert(sqrt(a) == 1); tassert(rfac(a, 3u) == 2*3*4); tassert(a + fac(4u) == 2 + 4*3*2); tassert(fib(4u) == 3); tassert(bin(4u, 2u) == 6); tassert(abs(a) == a); tassert(gcd(a, b) == 2); tassert(lcm(a, b) == 16); fmpzxx p(31); tassert((invmod(b % p, p) * b) % p == 1); tassert((negmod(b % p, p) + b) % p == 0); fmpzxx mb(-b); fmpzxx three(3); tassert(cdiv_q(mb, three) == -5); tassert(fdiv_r(mb, three) == 2); tassert(tdiv_q(mb, three) == -5); tassert(cdiv_q(mb, 3) == -5); tassert(tdiv_q(mb, 3) == -5); tassert(cdiv_q(mb, 3u) == -5); tassert(tdiv_q(mb, 3u) == -5); tassert(tdiv_q_2exp(mb, 2u) == -4); tassert(fdiv_r_2exp(mb, 2u) == 0); tassert(divexact(b, a) == 8 && divexact(b, 2) == 8 && divexact(b, 2u) == 8); // check a composite expression tassert(2u + sqrt(a + a) == 4); // check immediate functions tassert(divisible(b, a + a)); tassert(divisible(b, a + a + 2u) == false); tassert(divisible(a + a, (unsigned short)2)); tassert(divisible(-a + b, 3) == false); tassert(divisible(c, a) == true); fmpzxx f(15); tassert(clog(f, a) == 4 && clog(f, 2u) == 4); tassert(flog(f, a) == 3 && flog(f, 2u) == 3); tassert(2.7 < dlog(f) && dlog(f) < 2.8); tassert(mul2(a, 15u, 16u) == a*15*16); tassert(divexact2(b, 2u, 2u) == 4); tassert(powm(a, 4u, fmpzxx(5)) == 1); tassert(powm(a, fmpzxx(4), fmpzxx(5)) == 1); tassert(mul_tdiv_q_2exp(a, fmpzxx(-3), 2u) == -1); tassert(mul_tdiv_q_2exp(a, -3, 2u) == -1); fmpzxx q(1), rem(2); tassert(fdiv_qr(b, a) == ltuple(8, 0)); tassert(tdiv_qr(b, a) == ltuple(8, 0)); bool worked; ltupleref(worked, q) = sqrtmod(fmpzxx(4), fmpzxx(5)); tassert(worked && (q == 2 || q == 3)); tassert(sqrtrem(fmpzxx(5)) == ltuple(2, 1)); // TODO gcdinv, xgcd // check member functions slong exp = 0; double d = fmpzxx(3).get_d_2exp(exp); double r = d * (WORD(1) << exp); tassert(r >= 2.9 && r <= 3.1); fmpzxx one(1), mone(-1), zero(0), two(2); tassert(one.is_one() && one.is_pm1() && one.is_odd() && !one.is_even() && !one.is_zero()); tassert(!zero.is_one() && !zero.is_pm1() && zero.is_zero()); tassert(mone.is_pm1()); tassert(two.is_even() && !two.is_odd()); tassert(one.is_square() && !two.is_square()); tassert(jacobi(b, p) == 1); tassert(p.is_probabprime()); tassert(p.is_prime_pseudosquare()); tassert((3*b).remove(a) == ltuple(4, 3)); a = 17; a.clrbit(0); tassert(a == 16); a.combit(1); tassert(a == 18); tassert(a.popcnt() == 2); frandxx rand; mp_bitcnt_t bits = 123; // some extra space in two words std::vector arr(bits / FLINT_BITS + 2); fmpzxx tostore = fmpzxx::randtest_unsigned(rand, bits); bit_pack(arr, bits, tostore); tassert(tostore == fmpzxx::bit_unpack_unsigned(arr, bits)); tassert(tostore == fmpzxx::bit_unpack(arr, bits).get<1>()); } void test_member_functions() { // NB: only a sample, since these are done by macros anyway fmpzxx a(2), b(3); tassert((a*b).divisible(b)); tassert((a*b).divisible(3)); tassert(b.flog(3u) == 1); tassert(a.clog(a) == 1); tassert(a.rfac(3u) == rfac(a, 3u)); tassert(a.gcd(b) == gcd(a, b)); tassert(a.lcm(b) == lcm(a, b)); tassert(a.cdiv_q(b) == cdiv_q(a, b)); tassert(a.mul2(3u, 4u) == mul2(a, 3u, 4u)); tassert(a.sqrtmod(b) == sqrtmod(a, b)); tassert(b.sqrt() == sqrt(b)); } template void assert_is_fmpzxx(const T&) { tassert(traits::is_fmpzxx::val); } struct newtype {typedef void data_ref_t; typedef void data_srcref_t;}; void test_traits() { tassert(traits::is_fmpzxx::val == true); tassert(traits::is_fmpzxx::val == false); assert_is_fmpzxx(fmpzxx(1) + fmpzxx(2)); // the following does not even compile: //tassert((traits::is_fmpzxx >::val == false)); } template unsigned count_temporaries2(const T&) { return T::ev_traits_t::temp_rule_t::temporaries_t::len // this term is always zero, but causes compiler error // if we are not actually in the ternary case + T::ev_traits_t::temp_rule_t::TERNARY_OP_MARKER; } void test_temporaries() { fmpzxx a, b, c; tassert(count_temporaries(a + b) == 0); tassert(count_temporaries(a + b + c + a + b + c) == 1); tassert(count_temporaries(((a / c) + (b % a)) / ((b + c) + (c / a))) == 3); tassert(count_temporaries((a/b) + (a/c) + (b/c) + (c/b)) == 2); tassert(count_temporaries2((a*b) + (a*c) + (b*c) + (c*b)) == 1); // test a bug in evaluate_2 (if addmul is used on the right, this can // be done with two temporaries, else need three) tassert(count_temporaries(((a+b)+(a+c)) + (((a+c) + a*c))) == 2); } void test_ternary() { fmpzxx b(2), c(3), d(4); #define T0 fac(4u) #define T1 (b + b + b) #define T2 (T1 + T1) #define T3 (T2 + T2) #define T4 (T3 + T3) // The inner struct is a trickery to get gcc to free some of its data // structures. It reduces the resident set by 50%, and compile time by 75%. #define TT3(m1, m2, m3, ntemps) \ do{ struct inner { static void doit() { \ fmpzxx b(2), c(3), d(4); \ tassert(count_temporaries2(m1 + m2*m3) == ntemps); \ tassert(b + (m1 + m2*m3) == 2 + m1.to() + m2.to()*m3.to()); \ tassert(count_temporaries2(m1 + m3*m2) == ntemps); \ tassert(b + (m1 + m3*m2) == 2 + m1.to() + m2.to()*m3.to()); \ \ tassert(count_temporaries2(m2*m3 + m1) == ntemps); \ tassert(b + (m2*m3 + m1) == 2 + m1.to() + m2.to()*m3.to()); \ tassert(count_temporaries2(m1 + m3*m2) == ntemps); \ tassert(b + (m3*m2 + m1) == 2 + m1.to() + m2.to()*m3.to()); \ \ tassert(count_temporaries2(m1 - m2*m3) == ntemps); \ tassert(b + (m1 - m2*m3) == 2 + m1.to() - m2.to()*m3.to()); \ tassert(count_temporaries2(m1 - m3*m2) == ntemps); \ tassert(b + (m1 - m3*m2) == 2 + m1.to() - m2.to()*m3.to()); \ } }; inner::doit();} while(0) #define TT(m1, m2, ntemps) TT3(m1, m2, d, ntemps) TT(T0, c, 1); TT(T1, c, 1); TT(T2, c, 2); TT(T3, c, 3); TT(T0, T0, 2); TT(T0, T1, 2); TT(T0, T2, 2); TT(T0, T3, 3); #if HAVE_FAST_COMPILER TT(T1, T0, 2); TT(T1, T1, 2); TT(T1, T2, 2); TT(T1, T3, 3); TT(T2, T0, 2); TT(T2, T1, 2); TT(T2, T2, 3); TT(T2, T3, 3); TT(T3, T0, 3); TT(T3, T1, 3); TT(T3, T2, 3); TT(T3, T3, 4); // NB: TT3 is symmetric in m2 and m3 #define TT6(m1, m2, m3, ntemps) \ TT3(m1, m2, m3, ntemps); \ TT3(m2, m1, m3, ntemps); \ TT3(m3, m1, m2, ntemps); TT6(fac(2u), fac(3u), fac(4u), 3); TT6(T1, T2, T3, 3); TT6(T1, T2, T4, 4); TT6(T1, (d+d+d) /* T1' */, T4, 4); TT6(T0, fac(2u), T2, 3); TT6(T0, T1, (d+d+d), 3); TT6(T1, T3, (T2 + T1) /* T3' */, 3); #endif } void test_ternary_assigments() { fmpzxx a(2), b(3), c(4); tassert((a += b*c) == 14); tassert(a == 14); tassert((a -= b*c) == 2); tassert(a == 2); tassert((a += (b+b)*c) == 26); tassert((a -= (b+b)*c) == 2); tassert((a += c*(b+b)) == 26); tassert((a -= c*(b+b)) == 2); tassert((a += (b+b)*(c+c)) == 50); tassert((a -= (b+b)*(c+c)) == 2); // Make sure that the general rule kicks tassert((a += 3*c) == 14); tassert((a -= 3*c) == 2); } bool try_implicit_conversion(fmpzxx_ref, const fmpzxx_ref&, fmpzxx_srcref, const fmpzxx_srcref&, fmpzxx_srcref, const fmpzxx_srcref&) { return true; } void test_references() { fmpzxx a(2), b(3); fmpzxx_ref ar(a); fmpzxx_srcref acr(a), bcr(b); tassert(ar == 2 && bcr == 3 && ar == acr && ar == a); // test assignments fmpzxx d(ar); a = 4; tassert(ar == 4 && acr == 4 && d == 2); ar = 2; tassert(a == 2); // test some arithmetic tassert(a + bcr == 5); tassert(acr + bcr == 5); tassert(ar + 3u == 5); tassert(a < bcr && ar < b && acr < bcr); tassert(rfac(acr, 1u) == 2); ar = bin(4u, 2u); tassert(acr == 6); tassert(acr.to() == WORD(6)); tassert(ar.to_string() == "6"); ar += b; ar += bcr; tassert(a == 12); // test conversion of reference types tassert(try_implicit_conversion(a, a, a, a, ar, ar)); tassert((!traits::_is_convertible::val)); tassert((!traits::_is_convertible::val)); tassert((!traits::_is_convertible::val)); // test creation from C types fmpzxx_ref ar2 = fmpzxx_ref::make(a._fmpz()); fmpzxx_srcref acr2 = fmpzxx_srcref::make(acr._fmpz()); a = 7; tassert(ar2 == 7 && acr2 == 7); // test swapping a = 2; b = 3; swap(b, ar); tassert(a == 3 && b == 2); // make sure ADL is preferred over the general version in std using namespace std; swap(b, b); } void test_randomisation() { frandxx rand; tassert(abs(fmpzxx::randbits(rand, 5)) <= 31); tassert(abs(fmpzxx::randbits(rand, 5)) >= 16); tassert(abs(fmpzxx::randtest(rand, 5)) <= 31); tassert(fmpzxx::randtest_unsigned(rand, 5) <= 31); tassert(fmpzxx::randtest_unsigned(rand, 5) >= 0); tassert(fmpzxx::randtest_not_zero(rand, 5) != 0); fmpzxx thirty(30); tassert(fmpzxx::randm(rand, thirty) >= 0); tassert(fmpzxx::randm(rand, thirty) <= 29); tassert(fmpzxx::randtest_mod(rand, thirty) >= 0); tassert(fmpzxx::randtest_mod(rand, thirty) <= 29); tassert(fmpzxx::randtest_mod_signed(rand, thirty) > -15); tassert(fmpzxx::randtest_mod_signed(rand, thirty) <= 15); } void test_factoring() { fmpz_factorxx f;f = factor(-2*3*5); tassert(f.size() == 3); tassert(f.sign() == -1); tassert(f.p(0) == 2 && f.exp(0) == 1); tassert(f.p(1) == 3 && f.exp(1) == 1); tassert(f.p(2) == 5 && f.exp(2) == 1); tassert(f == factor(fmpzxx(-2*3*5))); tassert(f == fmpz_factorxx(f)); tassert(f == factor_trial_range(fmpzxx(-2*3*5), 0u, 2u).get<1>()); tassert(factor_trial_range(fmpzxx(-2*3*5), 0u, 2u).get<0>()); tassert(f.expand() == -2*3*5); tassert(f.expand() == f.expand_iterative()); tassert(f.expand() == f.expand_multiexp()); if(0) print(f); // make sure this compiles } void test_crt() { frandxx rand; fmpzxx x = fmpzxx::randtest_unsigned(rand, 25); std::vector primes; primes.push_back(1031); primes.push_back(1033); primes.push_back(1039); fmpz_combxx comb(primes); std::vector residues(primes.size()); multi_mod(residues, x, comb); fmpzxx prod(1); fmpzxx res; for(unsigned i = 0;i < primes.size();++i) { tassert(residues[i] == x % primes[i]); res = res.CRT(prod, residues[i], primes[i], false); prod *= primes[i]; } tassert(res == x); res = multi_CRT(residues, comb, false); tassert(res == x); } int main() { std::cout << "fmpzxx...."; test_printing(); test_order(); test_conversion(); test_initialisation_assignment(); test_arithmetic(); test_functions(); test_member_functions(); test_traits(); test_temporaries(); test_ternary(); test_ternary_assigments(); test_references(); test_randomisation(); test_factoring(); test_crt(); test_print_read(fmpzxx(-17)); // TODO test that certain things *don't* compile? // TODO test enable_all_fmpzxx std::cout << "PASS" << std::endl; } flint2-2.8.4/flintxx/test/t-forwarding.cpp000066400000000000000000000055301414523752600205210ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // XXX NOTE: the forwarding code was never completed, and neither was this // test file. #include #include #include "flintxx/forwarding.h" #include "flintxx/test/myint.h" #include "flintxx/test/helpers.h" using namespace flint; template class forwarded_expression : public expression, Operation, Data> { public: forwarded_expression() {}; template explicit forwarded_expression(const T& t) : expression, Operation, Data>(t) {} template forwarded_expression& operator=(const T& t) { this->set(t); return *this; } protected: explicit forwarded_expression(const Data& d) : expression, Operation, Data>(d) {} template friend class ::flint::expression; }; struct hide_myint { myint i; template hide_myint(const T& t) : i(t) {} hide_myint() {} }; typedef forwarded_expression fwint; namespace flint { namespace forwarding { template<> struct enable : mp::true_ { typedef myint underlying_t; static const myint& get_underlying(const fwint& fwd) { return fwd._data().i; } static myint& get_underlying(fwint& fwd) { return fwd._data().i; } }; } } void test_print() { fwint fwd(4); std::ostringstream oss; oss << fwd; tassert(oss.str() == "4"); } void test_assignment() { fwint f1, f2(4); f1 = WORD(3); // TODO understand why "3" seems to lead to circular dependency tassert(f1 == 3); f1 = f2; tassert(f1 == 4); } void test_equals() { fwint f1(4), f2(5); myint m1(4); tassert(f1 == f1); tassert(f1 != f2); tassert(f1 == 4); tassert(5 != f1); tassert(f1 == m1); tassert(m1 != f2); } void test_conversion() { fwint a(4); tassert(typed_equals(a.to(), 4)); } void test_evaluation() { fwint a(4); myint b(5); tassert(typed_equals((a + a).evaluate(), myint(8))); tassert(a + b == 9); tassert(a + 6 == 10); tassert((a + 6) + b == 15); } int main() { std::cout << "forwarding...."; test_print(); test_assignment(); // TODO test cmp test_equals(); test_conversion(); test_evaluation(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-ltuple.cpp000066400000000000000000000111371414523752600176640ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flintxx/ltuple.h" #include "fmpzxx.h" #include "flintxx/test/helpers.h" #include "flintxx/test/myint.h" using namespace flint; void test_traits() { tassert(!traits::is_ltuple_expr::val); tassert(!traits::is_ltuple_expr::val); } namespace flint { typedef make_ltuple::type>::type fmpzxxint_pair; typedef make_ltuple::type>::type mylongint_pair; FLINT_DEFINE_BINOP(make_lazy_test) namespace rules { FLINT_DEFINE_BINARY_EXPR_COND2(make_lazy_test_op, fmpzxxint_pair, FMPZXX_COND_S, traits::is_signed_integer, to.template get<0>() = e1;to.template get<1>() = e2) FLINT_DEFINE_BINARY_EXPR2(make_lazy_test_op, mylongint_pair, mylong, int, to.template get<0>() = e1;to.template get<1>() = e2) } } void test_equals() { typedef mp::make_tuple maker; typedef mp::make_tuple refmaker; typedef mp::make_tuple srcrefmaker; typedef make_ltuple lmaker; typedef make_ltuple lrefmaker; typedef make_ltuple lsrcrefmaker; fmpzxx f; int a = 12345; lmaker::type ltuple(detail::INSTANTIATE_FROM_TUPLE(), maker::make(fmpzxx(1), 2)); lrefmaker::ref_type lref(detail::INSTANTIATE_FROM_TUPLE(), refmaker::make(f, a)); lsrcrefmaker::srcref_type lsrcref(detail::INSTANTIATE_FROM_TUPLE(), srcrefmaker::make( ltuple._data().inner.head, ltuple._data().inner.tail.head)); tassert(ltuple == ltuple); tassert(ltuple != lref); tassert(ltuple == lsrcref); tassert(lref != lsrcref); f = 1; a = 2; tassert(ltuple == lref); tassert(lref == lsrcref); tassert(ltuple == make_lazy_test(fmpzxx(1), 2)); } void test_assignment() { typedef mp::make_tuple maker; typedef mp::make_tuple refmaker; typedef mp::make_tuple srcrefmaker; typedef make_ltuple lmaker; fmpzxx f; int a; lmaker::type ltuple(detail::INSTANTIATE_FROM_TUPLE(), maker::make(fmpzxx(1), 2)); lmaker::ref_type lref(detail::INSTANTIATE_FROM_TUPLE(), refmaker::make(f, a)); lref = ltuple; tassert(f == 1 && a == 2); f = 0; a = 0; lmaker::srcref_type lsrcref(detail::INSTANTIATE_FROM_TUPLE(), srcrefmaker::make( ltuple._data().inner.head, ltuple._data().inner.tail.head)); ltuple._data().inner.head = 17; lref = lsrcref; tassert(f == 17 && a == 2); f = 3; a = 4; ltuple = lref; tassert(ltuple._data().inner.head == 3 && ltuple._data().inner.tail.head == 4); lref = make_lazy_test(fmpzxx(17), 18); tassert(f == 17 && a == 18); } void test_ltupleref() { fmpzxx a, b; int c; ltupleref(c) = ltuple(2); tassert(c == 2); ltupleref(a, c) = ltuple(fmpzxx(3), 4); tassert(a == 3 && c == 4); // test assignment with type conversion ltupleref(a, b, c) = ltuple(1, 2, 4u); tassert(a == 1 && b == 2 && c == 4); // test assignment with c-style references ltuple(fmpzxx_ref(a)) = ltuple(b); tassert(a == 2); } template bool is_lazy(const T&) { return traits::is_lazy_expr::val; } void test_get() { fmpzxx a(1); int b = 2; tassert(ltuple(a, b).get<0>() == a && ltuple(a, b).get<1>() == b); ltupleref(a, b).get<0>() = 17; ltupleref(a, b).get<1>() = 15; tassert(a == 17 && b == 15); tassert(make_lazy_test(a, 3).get<0>() == 17); tassert(is_lazy(make_lazy_test(a, 3).get<0>())); tassert(make_lazy_test(a, 3).get<1>() == 3); } void test_placeholder() { fmpzxx a; int b; ltupleref(a, _) = make_lazy_test(fmpzxx(17), 5); tassert(a == 17); ltupleref(_, b) = make_lazy_test(fmpzxx(18), 6); tassert(b == 6 && a == 17); ltupleref(_, _) = make_lazy_test(fmpzxx(1), 2); tassert(b == 6 && a == 17); } void test_create_temporaries() { tassert(make_lazy_test(mylong(1), 2).get<0>() == mylong(1)); } int main() { std::cout << "ltuple...."; test_traits(); test_equals(); test_assignment(); test_ltupleref(); test_get(); test_placeholder(); test_create_temporaries(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-mp.cpp000066400000000000000000000063111414523752600167710ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flintxx/test/helpers.h" #include "flintxx/mp.h" using namespace flint; using namespace mp; void test_equal_types() { tassert((equal_types::val)); tassert((!equal_types::val)); } void test_logic() { tassert(not_::val == false); tassert(not_::val == true); tassert((and_::val == true)); tassert((and_::val == false)); tassert((and_::val == false)); tassert((and_v::val == true)); tassert((and_v::val == false)); tassert((and_v::val == false)); tassert((or_::val == true)); tassert((or_::val == true)); tassert((or_::val == false)); tassert((and_::val == true)); tassert((and_::val == false)); tassert((and_::val == false)); tassert((and_::val == false)); } template typename enable_if, int>::type test_enable_if_1(T) { return 0; } template typename disable_if, int>::type test_enable_if_1(T) { return 1; } template int test_enable_if_2(T, typename enable_if >::type* = 0) { return 0; } template int test_enable_if_2(T, typename disable_if >::type* = 0) { return 1; } void test_enable_if() { tassert(test_enable_if_1(int(1)) == 0); tassert(test_enable_if_1(unsigned(1)) == 1); tassert(test_enable_if_2(int(1)) == 0); tassert(test_enable_if_2(unsigned(1)) == 1); } void test_if() { tassert((equal_types::type, int>::val)); tassert((equal_types::type, slong>::val)); typedef mp::select s1; tassert((equal_types::val)); typedef mp::select s2; tassert((equal_types::val)); typedef mp::select s3; tassert((equal_types::val)); typedef mp::select s4; tassert((equal_types::val)); typedef mp::select s5; tassert((equal_types::val)); typedef mp::select s6; tassert((equal_types::val)); typedef mp::select s7; tassert((equal_types::val)); } int main() { std::cout << "mp...."; test_equal_types(); test_logic(); test_enable_if(); test_if(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-nmod_matxx.cpp000066400000000000000000000223401414523752600205330ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_matxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_init() { mp_limb_t M = 1039; nmod_matxx A(3, 4, M); nmodxx_ctx_srcref ctx = A.estimate_ctx(); tassert(ctx.n() == M); tassert((A + A).modulus() == M); tassert(A.rows() == 3 && A.cols() == 4); tassert(A.at(0, 0) == nmodxx::red(0, ctx)); A.at(0, 0) = nmodxx::red(1, ctx); nmod_matxx B(A); tassert(A == B); tassert(B.rows() == 3 && B.cols() == 4); tassert(B.at(0, 0) == nmodxx::red(1, ctx)); B.at(0, 0) = nmodxx::red(0, ctx); tassert(A.at(0, 0) == nmodxx::red(1, ctx)); tassert(A != B); B = A; tassert(A == B); A.set_zero(); tassert(A.is_zero() && A == nmod_matxx::zero(A.rows(), A.cols(), A.modulus())); } template bool has_explicit_temporaries(const Expr&) { return Expr::ev_traits_t::rule_t::temporaries_t::len != 0; } void test_arithmetic() { mp_limb_t M = 1039; nmod_matxx A(10, 10, M); nmod_matxx v(10, 1, M); nmodxx_ctx_srcref ctx = A.estimate_ctx(); for(unsigned i = 0;i < 10;++i) v.at(i, 0) = nmodxx::red(i, ctx); nmodxx two = nmodxx::red(2, ctx); tassert(transpose(v).rows() == 1); tassert(v.transpose().cols() == 10); tassert((two*v).rows() == 10); tassert((v*two).rows() == 10); tassert((v*transpose(v)).rows() == 10 && (v*transpose(v)).cols() == 10); tassert(!has_explicit_temporaries(trace(transpose(v)))); tassert(!has_explicit_temporaries(trace(A + v*transpose(v)))); tassert(!has_explicit_temporaries(A + v*transpose(v))); tassert(!has_explicit_temporaries(trace((v*transpose(v) + A)))); tassert(!has_explicit_temporaries(trace(v*transpose(v) + v*transpose(v)))); tassert(!has_explicit_temporaries(v*transpose(v) + v*transpose(v))); tassert(trace(transpose(v)) == nmodxx::red(0, ctx)); tassert(trace(A + v*transpose(v)) == nmodxx::red(285, ctx)); tassert(trace(v*transpose(v) + A) == nmodxx::red(285, ctx)); tassert(trace(v*transpose(v) + v*transpose(v)) == nmodxx::red(2*285, ctx)); tassert(trace((A+A)*(nmodxx::red(1, ctx) + nmodxx::red(1, ctx))) == nmodxx::red(0, ctx)); for(unsigned i = 0;i < 10; ++i) for(unsigned j = 0; j < 10; ++j) A.at(i, j) = nmodxx::red(i*j, ctx); tassert(A == v*transpose(v)); tassert(A != transpose(v)*v); A.at(0, 0) = nmodxx::red(15, ctx); tassert(A != v*transpose(v)); A.at(0, 0) = nmodxx::red(0, ctx); for(unsigned i = 0;i < 10; ++i) for(unsigned j = 0; j < 10; ++j) A.at(i, j) *= two; tassert(A == v*transpose(v) + v*transpose(v)); tassert(A - v*transpose(v) == v*transpose(v)); tassert(((-A) + A).is_zero()); tassert((A + A).at(0, 0) == A.at(0, 0) + A.at(0, 0)); } void test_functions() { mp_limb_t M = 1031; nmod_matxx A(2, 3, M), B(2, 2, M), empty(0, 15, M); nmodxx_ctx_srcref ctx = A.estimate_ctx(); B.at(0, 0) = nmodxx::red(1, ctx); tassert(A.is_zero() && !A.is_empty() && !A.is_square()); tassert(!B.is_zero() == B.is_square()); tassert(empty.is_zero() && empty.is_empty()); // transpose tested in arithmetic // mul tested in arithmetic // trace tested in arithmetic frandxx rand; A.set_randtest(rand); B.set_randtest(rand); tassert(B*A == B.mul_classical(A)); tassert(B*A == B.mul_strassen(A)); B.set_randrank(rand, 1); tassert(B.det() == nmodxx::red(0, ctx)); B.set_randrank(rand, 2); tassert(B.det() != nmodxx::red(0, ctx)); B.set_randrank(rand, 1); assert_exception(B.inv().evaluate()); B.set_randrank(rand, 2); nmod_matxx eye(2, 2, M); eye.at(0, 0) = nmodxx::red(1, ctx);eye.at(1, 1) = nmodxx::red(1, ctx); tassert(B.inv() * B == eye); A.set_randrank(rand, 2); tassert(rank(A) == 2); B.set_randtril(rand, false); tassert(B*B.solve_tril(A, false) == A); tassert(B.solve_tril_classical(A, false) == B.solve_tril(A, false)); tassert(B.solve_tril_recursive(A, false) == B.solve_tril(A, false)); B.set_randtriu(rand, true); tassert(B*B.solve_triu(A, true) == A); tassert(B.solve_triu_classical(A, true) == B.solve_triu(A, true)); tassert(B.solve_triu_recursive(A, true) == B.solve_triu(A, true)); B.set_randrank(rand, 2); tassert(B*B.solve(A) == A); nmod_vecxx X(2, ctx); X[0] = nmodxx::red(1, ctx); X[1] = nmodxx::red(2, ctx); X = B.solve(X); tassert(B.at(0, 0)*X[0] + B.at(0, 1) * X[1] == nmodxx::red(1, ctx)); tassert(B.at(1, 0)*X[0] + B.at(1, 1) * X[1] == nmodxx::red(2, ctx)); B.set_randrank(rand, 1); assert_exception(B.solve(A).evaluate()); assert_exception(B.solve(X).evaluate()); slong nullity;nmod_matxx C(3, 3, M); tassert(nullspace(A).get<1>().rows() == 3); tassert(nullspace(A).get<1>().cols() == 3); ltupleref(nullity, C) = nullspace(A); tassert(nullity == 3 - rank(A)); tassert(C.rank() == nullity); tassert((A*C).is_zero()); A.set_rref(); tassert(A.at(1, 0) == nmodxx::red(0, ctx)); } void test_randomisation() { frandxx rand; mp_limb_t M = 1031; nmod_matxx A(2, 2, M); nmodxx_ctx_srcref ctx = A.estimate_ctx(); // not really anything we can test about these ... // just make sure the call works A.set_randtest(rand); A.set_randfull(rand); nmod_vecxx v(2, ctx);v[0] = nmodxx::red(5, ctx);v[1] = nmodxx::red(7, ctx); A.set_randpermdiag(rand, v); tassert(A.at(0, 0) + A.at(0, 1) + A.at(1, 0) + A.at(1, 1) == nmodxx::red(5 + 7, ctx)); A.set_randrank(rand, 1); tassert(A.rank() == 1); A.apply_randops(rand, 17); tassert(A.rank() == 1); A.set_randtril(rand, true); tassert(A.at(0, 0) == nmodxx::red(1, ctx)); tassert(A.at(1, 1) == nmodxx::red(1, ctx)); tassert(A.at(0, 1) == nmodxx::red(0, ctx)); A.set_randtriu(rand, false); tassert(A.at(1, 0) == nmodxx::red(0, ctx)); frandxx rand2, rand3; nmod_matxx B(2, 2, M); B.set_randtest(rand2); tassert(B == nmod_matxx::randtest(2, 2, M, rand3)); B.set_randfull(rand2); tassert(B == nmod_matxx::randfull(2, 2, M, rand3)); B.set_randrank(rand2, 1); tassert(B == nmod_matxx::randrank(2, 2, M, rand3, 1)); B.set_randtril(rand2, false); tassert(B == nmod_matxx::randtril(2, 2, M, rand3, false)); B.set_randtriu(rand2, false); tassert(B == nmod_matxx::randtriu(2, 2, M, rand3, false)); B.set_randpermdiag(rand2, v); tassert(B == nmod_matxx::randpermdiag(2, 2, M, rand3, v)); } void test_reduction_reconstruction() { std::vector primes; primes.push_back(1031); primes.push_back(1033); primes.push_back(1039); mp_limb_t M = primes[0]; frandxx rand; fmpz_matxx A(5, 7);A.set_randtest(rand, 8); nmod_matxx Ap = nmod_matxx::reduce(A, M); nmodxx_ctx_srcref ctx = Ap.estimate_ctx(); tassert(Ap.rows() == A.rows() && Ap.cols() == A.cols()); for(slong i = 0;i < A.rows();++i) for(slong j = 0;j < A.cols();++j) tassert(Ap.at(i, j) == nmodxx::red(A.at(i, j), ctx)); tassert(A == fmpz_matxx::lift(Ap)); for(slong i = 0;i < A.rows();++i) for(slong j = 0;j < A.cols();++j) A.at(i, j) = abs(A.at(i, j)); tassert(A == fmpz_matxx::lift_unsigned(nmod_matxx::reduce(A, M))); nmod_mat_vector v1(A.rows(), A.cols(), primes); nmod_mat_vector v2(v1); tassert(v1 == v2); v2[0].at(0, 0) += nmodxx::red(1, ctx); tassert(v2[0].at(0, 0) != v1[0].at(0, 0)); tassert(v1 != v2); v2 = v1; tassert(v1 == v2); A.set_randtest(rand, 25); for(unsigned i = 0;i < primes.size();++i) v1[i] = nmod_matxx::reduce(A, primes[i]); tassert(v1 == multi_mod(A, primes)); fmpz_combxx comb(primes); tassert(multi_mod(A, primes) == multi_mod_precomp(A, primes, comb)); fmpzxx prod(1); fmpz_matxx res(A.rows(), A.cols()); for(unsigned i = 0;i < primes.size();++i) { res = res.CRT(prod, v1[i], true); prod *= primes[i]; } tassert(res == A); tassert(res == multi_CRT(v1, true)); tassert(res == multi_CRT_precomp(v1, comb, true)); } void test_lu() { frandxx rand; nmod_matxx A = nmod_matxx::randtest(5, 5, 1031, rand); nmod_matxx B1(A), B2(A); nmod_matxx::lu_rt res = B1.set_lu(); permxx perm(5); slong rank = nmod_mat_lu(perm._data(), B2._mat(), false); tassert(B1 == B2 && rank == res.first() && perm == res.second()); B1 = A; B2 = A; tassert(B1.set_lu_classical() == B2.set_lu() && B1 == B2); B1 = A; B2 = A; tassert(B1.set_lu_recursive() == B2.set_lu() && B1 == B2); } void test_printing() { if(0) print_pretty(nmod_matxx::zero(2, 2, 7)); // make sure this compiles } int main() { std::cout << "nmod_matxx...."; test_init(); test_arithmetic(); test_functions(); test_randomisation(); test_reduction_reconstruction(); test_lu(); test_printing(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-nmod_poly_matxx.cpp000066400000000000000000000205771414523752600216100ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly_matxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_init() { mp_limb_t M = 1039; nmod_poly_matxx A(3, 4, M); nmodxx_ctx_srcref ctx = A.estimate_ctx(); tassert(ctx.n() == M); tassert((A + A).modulus() == M); tassert(A.rows() == 3 && A.cols() == 4); tassert(A.at(0, 0) == nmod_polyxx::from_ground(0, ctx)); A.at(0, 0) = nmod_polyxx::from_ground(1, ctx); nmod_poly_matxx B(A); tassert(A == B); tassert(B.rows() == 3 && B.cols() == 4); tassert(B.at(0, 0) == nmod_polyxx::from_ground(1, ctx)); B.at(0, 0) = nmod_polyxx::from_ground(0, ctx); tassert(A.at(0, 0) == nmod_polyxx::from_ground(1, ctx)); tassert(A != B); B = A; tassert(A == B); frandxx state; nmod_matxx C(A.rows(), A.cols(), A.modulus()); C.set_randtest(state); A = nmod_poly_matxx::from_ground(C); for(slong i = 0;i < A.rows();++i) for(slong j = 0;j < A.cols();++j) tassert(A.at(i, j) == nmod_polyxx::from_ground(C.at(i, j))); tassert(nmod_poly_matxx::zero(2, 2, M).is_zero() && nmod_poly_matxx::one(2, 2, M).is_one()); } template bool has_explicit_temporaries(const Expr&) { return Expr::ev_traits_t::rule_t::temporaries_t::len != 0; } void test_arithmetic() { mp_limb_t M = 1039; nmod_poly_matxx A(10, 10, M); nmod_poly_matxx v(10, 1, M); nmodxx_ctx_srcref ctx = A.estimate_ctx(); for(unsigned i = 0;i < 10;++i) v.at(i, 0) = nmod_polyxx::from_ground(i, ctx); nmod_polyxx two = nmod_polyxx::from_ground(2, ctx); tassert(transpose(v).rows() == 1); tassert(v.transpose().cols() == 10); tassert((two*v).rows() == 10); tassert((v*two).rows() == 10); tassert((v*transpose(v)).rows() == 10 && (v*transpose(v)).cols() == 10); tassert(!has_explicit_temporaries(trace(transpose(v)))); tassert(!has_explicit_temporaries(trace(A + v*transpose(v)))); tassert(!has_explicit_temporaries(A + v*transpose(v))); tassert(!has_explicit_temporaries(trace((v*transpose(v) + A)))); tassert(!has_explicit_temporaries(trace(v*transpose(v) + v*transpose(v)))); tassert(!has_explicit_temporaries(v*transpose(v) + v*transpose(v))); tassert(trace(transpose(v)) == nmod_polyxx::from_ground(0, ctx)); tassert(trace(A + v*transpose(v)) == nmod_polyxx::from_ground(285, ctx)); tassert(trace(v*transpose(v) + A) == nmod_polyxx::from_ground(285, ctx)); tassert(trace(v*transpose(v) + v*transpose(v)) == nmod_polyxx::from_ground(2*285, ctx)); tassert(trace((A+A)*(nmod_polyxx::from_ground(1, ctx) + nmod_polyxx::from_ground(1, ctx))) == nmod_polyxx::from_ground(0, ctx)); for(unsigned i = 0;i < 10; ++i) for(unsigned j = 0; j < 10; ++j) A.at(i, j) = nmod_polyxx::from_ground(i*j, ctx); tassert(A == v*transpose(v)); tassert(A != transpose(v)*v); A.at(0, 0) = nmod_polyxx::from_ground(15, ctx); tassert(A != v*transpose(v)); A.at(0, 0) = nmod_polyxx::from_ground(0, ctx); for(unsigned i = 0;i < 10; ++i) for(unsigned j = 0; j < 10; ++j) A.at(i, j) *= two; tassert(A == v*transpose(v) + v*transpose(v)); tassert(A - v*transpose(v) == v*transpose(v)); tassert(((-A) + A).is_zero()); tassert((A + A).at(0, 0) == A.at(0, 0) + A.at(0, 0)); tassert(A * nmodxx::red(17, ctx) == A * nmod_polyxx::from_ground(17, ctx)); frandxx rand; nmodxx x = nmodxx::red(17, ctx); A.set_randtest(rand, 5); nmod_matxx B(A.rows(), A.cols(), M); B = A(x); for(slong i = 0;i < A.rows();++i) for(slong j = 0;j < A.cols();++j) tassert(B.at(i, j) == A.at(i, j)(x)); tassert(A(x) == evaluate(A, x)); } void test_functions() { mp_limb_t M = 1031; nmod_poly_matxx A(2, 3, M), B(2, 2, M), empty(0, 15, M); nmodxx_ctx_srcref ctx = A.estimate_ctx(); B.at(0, 0) = nmod_polyxx::from_ground(1, ctx); tassert(A.is_zero() && !A.is_empty() && !A.is_square() && !A.is_one()); tassert(!B.is_zero() == B.is_square()); tassert(empty.is_zero() && empty.is_empty()); B.at(1, 1) = B.at(0, 0); tassert(B.is_one()); // transpose tested in arithmetic // mul tested in arithmetic // trace tested in arithmetic A.at(0, 0).set_coeff(35, 1); tassert(A.max_length() == 36); frandxx rand; A.set_randtest(rand, 5); B.set_randtest(rand, 5); tassert(B*A == B.mul_classical(A)); tassert(B*A == B.mul_KS(A)); tassert(B*A == B.mul_interpolate(A)); tassert(B.sqr() == B*B); tassert(B.sqr_classical() == B*B); tassert(B.sqr_KS() == B*B); tassert(B.sqr_interpolate() == B*B); tassert(B.pow(5u) == B*B.sqr().sqr()); nmod_matxx Bp(B.rows(), B.cols(), B.modulus()); Bp.set_randrank(rand, 1); tassert(nmod_poly_matxx::from_ground(Bp).det().is_zero()); Bp.set_randrank(rand, 2); tassert(nmod_poly_matxx::from_ground(Bp).det() == nmod_polyxx::from_ground(Bp.det())); Bp.set_randrank(rand, 1); tassert(inv(nmod_poly_matxx::from_ground(Bp)).get<0>() == false); Bp.set_randrank(rand, 2); bool worked;nmod_polyxx den(B.modulus()); ltupleref(worked, B, den) = inv(nmod_poly_matxx::from_ground(Bp)); tassert(worked && B*nmod_poly_matxx::from_ground(Bp)*A == A*den); tassert(rank(B) == 2); Bp.set_randrank(rand, 1); tassert(nmod_poly_matxx::from_ground(Bp).solve(A).get<0>() == false); Bp.set_randrank(rand, 2); nmod_poly_matxx P(A.rows(), A.cols(), A.modulus()); ltupleref(worked, P, den) = nmod_poly_matxx::from_ground(Bp).solve(A); tassert(worked && nmod_poly_matxx::from_ground(Bp)*P == A*den); B = nmod_poly_matxx::from_ground(Bp); tassert(B.solve(A) == B.solve_fflu(A)); permxx perm(B.rows()); tassert(solve_fflu_precomp(perm, B.fflu(&perm, false).get<1>().evaluate(), A) == B.solve_fflu(A).get<1>()); Bp.set_randtest(rand); B = nmod_poly_matxx::from_ground(Bp); slong nullity;nmod_poly_matxx C(2, 2, M); tassert(nullspace(B).get<1>().rows() == 2); tassert(nullspace(B).get<1>().cols() == 2); ltupleref(nullity, C) = nullspace(B); tassert(nullity == 2 - rank(B)); tassert(C.rank() == nullity); tassert((B*C).is_zero()); B.set_zero();tassert(B.is_zero()); } void test_randomisation() { frandxx rand, rand2; mp_limb_t M = 1031; nmod_poly_matxx A(2, 2, M); A.set_randtest(rand, 17); tassert(A.at(0, 0).length() <= 17); tassert(A == nmod_poly_matxx::randtest(2, 2, M, rand2, 17)); A.set_randtest_sparse(rand, 17, 0.5); tassert(A.at(0, 0).length() <= 17); tassert(A == nmod_poly_matxx::randtest_sparse(2, 2, M, rand2, 17, 0.5)); } void test_row_reduction() { frandxx state; nmod_poly_matxx A = nmod_poly_matxx::randtest(5, 5, 1031, state, 7); slong rank1, rank2; nmod_polyxx den1(A.modulus()), den2(A.modulus()); nmod_poly_matxx res1(A.rows(), A.cols(), A.modulus()); nmod_poly_matxx res2(res1); tassert(find_pivot_any(A, 2, 4, 1) == nmod_poly_mat_find_pivot_any(A._mat(), 2, 4, 1)); tassert(find_pivot_partial(A, 2, 4, 1) == nmod_poly_mat_find_pivot_partial(A._mat(), 2, 4, 1)); tassert(A.fflu(0, false).get<1>().rows() == A.rows()); permxx p1(5), p2(5); ltupleref(rank1, res1, den1) = fflu(A, &p1); rank2 = nmod_poly_mat_fflu(res2._mat(), den2._poly(), p2._data(), A._mat(), false); tassert(rank1 == rank2 && res1 == res2 && p1 == p2 && den1 == den2); tassert(rank1 == A.fflu(0, false).get<0>()); ltupleref(rank1, res1, den1) = rref(A); rank2 = nmod_poly_mat_rref(res2._mat(), den2._poly(), A._mat()); tassert(rank1 == rank2 && res1 == res2 && p1 == p2 && den1 == den2); } void test_printing() { if(0) print_pretty(nmod_poly_matxx::zero(2, 2, 7), "x"); // make sure this compiles } int main() { std::cout << "nmod_poly_matxx...."; test_init(); test_arithmetic(); test_functions(); test_randomisation(); test_row_reduction(); test_printing(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-nmod_polyxx.cpp000066400000000000000000000362051414523752600207420ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpq_polyxx.h" #include "fmpz_polyxx.h" #include "nmod_polyxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_init() { nmod_polyxx p(10); tassert(p.length() == 0); tassert(p.modulus() == 10); nmodxx_ctx_srcref ctx = p.estimate_ctx(); tassert(p == nmod_polyxx::from_ground(nmodxx::red(0, ctx))); p.set_coeff(0, 1); tassert(p == nmod_polyxx::from_ground( (nmodxx::red(1, ctx)) + (nmodxx::red(0, ctx)))); tassert(nmod_polyxx::zero(13).is_zero() && nmod_polyxx::one(13).is_one()); } void test_manipulation() { mp_limb_t M = 31; nmod_polyxx p(M), q(M); nmodxx_ctx_srcref ctx = p.estimate_ctx(); p.set_coeff(5, 17 + M); tassert(p.degree() == 5); q.set_coeff(5, nmodxx::red(17, ctx)); tassert((q + nmod_polyxx(M)).get_coeff(5) == nmodxx::red(17, ctx)); p.set_coeff(0, nmodxx::red(1, ctx)); tassert(p != q); p.set_coeff(0, 0); tassert(p == q); tassert(p.length() == 6); p.realloc(0); tassert(p.is_zero() && !p.is_one()); p.set_coeff(0, 1); tassert(p.is_one()); } void test_assignment() { mp_limb_t M = 31; nmod_polyxx p(M), q(M); p.set_coeff(0, 1); tassert(p != q); p = q; tassert(p == q); p = "4 31 0 0 0 1"; q.set_coeff(3, 1); tassert(p == q); tassert(p == nmod_polyxx("4 31 0 0 0 1")); // TODO XXX this does not always fail? //assert_exception(p = "2 1 2"); assert_exception(p = "2 x 2"); assert_exception(nmod_polyxx("2 x 2")); } void test_conversion() { nmod_polyxx p(31); p.set_coeff(3, 1); tassert(p.to_string() == "4 31 0 0 0 1"); } void test_arithmetic() { mp_limb_t M = 31; nmod_polyxx g(M), h(M); nmodxx_ctx_srcref ctx = g.estimate_ctx(); g.set_coeff(0, 17); h.set_coeff(0, 15); tassert((g + h).get_coeff(0) == nmodxx::red(15 + 17, ctx)); frandxx state; g.set_randtest(state, 10); h.set_randtest(state, 10); tassert(((-g) + g).is_zero()); tassert(g - h == g + (-h)); tassert(g*nmodxx::red(3, ctx) == g + g + g); tassert(g.make_monic() == g*inv(g.get_coeff(g.degree()))); nmod_polyxx f(M);f.set_coeff(0, 15); tassert(f*g == nmodxx::red(15, ctx)*g); tassert(h.mul_classical(g) == h.mul_KS(g) && h.mul_KS(g) == h*g); f = h*g;f.truncate(7); tassert(f == mullow(h, g, 7)); tassert(f == h.mullow_KS(g, 7)); tassert(f == h.mullow_classical(g, 7)); f = (h*g).shift_right(7); tassert(f == h.mulhigh(g, 7).shift_right(7)); tassert(f == h.mulhigh_classical(g, 7).shift_right(7)); f = h / g; tassert(f*g + (h % g) == h); tassert(((h*g) % h).is_zero()); f.set_randtest(state, 10); g %= f; h %= f; tassert(h.mulmod(g, f) == ((h*g) % f)); tassert(h.mulmod(g, f) == h.mulmod_preinv(g, f, f.reverse(f.length()).inv_series(f.length()))); f = "3 31 1 0 1"; nmodxx x = nmodxx::red(7, ctx); tassert(evaluate(f, x) == x*x + nmodxx::red(1, ctx)); f.realloc(0);f.set_coeff(31, 1); tassert(evaluate(f, x) == x); tassert(f(x) == x); nmod_polyxx seven(M); seven.set_coeff(0, x); tassert(compose(f, seven).get_coeff(0) == f(x)); tassert(f(seven).length() == 1); nmod_vecxx vec1(2, ctx), vec2(2, ctx); vec1[0] = nmodxx::red(7, ctx); vec1[1] = nmodxx::red(15, ctx); vec2[0] = f(vec1[0]); vec2[1] = f(vec1[1]); tassert(f(vec1) == vec2); } void test_functions() { mp_limb_t M = 31; nmod_polyxx g(M); nmodxx_ctx_srcref ctx = g.estimate_ctx(); g.set_coeff(5, 15); tassert(g.max_bits() == 4); g.truncate(3); tassert(g.is_zero()); g.set_coeff(15, 1); tassert(g.shift_right(15).is_one()); tassert(g.shift_right(15).shift_left(15) == g); frandxx rand; g.set_randtest(rand, 15); tassert(g.length() <= 15); g.set_randtest_irreducible(rand, 15); tassert(g.length() <= 15); tassert(g.is_squarefree()); tassert(g.is_irreducible()); tassert(g == nmod_polyxx::bit_unpack(g.bit_pack(5u), 5u, ctx)); // multiplication, division, modulo tested in arithmetic tassert(g.pow(3u) == g*g*g); tassert(g.pow(5u) == g.pow_binexp(5u)); nmod_polyxx res(g.pow(15u));res.truncate(12); tassert(res == g.pow_trunc(15u, 12)); tassert(res == g.pow_trunc_binexp(15u, 12)); nmod_polyxx f(M);f.set_randtest(rand, 10); res = g.pow(10u) % f; tassert(res == g.powmod_binexp(10u, f)); tassert(res == g.powmod_binexp_preinv(10u, f, f.reverse(f.length()).inv_series(f.length()))); res = "5 31 1 1 1 1 1"; tassert(res.derivative().to_string() == "4 31 1 2 3 4"); tassert(g.integral().derivative() == g); tassert(f.divrem(g) == ltuple(f / g, f % g)); tassert(f.divrem_basecase(g) == f.divrem(g)); tassert(f.divrem_divconquer(g) == f.divrem(g)); tassert(f.div_basecase(g) == f / g); tassert(f.div_divconquer(g) == f / g); tassert(f.rem_basecase(g) == f % g); f.set_coeff(0, 17); // non-zero mod 31, so a unit res = f*f.inv_series(15);res.truncate(15); tassert(res.is_one()); tassert(f.inv_series(15) == f.inv_series_basecase(15)); tassert(f.inv_series(15) == f.inv_series_newton(15)); res = g * f.inv_series(15);res.truncate(15); tassert(g.div_series(f, 15) == res); f.set_coeff(f.degree(), 12); // unit tassert(g.div_newton(f) == g / f); tassert(g.divrem_newton(f) == g.divrem(f)); tassert(g.divrem(f) == g.divrem_newton_n_preinv(f, f.reverse(f.length()).inv_series(f.length()))); tassert(g /f == g.div_newton_n_preinv(f, f.reverse(f.length()).inv_series(f.length()))); res = "2 31 5 1"; tassert(f.div_root(-nmodxx::red(5, ctx)) == f / res); nmod_vecxx v(10, ctx); _nmod_vec_randtest(v._array(), rand._data(), v.size(), ctx._nmod()); tassert(f.evaluate_fast(v) == f(v)); tassert(f.evaluate_iter(v) == f(v)); nmod_vecxx xs(10, ctx); for(int i = 0;i < xs.size();++i) xs[i] = nmodxx::red(i, ctx); res = nmod_polyxx::interpolate(xs, v); tassert(res.degree() < xs.size()); for(int i = 0;i < xs.size();++i) tassert(res(xs[i]) == v[i]); tassert(nmod_polyxx::interpolate_fast(xs, v) == res); tassert(nmod_polyxx::interpolate_newton(xs, v) == res); tassert(nmod_polyxx::interpolate_barycentric(xs, v) == res); tassert(f(g) == f.compose_divconquer(g)); tassert(f(g) == f.compose_horner(g)); res = "2 31 7 1"; tassert(f(res) == f.taylor_shift(nmodxx::red(7, ctx))); tassert(f(res) == f.taylor_shift_horner(nmodxx::red(7, ctx))); tassert(f(res) == f.taylor_shift_convolution(nmodxx::red(7, ctx))); nmod_polyxx h(M); h.set_randtest(rand, 15); tassert(f.compose_mod(g, h) == f(g) % h); tassert(f.compose_mod(g, h) == f.compose_mod_horner(g, h)); tassert(f.compose_mod(g, h) == f.compose_mod_brent_kung(g, h)); tassert(f.compose_mod(g, h) == f.compose_mod_brent_kung_preinv(g, h, h.reverse(h.length()).inv_series(h.length()))); h.set_randtest_irreducible(rand, 12); tassert(h.gcd(f).is_one()); tassert(f.gcd_euclidean(f) == f.make_monic()); tassert(f.gcd_hgcd(g) == f.gcd(g)); nmod_polyxx R(M), S(M); ltupleref(res, R, S) = f.xgcd(g); tassert(res == R*f + S*g && res == gcd(f, g)); tassert(f.xgcd(g) == f.xgcd_hgcd(g)); tassert(f.xgcd(g) == f.xgcd_euclidean(g)); fmpz_polyxx lift1 = fmpz_polyxx::randtest(rand, 10, 6); fmpz_polyxx lift2 = fmpz_polyxx::randtest(rand, 10, 6); lift1.set_coeff(10, 1); lift2.set_coeff(10, 1); f = nmod_polyxx::reduce(lift1, ctx); for(int i = 0;i < f.length();++i) tassert(f.get_coeff(i) == nmodxx::red(lift1.get_coeff(i), ctx)); g = nmod_polyxx::reduce(lift2, ctx); tassert(f.resultant(g) == nmodxx::red(lift1.resultant(lift2), ctx)); tassert(f.resultant(g) == f.resultant_euclidean(g)); g.set_coeff(0, 0); res = f(g); res.truncate(15); tassert(f.compose_series(g, 15) == res); tassert(f.compose_series_horner(g, 15) == res); tassert(f.compose_series_brent_kung(g, 15) == res); tassert(f.compose_series_divconquer(g, 15) == res); res = "2 31 0 1"; g.set_coeff(1, 17); // unit tassert(g.compose_series(g.revert_series(15), 15) == res); tassert(g.revert_series_newton(15) == g.revert_series(15)); tassert(g.revert_series_lagrange(15) == g.revert_series(15)); tassert(g.revert_series_lagrange_fast(15) == g.revert_series(15)); f.set_coeff(0, 1); tassert(f.sqrt_series(15).pow_trunc(2u, 15) == f); tassert(f.invsqrt_series(15).pow_trunc(2u, 15) == f.inv_series(15)); tassert((f*f).sqrt() == f); res = "1 31 1"; assert_exception((f*f + res).sqrt().evaluate()); f = nmod_polyxx::product_roots(xs); tassert(f.degree() == xs.size()); for(int i = 0;i < xs.size();++i) tassert(f(nmodxx::red(i, ctx)).to() == 0); res = "2 31 0 1"; tassert(f.inflate(5u) == f(res.pow(5u))); tassert(f.inflate(5u).deflate(5u) == f); tassert(f.inflate(5u).deflation() >= 5); tassert(f.deflate(f.deflation()).deflation() == 1); g.set_randtest_irreducible(rand, 4); f.set_randtest_irreducible(rand, 5); res = f*g*g; tassert(res.remove(g) == 2 && res == f); } void test_transcendental_functions() { frandxx state; mp_limb_t M = 1031; // prime nmod_polyxx f(M); nmodxx_ctx_srcref ctx = f.estimate_ctx(); fmpq_polyxx lift = fmpq_polyxx::randtest(state, 10, 9); lift.set_coeff(0, 0); f = nmod_polyxx::reduce(lift, ctx); for(int i = 0;i < f.length();++i) tassert(f.get_coeff(i) == nmodxx::red(lift.get_coeff(i), ctx)); tassert(f.exp_series(15) == nmod_polyxx::reduce(lift.exp_series(15), ctx)); tassert(f.atan_series(15) == nmod_polyxx::reduce(lift.atan_series(15), ctx)); tassert(f.atanh_series(15) == nmod_polyxx::reduce(lift.atanh_series(15), ctx)); tassert(f.asin_series(15) == nmod_polyxx::reduce(lift.asin_series(15), ctx)); tassert(f.asinh_series(15) == nmod_polyxx::reduce(lift.asinh_series(15), ctx)); tassert(f.sin_series(15) == nmod_polyxx::reduce(lift.sin_series(15), ctx)); tassert(f.cos_series(15) == nmod_polyxx::reduce(lift.cos_series(15), ctx)); tassert(f.tan_series(15) == nmod_polyxx::reduce(lift.tan_series(15), ctx)); tassert(f.sinh_series(15) == nmod_polyxx::reduce(lift.sinh_series(15), ctx)); tassert(f.cosh_series(15) == nmod_polyxx::reduce(lift.cosh_series(15), ctx)); tassert(f.tanh_series(15) == nmod_polyxx::reduce(lift.tanh_series(15), ctx)); tassert(f.exp_series_basecase(15) == f.exp_series(15)); f.set_coeff(0, 1); lift.set_coeff(0, 1); tassert(f.log_series(15) == nmod_polyxx::reduce(lift.log_series(15), ctx)); f.realloc(0); nmodxx a = nmodxx::red(7, ctx); f.set_coeff(5, a); tassert(f.exp_series(15) == exp_series_monomial(a, 5u, 15)); f.set_coeff(0, 1); tassert(f.log_series(15) == log_series_monomial(a, 5u, 15)); } // test stuff which we should get automatically - addmul, references etc void test_extras() { // TODO } bool equiv_fac(const nmod_poly_factorxx& fac1, const nmod_poly_factorxx& fac2) { tassert(fac1.size() == 2); if(fac1.exp(0) == fac1.exp(1)) { if(fac2.exp(0) != fac1.exp(0) || fac2.exp(1) != fac1.exp(0)) return false; return (fac1.p(0) == fac2.p(0) && fac1.p(1) == fac2.p(1)) || (fac1.p(1) == fac2.p(0) && fac1.p(0) == fac2.p(1)); } if(fac1.size() != fac2.size()) return false; if(fac1.exp(0) == fac2.exp(0)) return fac1.exp(1) == fac2.exp(1) && fac1.p(0) == fac2.p(0) && fac1.p(1) == fac2.p(1); else return fac1.exp(0) == fac2.exp(1) && fac1.exp(1) == fac2.exp(0) && fac1.p(0) == fac2.p(1) && fac1.p(1) == fac2.p(0); } void test_factoring() { mp_limb_t M = 1031; nmod_polyxx f(M), g(M); frandxx state; f.set_randtest_irreducible(state, 4); f = f.make_monic(); g.set_randtest_irreducible(state, 5); g = g.make_monic(); nmod_poly_factorxx fac = factor(f*f*g); tassert(fac.size() == 2); if(fac.exp(0) == 1) { tassert(fac.p(0) == g); tassert(fac.p(1) == f && fac.exp(1) == 2); } else { tassert(fac.p(0) == f && fac.exp(0) == 2); tassert(fac.p(1) == g && fac.exp(1) == 1); } nmod_poly_factorxx fac2;fac2 = fac;fac2.pow(2); fac.insert(g, 1); fac.insert(f, 2); tassert(fac == fac2); nmod_polyxx prod(f*f*f*g*g); fac = factor(prod); tassert(equiv_fac(fac, factor_cantor_zassenhaus(prod))); tassert(equiv_fac(factor(f*g), factor_berlekamp(f*g))); tassert(equiv_fac(fac, factor_kaltofen_shoup(prod))); tassert(equiv_fac(fac, factor_with_cantor_zassenhaus(prod))); tassert(equiv_fac(fac, factor_with_berlekamp(prod))); tassert(equiv_fac(fac, factor_with_kaltofen_shoup(prod))); std::vector degs(2); fac.realloc(0);fac.set_factor_distinct_deg(f*g, degs); tassert(degs.size() == 2); tassert((degs[0] == f.degree() && degs[1] == g.degree()) || (degs[1] == f.degree() && degs[0] == g.degree())); // TODO test set_factor_equal_deg* if(0) print(fac); // make sure this compiles } void test_reduction_reconstruction() { std::vector primes; primes.push_back(1031); primes.push_back(1033); primes.push_back(1039); mp_limb_t M = primes[0]; nmodxx_ctx ctx(M); frandxx rand; fmpz_polyxx A = fmpz_polyxx::randtest(rand, 10, 8); nmod_polyxx Ap = nmod_polyxx::reduce(A, ctx); for(slong i = 0;i < A.length();++i) tassert(Ap.get_coeff(i) == nmodxx::red(A.get_coeff(i), ctx)); tassert(A == fmpz_polyxx::lift(Ap)); for(slong i = 0;i < A.length();++i) A.coeff(i) = abs(A.coeff(i)); tassert(A == fmpz_polyxx::lift_unsigned(nmod_polyxx::reduce(A, ctx))); A = fmpz_polyxx::randtest(rand, 10, 25); fmpzxx prod(1); fmpz_polyxx res; for(unsigned i = 0;i < primes.size();++i) { res = res.CRT(prod, nmod_polyxx::reduce(A, primes[i]), true); prod *= primes[i]; } tassert(res == A); } void test_randomisation() { frandxx state1, state2; mp_limb_t N = 1031; nmod_polyxx p(N); p.set_randtest(state1, 7); tassert(p == nmod_polyxx::randtest(N, state2, 7)); p.set_randtest_irreducible(state1, 7); tassert(p == nmod_polyxx::randtest_irreducible(N, state2, 7)); } int main() { std::cout << "nmod_polyxx...."; test_init(); test_manipulation(); test_assignment(); test_conversion(); test_arithmetic(); test_functions(); test_transcendental_functions(); test_extras(); test_factoring(); test_reduction_reconstruction(); test_randomisation(); frandxx rand; test_print_read(nmod_polyxx::randtest(7, rand, 5)); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-nmod_vecxx.cpp000066400000000000000000000063471414523752600205400ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_vecxx.h" #include "flintxx/ltuple.h" #include "flintxx/test/helpers.h" using namespace flint; bool test_conv(nmodxx_ctx_srcref) {return true;} void test_init() { nmodxx_ctx c(31); tassert(test_conv(c)); tassert(c.n() == 31); nmodxx a = nmodxx::make_nored(65, c); tassert(a._limb() == 65); a.reduce(); tassert(a._limb() == (65 % 31)); nmodxx b = nmodxx::red(65, c); tassert(b._limb() == a._limb()); tassert(a == b); nmodxx zero(c); tassert(zero != a); a = zero; tassert(a == zero); tassert(nmodxx::red(65, c) == nmodxx::red(fmpzxx(65), c)); tassert(nmodxx::red(3, c)/nmodxx::red(2, c) == nmodxx::red(fmpqxx(3, 2u), c)); } void test_conversion() { nmodxx_ctx c(31); nmodxx a = nmodxx::red(65, c); tassert(a.to() == a._limb()); tassert(a.to_string() == "3 mod 31"); } void test_arithmetic() { nmodxx_ctx c(31); nmodxx a = nmodxx::red(65, c); nmodxx b = nmodxx::red(21, c); tassert(a + b == nmodxx::red(65 + 21, c)); tassert((a + b).estimate_ctx() == a._ctx()); tassert((-a) + a == nmodxx::red(0, c)); tassert(b + (-a) == b - a); tassert(nmodxx::red(3, c) * a == a + a + a); tassert((a / b) * b == a); tassert(inv(b) == nmodxx::red(1, c) / b); tassert(pow(a, 4u) == a*a*a*a); tassert(b.inv() == inv(b)); tassert(a.pow(4u) == pow(a, 4u)); } void test_references() { nmodxx_ctx c(31); nmodxx a = nmodxx::red(17, c); nmodxx b = nmodxx::red(19, c); nmodxx_ref ar(a); nmodxx_srcref bsr(b); tassert(a == ar); tassert(bsr != ar); ar = nmodxx::red(19, c); tassert(a == bsr); tassert(ar + bsr + a == nmodxx::red(3, c) * b); nmodxx_ref ar2 = nmodxx_ref::make(a._limb(), a.estimate_ctx()); nmodxx_srcref asr2 = nmodxx_srcref::make(a._limb(), a.estimate_ctx()); ar2 = nmodxx::red(4, c); tassert(asr2 == nmodxx::red(4, c)); } void test_vec() { nmodxx_ctx c(31); nmod_vecxx v1(10, c), v2(10, c); for(slong i = 0;i < (slong) v1.size();++i) { v1[i] = nmodxx::red(0, c); v2[i] = nmodxx::red(0, c); } tassert(v1 == v2); v1[0] = nmodxx::red(15, c); tassert(v1 != v2); tassert(v1 + v2 == v1); } namespace flint { typedef make_ltuple::type>::type ltup_t; FLINT_DEFINE_UNOP(make_lazy_test) namespace rules { FLINT_DEFINE_UNARY_EXPR_COND(make_lazy_test_op, ltup_t, NMOD_VECXX_COND_S, to.template get<0>() = from[0]) } } void test_temporaries() { nmodxx_ctx ctx(17); nmod_vecxx v(1, ctx);v[0] = nmodxx::red(7, ctx); tassert(make_lazy_test(v).get<0>() == v[0]); } int main() { std::cout << "nmod_vecxx...."; test_init(); test_conversion(); test_arithmetic(); test_references(); test_vec(); test_temporaries(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-padic_matxx.cpp000066400000000000000000000123351414523752600206610ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "padic_matxx.h" #include "flintxx/test/helpers.h" using namespace flint; padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE); void test_init() { padic_matxx a(ctx, 5, 7, 20); tassert(a.get_ctx()._ctx() == &ctx._ctx()[0]); tassert(a.prec() == 20); tassert(a.rows() == 5 && a.cols() == 7); padic_matxx c(a); tassert(a == c); padic_matxx b(ctx, 3, 4, 30); tassert((a + b).estimate_ctx()._ctx() == &ctx._ctx()[0]); tassert((a + b).prec() == 30); tassert((a + b).create_temporary().prec() == 30); padic_matxx d((a + b).create_temporary()); tassert(d.get_ctx()._ctx() == &ctx._ctx()[0]); tassert(d.prec() == 30); padic_matxx e(a + b); tassert(e.prec() == 30); tassert(padic_matxx::zero(ctx, 5, 7).is_zero() && padic_matxx::zero(ctx, 5, 7, 25).is_zero()); a.prec() = 25; tassert(a.prec() == 25); a.val() = 17; tassert(a.val() == 17); padic_matxx eye = padic_matxx::one(ctx, 3, 3); for(slong i = 0;i < eye.rows();++i) for(slong j = 0;j < eye.cols();++j) if(i == j) tassert(eye.get_entry(i, j).is_one()); else tassert(eye.get_entry(i, j).is_zero()); } void test_manipulation() { padic_matxx a(ctx, 5, 7); tassert(a.at(0, 0) == 0); padic_matxx b(a); b.set_entry(0, 0, padicxx::one(ctx)); tassert(a != b); b /= fmpzxx(5); tassert(b.at(0, 0) == 1); b.at(0, 0) = 2; tassert((b / fmpzxx(5)).val() == -2); tassert(b.get_entry(0, 0) == padicxx::from_QQ(fmpqxx::frac(2, 5), ctx)); tassert(b.get_entry(0, 0) == (b + padic_matxx::zero(ctx, 5, 7)).get_entry(0, 0)); } void test_assignment() { padic_matxx a(ctx, 3, 7), b(ctx, 3, 7); b.set_entry(0, 0, padicxx::from_QQ(3, ctx)); tassert(a != b); fmpq_matxx M(3, 7); b = M; tassert(a == b); tassert(b.to() == M); } template bool has_explicit_temporaries(const Expr&) { return Expr::ev_traits_t::rule_t::temporaries_t::len != 0; } void test_arithmetic() { frandxx state; padic_matxx v(ctx, 1, 10); padic_matxx A(ctx, 10, 10); tassert(!has_explicit_temporaries(transpose(transpose(v)))); tassert(!has_explicit_temporaries(transpose(A + v*transpose(v)))); tassert(!has_explicit_temporaries(A + v*transpose(v))); tassert(!has_explicit_temporaries(transpose((v*transpose(v) + A)))); tassert(!has_explicit_temporaries(transpose(v*transpose(v) + v*transpose(v)))); tassert(!has_explicit_temporaries(v*transpose(v) + v*transpose(v))); fmpz_matxx a = fmpz_matxx::randtest(4, 4, state, 10); fmpz_matxx b = fmpz_matxx::randtest(4, 4, state, 10); fmpq_matxx aq(4, 4);aq = a; fmpq_matxx bq(4, 4);bq = b; padic_matxx ap = padic_matxx::from_QQ(aq, ctx); padic_matxx bp = padic_matxx::from_QQ(bq, ctx); tassert(ap + bp == padic_matxx::from_QQ(aq + bq, ctx)); tassert(ap - bp == padic_matxx::from_QQ(aq - bq, ctx)); tassert(ap * bp == padic_matxx::from_QQ(aq * bq, ctx)); tassert(-ap == padic_matxx::from_QQ(-aq, ctx)); fmpzxx s = fmpzxx::randtest(state, 15); tassert(ap * s == padic_matxx::from_QQ(aq * s, ctx)); ltupleref(_, s) = s.remove(ctx.get_p()); tassert(ap / s == padic_matxx::from_QQ(aq / s, ctx)); } void test_functions() { frandxx state; padic_matxx A = padic_matxx::randtest(3, 4, state, ctx); padic_matxx B(A.transpose()); for(slong i = 0;i < B.rows();++i) for(slong j = 0;j < B.cols();++j) tassert(B.get_entry(i, j) == A.get_entry(j, i)); tassert(!A.is_square() && !A.is_empty()); } // test stuff which we should get automatically - references etc void test_extras() { padic_matxx a(ctx, 2, 2); padic_matxx b(ctx, 2, 2); a.set_entry(0, 0, padicxx::from_QQ(3, ctx)); b.set_entry(0, 1, padicxx::from_QQ(2, ctx)); padic_matxx_ref ar(a); padic_matxx_srcref asr(a); tassert(a == ar && ar == asr); tassert(ar + asr == a + a); tassert(padic_matxx(ar) == ar); tassert(padic_matxx(asr) == ar); ar.set_entry(0, 0, padicxx::from_QQ(1, ctx)); tassert(a.get_entry(0, 0).is_one()); } void test_prec() { padic_matxx a(ctx, 2, 2, 5), b(ctx, 2, 2, 7); padic_matxx_ref ar(a); padic_matxx_srcref br(b); tassert((a + a).prec() == 5); tassert((a + ar).prec() == 5); tassert((a + b).prec() == 7); tassert((a + br).prec() == 7); tassert((a.toN(15) + br.toN(10)).prec() == 15); } void test_printing() { tassert_fprint(padic_matxx::one(ctx, 2, 2), "2 2 1 0 0 1"); tassert_fprint_pretty(padic_matxx::one(ctx, 2, 2), "[[1 0]\n[0 1]]"); } int main() { std::cout << "padic_matxx...."; test_init(); test_manipulation(); test_assignment(); test_arithmetic(); test_functions(); test_extras(); test_prec(); test_printing(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-padic_polyxx.cpp000066400000000000000000000127101414523752600210600ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "padic_polyxx.h" #include "flintxx/test/helpers.h" using namespace flint; padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE); void test_init() { padic_polyxx a(ctx, 20); tassert(a.get_ctx()._ctx() == ctx._ctx()); tassert(a.prec() == 20); padic_polyxx c(a); tassert(a == c); padic_polyxx b(ctx, 30); tassert((a + b).estimate_ctx()._ctx() == ctx._ctx()); tassert((a + b).prec() == 30); tassert((a + b).create_temporary().prec() == 30); padic_polyxx d((a + b).create_temporary()); tassert(d.get_ctx()._ctx() == ctx._ctx()); tassert(d.prec() == 30); padic_polyxx e(a + b); tassert(e.prec() == 30); tassert(padic_polyxx::zero(ctx).is_zero() && padic_polyxx::zero(ctx, 25).is_zero()); tassert(padic_polyxx::one(ctx).is_one() && padic_polyxx::one(ctx, 25).is_one()); a.prec() = 25; tassert(a.prec() == 25); a.val() = 17; tassert(a.val() == 17); } void test_assignment() { padic_polyxx a(ctx, 20), b(ctx, 20); ulong o1 = 1; slong o2 = 1; fmpzxx o3(1); fmpqxx o4 = fmpqxx::integer(o3); fmpz_polyxx o5 = fmpz_polyxx::from_ground(o3); fmpq_polyxx o6;o6.set_coeff(0, o4); a = o1;tassert(a.is_one());a = 0; a = o2;tassert(a.is_one());a = 0; a = o3;tassert(a.is_one());a = 0; a = o4;tassert(a.is_one());a = 0; a = o5;tassert(a.is_one());a = 0; a = o6;tassert(a.is_one()); tassert(a != b); a = b; tassert(a == b); a = padicxx::from_QQ(1, ctx);tassert(a.is_one()); } void test_conversion() { tassert(padic_polyxx::from_QQ(1, ctx).is_one()); tassert(padic_polyxx::from_QQX(fmpz_polyxx::from_ground(1), ctx).is_one()); tassert(padic_polyxx::from_ground(padicxx::one(ctx)).is_one()); frandxx state; fmpz_polyxx f = fmpz_polyxx::randtest_unsigned(state, 5, 10); tassert(padic_polyxx::from_QQX(f, ctx, 100).to() == f); fmpq_polyxx fq;fq = f; tassert(padic_polyxx::from_QQX(f, ctx, 100).to() == fq); } void test_arithmetic() { frandxx state; padicxx a = padicxx::randtest(state, ctx); padicxx b = padicxx::randtest(state, ctx); padic_polyxx ap = padic_polyxx::from_ground(a); padic_polyxx bp = padic_polyxx::from_ground(b); tassert(ap + bp == padic_polyxx::from_ground(a + b)); tassert(ap - bp == padic_polyxx::from_ground(a - b)); tassert(ap * bp == padic_polyxx::from_ground(a * b)); tassert(-ap == padic_polyxx::from_ground(-a)); tassert(ap * b == padic_polyxx::from_ground(a * b)); } void test_functions() { frandxx state; padic_polyxx p = padic_polyxx::randtest(state, 4, ctx, 25); tassert(p.pow(3u) == p*p*p); tassert(p.degree() == 3); tassert(p.length() == 4); tassert(p.val() + 1 == (p*padicxx::from_QQ(5, ctx, 25)).val()); fmpz_polyxx F1 = fmpz_polyxx::randtest(state, 5, 10); fmpz_polyxx F2 = fmpz_polyxx::randtest(state, 5, 10); padic_polyxx f1 = padic_polyxx::from_QQX(F1, ctx); padic_polyxx f2 = padic_polyxx::from_QQX(F2, ctx); tassert(f1.derivative() == padic_polyxx::from_QQX(F1.derivative(), ctx)); tassert(compose(f1, f2) == padic_polyxx::from_QQX(F1(F2), ctx)); tassert(f1(f2) == compose(f1, f2)); fmpzxx X = fmpzxx::randtest(state, 10); padicxx x = padicxx::from_QQ(X, ctx); tassert(f1(x) == padicxx::from_QQ(F1(X), ctx)); tassert(f1.shift_left(5) == padic_polyxx::from_QQX(F1.shift_left(5), ctx)); tassert(f1.shift_right(2) == padic_polyxx::from_QQX(F1.shift_right(2), ctx)); F1.set_coeff(0, 1); f1 = padic_polyxx::from_QQX(F1, ctx); tassert(f1.inv_series(10) == padic_polyxx::from_QQX(F1.inv_series(10), ctx)); f2.set_zero(); f2.set_coeff(1, padicxx::one(ctx)); tassert(p.compose_pow(5) == p(f2.pow(5u))); tassert(!padic_polyxx::randtest_not_zero(state, 5, ctx).is_zero()); tassert(padic_polyxx::randtest_val(state, 5, 5, ctx).val() == 5); } // test stuff which we should get automatically - references etc void test_extras() { padic_polyxx a = padic_polyxx::from_QQ(fmpqxx(3, 5u), ctx); padic_polyxx b = padic_polyxx::from_QQ(fmpqxx(3, 1u), ctx); padic_polyxx_ref ar(a); padic_polyxx_srcref asr(a); tassert(a == ar && ar == asr); ar = 3; tassert(a == b && asr == b); tassert(ar + asr == a + a); tassert(padic_polyxx(ar) == ar); tassert(padic_polyxx(asr) == ar); } void test_prec() { padic_polyxx a(ctx, 5), b(ctx, 7); padic_polyxx_ref ar(a); padic_polyxx_srcref br(b); tassert((a + a).prec() == 5); tassert((a + ar).prec() == 5); tassert((a + b).prec() == 7); tassert((a + br).prec() == 7); tassert((a.toN(15) + br.toN(10)).prec() == 15); } void test_printing() { padic_polyxx p(ctx); p.set_coeff(2, padicxx::one(ctx)); tassert_fprint(p, "3 0 0 1"); tassert_fprint_pretty(p, "x", "x^2"); } int main() { std::cout << "padic_polyxx...."; test_init(); test_assignment(); test_conversion(); test_arithmetic(); test_functions(); test_extras(); test_prec(); test_printing(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-padicxx.cpp000066400000000000000000000132411414523752600200150ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "padicxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_init() { padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE); tassert(ctx.get_p() == 5); padicxx a(ctx, 20); tassert(a.prec() == 20); padicxx c(a); tassert(a == c); padicxx b(ctx, 30); tassert((a + b).prec() == 30); tassert((a + b).create_temporary().prec() == 30); padicxx d((a + b).create_temporary()); tassert(d.prec() == 30); padicxx e(a + b); tassert(e.prec() == 30); tassert(padicxx::zero(ctx).is_zero() && padicxx::zero(ctx, 25).is_zero()); tassert(padicxx::one(ctx).is_one() && padicxx::one(ctx, 25).is_one()); a.prec() = 25; tassert(a.prec() == 25); a.val() = 17; tassert(a.val() == 17); padicxx zero = padicxx::zero(ctx); tassert(zero.unit() == 0); tassert((zero + zero).unit() == 0); tassert((zero + zero).val() == 0); } void test_assignment() { padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE); padicxx a(ctx, 20), b(ctx, 20); fmpzxx c(17); fmpqxx d(17, 1u); a = 17; tassert(a != b); b = 17; tassert(a == b); b = 0; tassert(a != b); b = UWORD(17); tassert(a == b); b = 0; b = c; tassert(a == b); b = 0; b = fmpzxx_ref(c); tassert(a == b); b = 0; b = fmpzxx_srcref(c); tassert(a == b); b = 0; b = d; tassert(a == b); } void test_conversion() { padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE); padicxx_ctx ctx2(fmpzxx(5), 10, 20, PADIC_VAL_UNIT); padicxx a(ctx), b(ctx2); a = 15; b = 15; tassert(a.to_string() == "15"); tassert(b.to_string() == "3*5"); tassert(a.to() == 15); tassert(a.to() == fmpqxx(15, 1u)); std::ostringstream oss; oss << a << ' ' << b; tassert(oss.str() == "15 3*5"); } template padicxx make_padic(const T& t, slong prec = PADIC_DEFAULT_PREC) { static padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE); return padicxx::from_QQ(t, ctx, prec); } template bool fuzzy_equals(const T& t, const U& u) { slong prec = std::min(t.prec(), u.prec()) - 5; padicxx a(t.estimate_ctx(), prec); a = t; padicxx b(t.estimate_ctx(), prec); b = u; return a == b; } void test_arithmetic() { fmpqxx af(17, 25u), bf(5, 27u); padicxx a(make_padic(af)); padicxx b(make_padic(bf)); tassert(fuzzy_equals(a + b, make_padic(af + bf))); tassert(fuzzy_equals(a * b, make_padic(af * bf))); tassert(fuzzy_equals(a / b, make_padic(af / bf))); tassert(fuzzy_equals(a - b, make_padic(af - bf))); tassert(fuzzy_equals(a << 2, make_padic(af * fmpzxx(25)))); tassert(fuzzy_equals(a >> 2, make_padic(af / fmpzxx(25)))); tassert(-a == make_padic(-af)); } void test_functions() { padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE); padicxx a(make_padic(fmpqxx(14, 25u))); tassert(fuzzy_equals(a, pow(sqrt(a), 2))); assert_exception(sqrt(make_padic(fmpqxx(2, 1u))).evaluate()); fmpqxx cf(14*5, 1u); padicxx c = make_padic(fmpqxx(14*5, 1u)); tassert(fuzzy_equals(log(exp(c)), c)); tassert(exp(c) == exp_rectangular(c) && exp(c) == exp_balanced(c)); c = exp(c); tassert(log(c) == log_satoh(c) && log(c) == log_balanced(c) && log(c) == log_rectangular(c)); padicxx b(make_padic(fmpqxx(14, 17u))); tassert((inv(b)*b).is_one()); padicxx two(make_padic(fmpqxx(2, 1u))); padicxx tl(teichmuller(two)); tassert(pow(tl, 4).is_one() && (tl - two).val() > 0); // TODO test reduce // test padic_val_fac functions tassert(padic_val_fac(fmpzxx(26), fmpzxx(5)) == 6); tassert(padic_val_fac(26u, fmpzxx(5)) == 6); // test randomisation frandxx rand; tassert(padicxx::randtest(rand, ctx, 5).val() < 5 && padicxx::randtest(rand, ctx, 5).val() >= -1); tassert(padicxx::randtest(rand, ctx, -5).val() < -5 && padicxx::randtest(rand, ctx, -5).val() >= -6); tassert(!padicxx::randtest_not_zero(rand, ctx, 5).is_zero()); tassert(padicxx::randtest_int(rand, ctx, -5).is_zero()); padicxx ap(a), bp(b); swap(a, b); tassert(a == bp && b == ap); // test members (just a sample, since from macros) tassert(b.inv() == inv(b)); tassert(b.pow(7) == pow(b, 7)); } // test stuff which we should get automatically - references etc void test_extras() { padicxx a(make_padic(fmpqxx(3, 5u))); padicxx b(make_padic(fmpqxx(3, 1u))); padicxx_ref ar(a); padicxx_srcref asr(a); tassert(a == ar && ar == asr); ar = 3; tassert(a == b && asr == b); tassert(ar + asr == a + a); tassert(padicxx(ar) == ar); tassert(padicxx(asr) == ar); } void test_prec() { padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE); padicxx a(ctx, 5), b(ctx, 7); padicxx_ref ar(a); padicxx_srcref br(b); tassert((a + a).prec() == 5); tassert((a + ar).prec() == 5); tassert((a + b).prec() == 7); tassert((a + br).prec() == 7); tassert((a.toN(15) + br.toN(10)).prec() == 15); } void test_printing() { tassert_fprint(make_padic(0), "0"); } int main() { std::cout << "padicxx...."; test_init(); test_assignment(); test_conversion(); test_arithmetic(); test_functions(); test_extras(); test_prec(); test_printing(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-permxx.cpp000066400000000000000000000022551414523752600177030ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "permxx.h" #include "flintxx/test/helpers.h" using namespace flint; int main() { std::cout << "permxxxx...."; permxx p1(10), p2(10); p1[0] = 1;p1[1] = 0; tassert(p1 != p2); p1 = p2; tassert(p1 == p2); permxx p3(p2); p2[1] = 0; p2[0] = 1; tassert(p1 != p2); tassert(p3 != p2); tassert(parity(p2) == 1); frandxx state; p1 = permxx::randtest(10, state); tassert(p1*inv(p1) == permxx::one(10)); p2 = permxx::randtest(10, state); tassert(p1*p2 == compose(p1, p2)); p3 = p1*p2; p1 *= p2; tassert(p1 == p3); tassert(maybe_perm_data(&p1) == p1._data()); tassert(maybe_perm_data(0) == 0); if(0) print(p1); // make sure this compiles std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-qadicxx.cpp000066400000000000000000000116041414523752600200170ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "qadicxx.h" #include "flintxx/test/helpers.h" // This is a test in itself: used to not compile. #include "padic_polyxx.h" using namespace flint; void test_init() { qadicxx_ctx ctx(fmpzxx(5), 3, 10, 20, PADIC_TERSE); qadicxx a(ctx, 20); tassert(&a.get_qctx() == &ctx); tassert(a.prec() == 20); qadicxx c(a); tassert(a == c); qadicxx b(ctx, 30); tassert(&(a + b).estimate_ctx() == &ctx); tassert((a + b).prec() == 30); tassert((a + b).create_temporary().prec() == 30); qadicxx d((a + b).create_temporary()); tassert(&d.get_qctx() == &ctx); tassert(d.prec() == 30); qadicxx e(a + b); tassert(e.prec() == 30); tassert(qadicxx::zero(ctx).is_zero() && qadicxx::zero(ctx, 25).is_zero()); tassert(qadicxx::one(ctx).is_one() && qadicxx::one(ctx, 25).is_one()); qadicxx zero = qadicxx::zero(ctx); tassert((zero + zero).val() == 0); } void test_assignment() { qadicxx_ctx ctx(fmpzxx(5), 3, 10, 20, PADIC_TERSE); qadicxx a(ctx, 20), b(ctx, 20); a = 17u; tassert(a != b); b = 17u; tassert(a == b); } void test_conversion() { qadicxx_ctx ctx(fmpzxx(5), 3, 10, 20, PADIC_TERSE); frandxx state; padicxx p = padicxx::randtest(state, ctx.pctx()); qadicxx a = qadicxx::from_ground(ctx, p); tassert(a.to() == p); assert_exception(qadicxx::gen(ctx).to()); } void test_arithmetic() { qadicxx_ctx ctx(fmpzxx(5), 3, 10, 20, PADIC_TERSE); frandxx state; padicxx pa = padicxx::randtest(state, ctx.pctx()); padicxx pb = padicxx::randtest(state, ctx.pctx()); qadicxx qa = qadicxx::from_ground(ctx, pa); qadicxx qb = qadicxx::from_ground(ctx, pb); tassert((qa + qb).to() == pa + pb); tassert((qa - qb).to() == pa - pb); tassert((qa * qb).to() == pa * pb); tassert((-qa).to() == -pa); } void test_functions() { qadicxx_ctx ctx(fmpzxx(5), 3, 10, 20, PADIC_TERSE); frandxx state; padicxx pa = padicxx::randtest_not_zero(state, ctx.pctx()); padicxx pb(padicxx::randtest_int(state, ctx.pctx()) * padicxx::from_QQ(5*5*5, ctx.pctx())); qadicxx qa = qadicxx::from_ground(ctx, pa); qadicxx qb = qadicxx::from_ground(ctx, pb); qadicxx qc = qadicxx::randtest_val(state, 5, ctx); tassert(qa.inv().to() == pa.inv()); tassert(qc.pow(fmpzxx(3)) == qc*qc*qc); tassert(qb.exp().to() == pb.exp()); tassert(qc.exp() == qc.exp_rectangular()); tassert(qc.exp() == qc.exp_balanced()); tassert((qadicxx::one(ctx) + qb).log().to() == (padicxx::one(ctx.pctx()) + pb).log()); qc += qadicxx::one(ctx); tassert(qc.log() == qc.log_balanced()); qadicxx res(ctx, PADIC_DEFAULT_PREC); qadic_frobenius(res._qadic(), qc._qadic(), 3, ctx._ctx()); tassert(res == qc.frobenius(3)); qadic_teichmuller(res._qadic(), qc._qadic(), ctx._ctx()); tassert(res == qc.teichmuller()); padicxx resp(ctx.pctx(), PADIC_DEFAULT_PREC); qadic_trace(resp._padic(), qc._qadic(), ctx._ctx()); tassert(resp == qc.trace()); qadic_norm(resp._padic(), qc._qadic(), ctx._ctx()); tassert(resp == qc.norm()); tassert(qc.norm() == qc.norm_analytic()); tassert(qc.norm() == qc.norm_resultant()); } // test stuff which we should get automatically - references etc void test_extras() { qadicxx_ctx ctx(fmpzxx(5), 3, 10, 20, PADIC_TERSE); qadicxx a(ctx); qadicxx b(ctx);b = 3u; qadicxx_ref ar(a); qadicxx_srcref asr(a); tassert(a == ar && ar == asr); ar = 3u; tassert(a == b && asr == b); tassert(ar + asr == a + a); tassert(qadicxx(ar) == ar); tassert(qadicxx(asr) == ar); } void test_prec() { qadicxx_ctx ctx(fmpzxx(5), 3, 10, 20, PADIC_TERSE); qadicxx a(ctx, 5), b(ctx, 7); qadicxx_ref ar(a); qadicxx_srcref br(b); tassert((a + a).prec() == 5); tassert((a + ar).prec() == 5); tassert((a + b).prec() == 7); tassert((a + br).prec() == 7); tassert((a.toN(15) + br.toN(10)).prec() == 15); } void test_printing() { qadicxx_ctx ctx(fmpzxx(5), 3, 10, 20, PADIC_TERSE); if(0) print(ctx); // make sure this compiles tassert_fprint_pretty(qadicxx::gen(ctx).pow(fmpzxx(2)), "x^2"); } int main() { std::cout << "qadicxx...."; test_init(); test_assignment(); test_conversion(); test_arithmetic(); test_functions(); test_extras(); test_prec(); test_printing(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-traits.cpp000066400000000000000000000104101414523752600176560ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flintxx/test/helpers.h" #include "flintxx/traits.h" #include "flintxx/mp.h" using namespace flint; using namespace traits; struct newtype { }; void test_integrality() { tassert(is_signed_integer::val == true); tassert(is_signed_integer::val == true); tassert(is_signed_integer::val == true); tassert(is_signed_integer::val == false); tassert(is_signed_integer::val == false); tassert(is_signed_integer::val == false); tassert(is_signed_integer::val == false); tassert(is_unsigned_integer::val == true); tassert(is_unsigned_integer::val == true); tassert(is_unsigned_integer::val == true); tassert(is_unsigned_integer::val == false); tassert(is_unsigned_integer::val == false); tassert(is_unsigned_integer::val == false); tassert(is_unsigned_integer::val == false); tassert(is_integer::val == true); tassert(is_integer::val == true); tassert(is_integer::val == true); tassert(is_integer::val == true); tassert(is_integer::val == true); tassert(is_integer::val == true); tassert(is_integer::val == false); tassert(is_string::val == false); tassert(is_string::val == true); tassert(is_string::val == true); tassert(is_string::val == true); tassert(fits_into_slong::val == true); tassert(fits_into_slong::val == true); tassert(fits_into_slong::val == false); tassert(fits_into_slong::val == true); tassert(fits_into_slong::val == true); tassert(fits_into_slong::val == true); tassert(fits_into_slong::val == true); tassert(fits_into_slong::val == false); typedef void function_type(int, int); tassert(fits_into_slong::val == false); } void test_manipulation() { using mp::equal_types; tassert((equal_types::type, int>::val)); tassert((equal_types::type, newtype&>::val)); tassert((equal_types::type, const newtype&>::val)); tassert((equal_types::type, const newtype&>::val)); tassert((equal_types::type, int&>::val)); tassert((equal_types::type, newtype&>::val)); tassert((equal_types::type, const slong&>::val)); tassert((equal_types::type, const int&>::val)); tassert((equal_types::type, const int>::val)); tassert((equal_types::type, const newtype&>::val)); tassert((equal_types::type, const slong>::val)); tassert((equal_types::type, const int&>::val)); tassert((equal_types::type, int>::val)); tassert((equal_types::type, newtype>::val)); tassert((equal_types::type, slong>::val)); tassert((equal_types::type, int>::val)); tassert((equal_types::type, int*>::val)); } class super { }; class sub : public super { }; void test_convertibility() { tassert((_is_convertible::val == true)); tassert((_is_convertible::val == false)); tassert((_is_convertible::val == false)); tassert((_is_convertible::val == true)); tassert((_is_convertible::val == true)); // Test the HACK. tassert((_is_convertible::val == false)); } int main() { std::cout << "traits...."; test_integrality(); test_manipulation(); test_convertibility(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-tuple.cpp000066400000000000000000000260141414523752600175100ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flintxx/test/helpers.h" #include "flintxx/tuple.h" #include "flintxx/mp.h" using namespace flint; using namespace mp; using namespace traits; void test_make() { typedef make_tuple make3; typedef make_tuple make2; typedef make_tuple make1; tassert((equal_types< make3::type, tuple > > >::val)); tassert((equal_types< make2::type, tuple > >::val)); tassert((equal_types >::val)); tassert(make3::type::len == 3); tassert(make2::type::len == 2); tassert(make1::type::len == 1); make3::type tup = make3::make(1, 'b', 3); tassert(tup.head == 1); tassert(tup.tail.head == 'b'); tassert(tup.tail.tail.head == 3); tup.first() = 2; tassert(tup.head == 2); tassert(tup.second() == 'b'); make2::type pair = make2::make(1, 'b'); tassert(pair.first() == 1); tassert(pair.second() == 'b'); make1::type singleton = make1::make(1); tassert(singleton.first() == 1); typedef make_tuple makeref; tassert((equal_types::val)); int a = 4; makeref::type reftup = makeref::make(a, a); tassert(reftup.head == 4); a = 5; tassert(reftup.second() == 5); } template struct type_n { int payload; type_n(int p) : payload(p) {}; }; template struct type_n { int payload; type_n(int p) : payload(p) {}; type_n() {}; }; void test_back() { typedef type_n<0> A; typedef type_n<1> B; typedef type_n<2> C; typedef type_n<3> D; typedef make_tuple make3; typedef make_tuple make3p; typedef make_tuple make2A; typedef make_tuple make2B; typedef back_tuple backvoid; typedef back_tuple backD; typedef back_tuple backA; typedef back_tuple backB; tassert((equal_types::val)); tassert((equal_types::val)); tassert((equal_types::val)); tassert((equal_types::val)); make3::type backing = make3::make(1, 2, 3); make3p::type pointers; backvoid::init(pointers, backing, 0); tassert(pointers.first()->payload == 1); backing.second() = 4; tassert(pointers.second()->payload == 4); A ret = 4; make2A::type backing2 = make2A::make(1, 2); backA::init(pointers, backing2, &ret); tassert(pointers.first()->payload == 4); tassert(pointers.second()->payload == 1); ret.payload = 5; backing2.head.payload = 6; tassert(pointers.first()->payload == 5); tassert(pointers.second()->payload == 6); // Test some corner cases. tassert((equal_types::type, empty_tuple>::val)); typedef tuple tup1_t; tassert((equal_types::type, empty_tuple>::val)); } void test_concat() { typedef type_n<0> A; typedef type_n<1> B; typedef type_n<2> C; typedef type_n<3> D; typedef type_n<4> E; typedef make_tuple make1st; typedef make_tuple make2nd; typedef concat_tuple concater; tassert((equal_types< concater::type, tuple > > >::val)); concater::type concated = concater::type(0, tuple >(1, tuple(2, make2nd::make(3, 4)))); make2nd::type second = concater::get_second(concated); tassert(second.first().payload == 3); tassert(second.second().payload == 4); make1st::type first = concater::get_first(concated); tassert(first.first().payload == 0); tassert(first.second().payload == 1); tassert(first.tail.second().payload == 2); first.first().payload = 17; second.first().payload = 18; concated = concater::doit(first, second); tassert(concated.first().payload == 17); tassert(concated.tail.tail.tail.head.payload == 18); // Test a few corner cases. tassert((equal_types< concat_tuple::type, empty_tuple >::val)); typedef tuple tup1_t; tassert((equal_types< concat_tuple::type, tup1_t >::val)); tassert((equal_types< concat_tuple::type, tup1_t >::val)); } namespace flint{ namespace detail { template struct fillit { static void doit(T& t, int start) { t.head.payload = start; detail::fillit::doit(t.tail, ++start); } }; template<> struct fillit { static void doit(empty_tuple e, int start) { } }; template struct values { static void doit(const T& t, std::set& values) { values.insert(t.head.payload); detail::values::doit(t.tail, values); } }; template<> struct values { static void doit(empty_tuple e, std::set& values) { } }; } } template void fillit(T& t, int start = 1) { detail::fillit::doit(t, start); } template std::set values(const T& t) { std::set ret; detail::values::doit(t, ret); return ret; } void test_merge() { typedef type_n<0, true> A; typedef type_n<1, true> B; typedef type_n<2, true> C; typedef type_n<3, true> D; typedef type_n<4, true> E; // Test that merging tuples and // yields something of length n, and that the constitutents can be // recovered. Also do other order. #define TEST32n(T1, T2, T3, U1, U2, n) \ { \ typedef make_tuple m1; \ typedef make_tuple m2; \ typedef merge_tuple merge1; \ typedef merge_tuple merge2; \ tassert(merge1::type::len == n); \ tassert(merge2::type::len == n); \ merge1::type merged1; \ { \ fillit(merged1); \ m1::type n1 = merge1::get_first(merged1); \ m2::type n2 = merge1::get_second(merged1); \ std::set vals1 = values(n1), vals2 = values(n2); \ vals1.insert(vals2.begin(), vals2.end()); \ tassert(vals1.size() == n); \ } \ merge2::type merged2; \ { \ fillit(merged2); \ m2::type n2 = merge2::get_first(merged2); \ m1::type n1 = merge2::get_second(merged2); \ std::set vals1 = values(n1), vals2 = values(n2); \ vals1.insert(vals2.begin(), vals2.end()); \ tassert(vals1.size() == n); \ } \ } TEST32n(A, B, C, A, B, 3); TEST32n(A, B, C, B, A, 3); TEST32n(A, B, C, A, C, 3); TEST32n(A, B, C, C, A, 3); TEST32n(A, B, C, C, B, 3); TEST32n(A, B, C, B, C, 3); TEST32n(A, A, A, A, A, 3); TEST32n(A, B, C, A, D, 4); TEST32n(A, B, C, B, D, 4); TEST32n(A, B, C, C, D, 4); TEST32n(A, B, C, D, A, 4); TEST32n(A, B, C, D, B, 4); TEST32n(A, B, C, D, C, 4); TEST32n(A, A, A, A, B, 4); TEST32n(A, B, C, D, E, 5); TEST32n(A, A, A, B, B, 5); typedef merge_tuple emptymerge; tassert((equal_types::val)); typedef merge_tuple::type, empty_tuple> anothermerge; tassert(anothermerge::type::len == 2); } void test_traits() { tassert((is_homogeneous_tuple::type, int>::val == true)); tassert((is_homogeneous_tuple::type, int>::val == false)); tassert(is_tuple::val == true); tassert(is_tuple::type>::val == true); tassert((is_tuple::type>::val == true)); tassert(is_tuple::val == false); } struct filler { template T create() const { if(mp::equal_types::val) return 1; return 0; } }; void test_htuples() { tassert((equal_types::type, make_homogeneous_tuple::type>::val)); typedef make_tuple maker; maker::type tpl = maker::make(1, 2, 3); tassert(htuples::extract<1>(tpl) == make_tuple::make(1)); tassert((htuples::extract<2>(tpl) == make_tuple::make(1, 2))); tassert((htuples::extract<3>(tpl) == make_tuple::make(1, 2, 3))); typedef make_tuple make2; tassert(htuples::removeres(tpl, 1) == make2::make(2, 3)); tassert(htuples::removeres(tpl, 2) == make2::make(1, 3)); tassert(htuples::removeres(tpl, 3) == make2::make(1, 2)); tassert(htuples::removeres(tpl, 4) == make2::make(1, 2)); typedef make_tuple maker3; tassert((maker3::make(0, 1, 0) == htuples::fill(filler()))); } void test_get() { typedef make_tuple::type tuple_t; int a, b; tuple_t t(17, make_tuple::type(a, make_tuple::type(b, empty_tuple()))); tassert((equal_types::type>::val)); tassert((equal_types::type>::val)); tassert((equal_types::type>::val)); tassert((tuple_get::get(t) == 17)); tuple_get::get(t) = 42; b = 3; tassert((tuple_get::get(t) == 3)); tassert(a == 42); const tuple_t ct(t); tuple_get::get(ct) = 17; tassert((tuple_get::get(ct) == 17)); } void test_set() { make_tuple::type tup; tup.set(make_tuple::make(1, 2, 3)); tassert((tup == make_tuple::make(1, 2, 3))); } void test_equals_elementwise() { tassert((make_tuple::make(1, 2, 3).equals_elementwise( make_tuple::make(1, 2, 3)))); tassert((!make_tuple::make(0, 2, 3).equals_elementwise( make_tuple::make(1, 2, 3)))); } int main() { std::cout << "tuple...."; test_make(); test_back(); test_concat(); test_merge(); test_traits(); test_htuples(); test_get(); test_set(); test_equals_elementwise(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/test/t-vector.cpp000066400000000000000000000042061414523752600176600ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flintxx/vector.h" #include "flintxx/test/helpers.h" #include "flintxx/test/myint.h" #include "fmpz_vecxx.h" using namespace flint; template struct tuple_has : mp::or_< mp::equal_types, tuple_has > { }; template struct tuple_has : mp::false_ { }; template bool has_vector_temporaries(const Expr& e) { return tuple_has::val; } template void test(const Vec& original, const char* str = "(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)") { Vec v(original); Vec w(original); Vec u(original); Vec x(original); for(slong i = 0;i < (slong) v.size();++i) { v[i] = i; w[i] = WORD(0); u[i] = 2*i; x[i] = 8*i; } tassert(v.to_string() == str); tassert(v == v); tassert(v != w); tassert(u == v + v); tassert(v == v + w); tassert(x == ((v + v) + (v + v)) + ((v + v) + (v + v))); tassert((v + w)[0] == v[0] + w[0]); if(!mp::equal_types::val) tassert(!has_vector_temporaries( ((v + v) + (v + v)) + ((v + v) + (v + v)))); } // b/c generic vector has no assignment implementation ... void test_fmpz_vecxx() { fmpz_vecxx a(10), b(10); a[0] = 1; tassert(a != b); a = b; tassert(a == b); } int main() { std::cout << "vector...."; typedef make_vector::type intvec; typedef make_vector_n::type intvec10; test(intvec(10)); test(intvec10()); test(fmpz_vecxx(10), "10 0 1 2 3 4 5 6 7 8 9"); test_fmpz_vecxx(); std::cout << "PASS" << std::endl; return 0; } flint2-2.8.4/flintxx/traits.h000066400000000000000000000106471414523752600161170ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_TRAITS_H #define CXX_TRAITS_H // only for true_/false_ #include "mp.h" namespace flint { namespace detail { template struct wrap { T t; }; } // detail namespace traits { /////////////////////// // BASIC TYPE TRAITS /////////////////////// // These helpers can be used to manipulate and inquire type information. // For example, given an arbitrary type T, one might be interested in knowing // if it is an integral type (int, short, ulong, etc). // // This file contains generic traits, not specific to FLINT. using mp::true_; using mp::false_; // Compute if T belongs to the signed integer types. template struct is_signed_integer : false_ { }; template<> struct is_signed_integer : true_ { }; template<> struct is_signed_integer : true_ { }; template<> struct is_signed_integer : true_ { }; template<> struct is_signed_integer : true_ { }; // Compute if T belongs to the unsigned integer types. template struct is_unsigned_integer : false_ { }; template<> struct is_unsigned_integer : true_ { }; template<> struct is_unsigned_integer : true_ { }; template<> struct is_unsigned_integer : true_ { }; template<> struct is_unsigned_integer : true_ { }; // Compute if T belongs to the signed or unsigned integer types template struct is_integer : mp::or_, is_signed_integer > { }; // Compute if T can always losslessly be converted into an slong template struct fits_into_slong : mp::false_ { }; template struct fits_into_slong >::type> : mp::or_< is_signed_integer, mp::and_v< is_unsigned_integer, sizeof(T) < sizeof(slong) > > { }; template struct fits_into_flint_bitcnt_t : is_unsigned_integer { }; // Compute if T is like const char* template struct is_string : mp::false_ { }; template<> struct is_string : mp::true_ { }; template<> struct is_string : mp::true_ { }; template struct is_string : mp::true_ { }; template struct is_string : mp::true_ { }; // Compute a type appropriate for forwarding T. This is just the appropriate // constant reference type (but avoids things like const (int&)&, which cause // syntax errors. template struct forwarding {typedef const T& type;}; template struct forwarding {typedef T& type;}; template struct forwarding {typedef const T& type;}; template struct forwarding >::type> { typedef T type; }; template struct forwarding {typedef T* type;}; template<> struct forwarding {typedef bool type;}; // Compute a type appropriate for referencing. Usually T&. template struct reference {typedef T& type;}; template struct reference {typedef T& type;}; template struct reference {typedef const T& type;}; // Add a constant qualification. In particular, turn T& into const T&. template struct make_const {typedef const T type;}; template struct make_const {typedef const T& type;}; // Strip const and reference type annotations. This does *not* strip pointers! template struct basetype {typedef T type;}; template struct basetype {typedef T type;}; template struct basetype {typedef T type;}; template struct basetype {typedef T type;}; struct no { int data[2]; }; typedef int yes; template detail::wrap fakeinstance(); // use with care template struct _is_convertible { private: static yes test(...) {return yes();} static no test(To) {return no();} public: static const bool val = (sizeof(test(fakeinstance().t)) != sizeof(yes)); }; // XXX HACK template struct _is_convertible : false_ { }; } // traits } // flint #endif flint2-2.8.4/flintxx/traits_fwd.h000066400000000000000000000014151414523752600167500ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FLINTXX_TRAITS_FWD_H #define FLINTXX_TRAITS_FWD_H // Use this to break cyclic dependencies, by forward-declaring traits. namespace flint { namespace traits { template struct is_fmpz_matxx; template struct is_fmpq_matxx; template struct is_fmpz_polyxx; template struct is_nmod_matxx; template struct is_nmod_polyxx; } // traits } // flint #endif flint2-2.8.4/flintxx/tuple.h000066400000000000000000000430401414523752600157330ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_TUPLE_H #define CXX_TUPLE_H #include "traits.h" namespace flint { /////////////////////////// // A general tuple class. /////////////////////////// // This simply stores a head and a tail. Conventionally, tuples a built by // nesting the tail. The last entry should be an empty_tuple (see below). // So e.g. a pair of integers would be tuple >. // // There are some helpers in the mp namespace below. namespace detail { struct FILLIT { }; } // detail namespace mp { namespace htuples { // Filling of tuples template Tuple fill(const Filler& f) { return Tuple(detail::FILLIT(), f); } } // htuples } // mp template struct tuple { Head head; Tail tail; typedef Head head_t; typedef Tail tail_t; static const unsigned len = 1 + Tail::len; // Obtain a reference to head (convenience name for pairs). typename traits::reference::type first() {return head;} typename traits::forwarding::type first() const {return head;} // Obtain a reference to the head of the tail (convenience name for pairs). typename traits::reference::type second() {return tail.head;} typename traits::forwarding::type second() const {return tail.head;} tuple() {}; tuple(typename traits::forwarding::type h, typename traits::forwarding::type t) : head(h), tail(t) { } bool operator==(const tuple& other) { return head == other.head && tail == other.tail; } template void set(const T& t) { head = t.head; tail.set(t.tail); } template void set(T& t) { head = t.head; tail.set(t.tail); } template bool equals_elementwise(const T& t) const { return head == t.head && tail.equals_elementwise(t.tail); } private: template tuple(detail::FILLIT fillit, const Filler& f) : head(f.template create()), tail(fillit, f) { } template friend Tuple mp::htuples::fill(const Filler&); template friend struct tuple; }; struct empty_tuple { struct empty { }; typedef empty head_t; typedef empty tail_t; empty head; empty tail; static const unsigned len = 0; bool operator==(const empty_tuple&) {return true;} empty_tuple() {} void set(empty_tuple) {} bool equals_elementwise(empty_tuple) const {return true;} private: template empty_tuple(detail::FILLIT fillit, const Filler& f) { } template friend Tuple mp::htuples::fill(const Filler&); template friend struct tuple; }; namespace detail { typedef void UNUSED; template struct maybe_forwarding { typedef typename traits::forwarding::type type; static type default_value(); }; template<> struct maybe_forwarding { typedef UNUSED* type; static type default_value() {return 0;} }; } namespace mp { // Helper to conveniently define tuple types, and marshall objects into // tuples. // Typical usage: // typedef make_tuple maker; // maker::type my_tuple = maker::make(1, 'a', WORD(2)); // TODO this would be a prime use for variadic templates ... #define FLINTXX_MAKE_TUPLE_TEMPLATE_ARGS \ class T1 = detail::UNUSED, class T2 = detail::UNUSED, \ class T3 = detail::UNUSED, class T4 = detail::UNUSED, \ class T5 = detail::UNUSED, class T6 = detail::UNUSED, \ class T7 = detail::UNUSED, class T8 = detail::UNUSED #define FLINTXX_MAKE_TUPLE_FUNC_ARGS \ typename detail::maybe_forwarding::type t1 \ = detail::maybe_forwarding::default_value(), \ typename detail::maybe_forwarding::type t2 \ = detail::maybe_forwarding::default_value(), \ typename detail::maybe_forwarding::type t3 \ = detail::maybe_forwarding::default_value(), \ typename detail::maybe_forwarding::type t4 \ = detail::maybe_forwarding::default_value(), \ typename detail::maybe_forwarding::type t5 \ = detail::maybe_forwarding::default_value(), \ typename detail::maybe_forwarding::type t6 \ = detail::maybe_forwarding::default_value(), \ typename detail::maybe_forwarding::type t7 \ = detail::maybe_forwarding::default_value(), \ typename detail::maybe_forwarding::type t8 \ = detail::maybe_forwarding::default_value() #define FLINTXX_MAKE_TUPLE_TYPES_APPLYMACRO(func) \ func(T1), func(T2), func(T3), func(T4), \ func(T5), func(T6), func(T7), func(T8) #define FLINTXX_MAKE_TUPLE_FUNC_ARG_NAMES t1, t2, t3, t4, t5, t6, t7, t8 template struct make_tuple { typedef make_tuple next; typedef typename next::type tail_t; typedef tuple type; static type make(FLINTXX_MAKE_TUPLE_FUNC_ARGS) { return type(t1, next::make(t2, t3, t4, t5, t6, t7, t8)); } }; template<> struct make_tuple { typedef detail::UNUSED* T; typedef empty_tuple type; // g++-4.4 bolts if we use (...), even though all arguments are PODs static empty_tuple make(T=0, T=0, T=0, T=0, T=0, T=0, T=0, T=0) {return empty_tuple();} }; // Indexified access template struct tuple_get { typedef tuple_get nget; typedef typename nget::type type; static typename traits::forwarding::type get(const Tuple& t) { return nget::get(t.tail); } static typename traits::reference::type get(Tuple& t) { return nget::get(t.tail); } }; template struct tuple_get { typedef typename Tuple::head_t type; static typename traits::forwarding::type get(const Tuple& t) { return t.head; } static typename traits::reference::type get(Tuple& t) { return t.head; } }; // Create a tuple backing a tuple of points. // That is to say, given a tuple like , // compute a backing tuple type . // // If one of the types in the tuple is Return*, do not back it // and instead feed it in separately. I.e. if Return is A*, then type // will be just . // // The static member init(to, from, ret) can be used to initalize the tuple // of pointers "to" to point to its backing in "from" and "ret". template struct back_tuple; // General case: non-empty tuple , and Return type cannot be // merged in. template struct back_tuple, Return> { typedef tuple::type> type; static void init(tuple& to, type& from, Return* ret = 0) { back_tuple::init(to.tail, from.tail, ret); to.head = &from.head; } }; // Merging case: non-empty tuple , and Return is Head* template struct back_tuple, Head> { typedef typename back_tuple::type type; static void init(tuple& to, type& from, Head* ret = 0) { to.head = ret; back_tuple::init(to.tail, from, 0 /* unused */ ); } }; // Base case: empty tuple; nothing to do. template struct back_tuple { typedef empty_tuple type; static void init(empty_tuple& to, type& from, Return* ret = 0) { } }; // Helper to concatenate two tuples. // // This has one member type, and three static member functions get_second, // get_first and doit. // "type" is a tuple type which can store the data of both Tuple1 and Tuple2. // Then, given an element of type "type", get_first and get_second can be used // to fill types Tuple1 and Tuple2. Note that get_second can return a constant // reference, whereas get_first has to do copying. // (But these copies should usually be inlined and optimized away by the // compiler.) // // Example: Tuple1 = , Tuple2 = . // Then type = // get_second(t) = t.tail.tail.tail // get_first(t) = tuple(t.head, tuple(t.tail.head, tuple( // t.tail.tail.head, empty_tuple()))); // template struct concat_tuple; // Degenerate case: Tuple1 is empty. template struct concat_tuple { typedef Tuple2 type; static const Tuple2& get_second(const Tuple2& t) {return t;} static empty_tuple get_first(const Tuple2& t) {return empty_tuple();} static type doit(const empty_tuple& t1, const Tuple2& t2) {return t2;} }; // General case: non-empty Tuple1. template struct concat_tuple, Tuple2> { typedef tuple::type> type; static const Tuple2& get_second(const type& t) { return concat_tuple::get_second(t.tail); } static tuple get_first(const type& o) { return tuple( o.head, concat_tuple::get_first(o.tail)); } static type doit(const tuple& t1, const Tuple2& t2) { return type(t1.head, concat_tuple::doit(t1.tail, t2)); } }; // Merging of tuples // // This takes two tuples, and computes a tuple type which can store either. // As usual, the extraction functions require copying which can be amortized // by the compiler. // template struct merge_tuple; //{ // typedef XYZ type; // Tuple1 get_first(const type& type); // Tuple2 get_second(const type& type); //}; // General case // NB: tail is *always* a sub-tuple of the second argument! template struct merge_tuple, Tuple2> { public: typedef merge_tuple comp1; typedef merge_tuple, typename comp1::tail_t> comp2; typedef concat_tuple concater; public: typedef typename concater::type type; // This is the part of type into which we can still merge. typedef typename comp2::tail_t tail_t; typedef typename concat_tuple< typename comp1::used_t, typename comp2::used_t >::type used_t; private: static typename comp1::type get_tail(const type& input) { typedef concat_tuple< typename comp1::used_t, typename comp1::tail_t > myconcat; return myconcat::doit(concater::get_first(input), comp2::get_second(concater::get_second(input))); } public: static tuple get_first(const type& input) { Head h = comp2::get_first(concater::get_second(input)).first(); return tuple(h, comp1::get_first(get_tail(input))); } static Tuple2 get_second(const type& input) { return comp1::get_second(get_tail(input)); } }; // First argument a singleton, no merging template struct merge_tuple, tuple > { private: typedef merge_tuple, Tail> comp; typedef concat_tuple< typename comp::used_t, tuple > concater; public: typedef typename comp::used_t used_t; typedef tuple tail_t; typedef typename concater::type type; private: static typename comp::type get_tail(const type& input) { typedef concat_tuple< typename comp::used_t, typename comp::tail_t > myconcat; return myconcat::doit(concater::get_first(input), concater::get_second(input).tail); } public: static tuple get_first(const type& input) { return comp::get_first(get_tail(input)); } static tuple get_second(const type& input) { return tuple( concater::get_second(input).head, comp::get_second(get_tail(input))); } }; // First argument a singleton, with merging template struct merge_tuple, tuple > { typedef tuple type; typedef tuple used_t; typedef Tail tail_t; static tuple get_first(const type& input) { return make_tuple::make(input.head); } static tuple get_second(const type& input) { return input; } }; // Termination case 1 template struct merge_tuple { typedef Tuple2 type; typedef type tail_t; typedef empty_tuple used_t; static empty_tuple get_first(const type& input) { return empty_tuple(); } static Tuple2 get_second(const type& input) { return input; } }; // It seems like this code path is unnecessary and in fact ambiguous. // I am fairly convinced by now this is correct. // However, in case issues ever come up, it seemed useful to me to retain this. // -- Tom Bachmann (15/10/2013) #if 0 // Termination case 2 template struct merge_tuple { typedef Tuple1 type; typedef type tail_t; typedef empty_tuple used_t; static Tuple1 get_first(const type& input) { return input; } static empty_tuple get_second(const type& input) { return empty_tuple(); } }; #endif // Termination case 3 template struct merge_tuple, empty_tuple> { typedef tuple type; typedef empty_tuple tail_t; // NB: we "use" T here - it cannot be merged into it any longer! typedef type used_t; static empty_tuple get_second(const type& input) { return empty_tuple(); } static tuple get_first(const type& input) { return input; } }; // Termination case 4 template<> struct merge_tuple { typedef empty_tuple type; typedef empty_tuple tail_t; typedef empty_tuple used_t; static empty_tuple get_first(const type& input) {return empty_tuple();} static empty_tuple get_second(const type& input) {return empty_tuple();} }; // Creation and manipulation of homogeneous tuples // Build a tuple type of "n" repetitions of "T". template struct make_homogeneous_tuple { typedef tuple::type> type; }; template struct make_homogeneous_tuple { typedef empty_tuple type; }; namespace htuples { namespace hdetail { template struct extract_helper { typedef typename Tuple::head_t T; typedef typename Tuple::tail_t tail_t; typedef typename make_homogeneous_tuple::type ht; static ht get_noskip(const Tuple& tuple) { return ht(tuple.head, extract_helper::get_noskip( tuple.tail)); } }; template struct extract_helper<0, Tuple> { static empty_tuple get_noskip(const Tuple&) {return empty_tuple();} }; template struct remove_helper { static const unsigned n = Tuple::len; typedef typename Tuple::tail_t tail_t; typedef typename Tuple::head_t T; static tail_t get(const Tuple& tuple, T res) { if(tuple.head == res) return tuple.tail; return tail_t(tuple.head, remove_helper::get(tuple.tail, res)); } }; template struct remove_helper > { static empty_tuple get(const tuple&, T) { return empty_tuple(); } }; } // hdetail // Extract the first "n" values from the *homogeneous* tuple "tuple". template inline typename make_homogeneous_tuple::type extract( const Tuple& tuple) { return hdetail::extract_helper::get_noskip(tuple); } // Remove one element from the *homogeneous* tuple "tuple", if possible "res". // Example: // t1 = (1, 2, 3, 4) // t2 = (1, 1, 1, 1) // t3 = (2, 3, 4, 5) // // removeres(t1, 1) -> (2, 3, 4) // removeres(t2, 1) -> (1, 1, 1) // removeres(t3, 1) -> (2, 3, 4) or any other three element subset template inline typename Tuple::tail_t removeres(const Tuple& tuple, typename Tuple::head_t res) { return hdetail::remove_helper::get(tuple, res); } } // htuples } // mp namespace traits { // Compute if "Tuple" is of the form (U, U, .. U), or empty. template struct is_homogeneous_tuple : mp::and_< is_homogeneous_tuple, mp::equal_types > { }; template struct is_homogeneous_tuple : true_ { }; // Compute if T is a tuple template struct is_tuple : false_ { }; template struct is_tuple > : true_ { }; template<> struct is_tuple : true_ { }; } } // flint #endif flint2-2.8.4/flintxx/vector.h000066400000000000000000000305041414523752600161050ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // Sketch of a generic vector class. #ifndef CXX_VECTOR_H #define CXX_VECTOR_H #include #include #include "expression.h" #include "evaluation_tools.h" #include "ltuple.h" #include "mp.h" namespace flint { FLINT_DEFINE_BINOP(vector_at) template class vector_expression; namespace detail { template struct vector_wrapper : derived_wrapper2 { }; template struct vector_at_traits { typedef FLINT_BINOP_ENABLE_RETTYPE(vector_at, Expr, Idx) ref_t; typedef ref_t cref_t; static ref_t at(const Expr& v, Idx i) {return vector_at(v, i);} }; template struct vector_at_traits : Traits { }; } template class vector_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef typename Underlying_traits::ref_t ref_t; typedef typename Underlying_traits::cref_t cref_t; typedef typename Underlying_traits::idx_t idx_t; typedef typename Underlying_traits::underlying_t underlying_t; typedef typename Underlying_traits::arrayref_t arrayref_t; typedef typename Underlying_traits::arraysrcref_t arraysrcref_t; vector_expression() {} template explicit vector_expression(const T& t) : base_t(t) {} template vector_expression(const T& t, const U& u) : base_t(t, u) {} template vector_expression(const T& t, const U& u, const V& v) : base_t(t, u, v) {} template vector_expression& operator=(const T& t) { this->set(t); return *this; } template typename detail::vector_at_traits::ref_t operator[](Idx idx) { return detail::vector_at_traits::at(*this, idx); } template typename detail::vector_at_traits::cref_t operator[](Idx idx) const { return detail::vector_at_traits::at(*this, idx); } idx_t size() const {return Underlying_traits::size(*this);} arrayref_t _array() {return Underlying_traits::array(*this);} arraysrcref_t _array() const {return Underlying_traits::array(*this);} typename base_t::evaluated_t create_temporary() const { return Underlying_traits::create_temporary(*this); } protected: explicit vector_expression(const Data& d) : base_t(d) {} template friend class expression; }; namespace vectors { // Similar to matrices, the size of a vector expression has to be known in // order to allocate temporary objects. In this case, the generic // implementation looks for any vector immediate subexpression and returs its // size. This makes sense since mixing vectors of differing sizes usually makes // no sense. // Thus specialisation is usually only necessary in constructor-like operations, // which do not involve vector immediates. template struct outsize { template static unsigned get(const Expr& e) { return tools::find_subexpr_T(e)._data().size; } }; // Hack for ltuple_get, similar to the matrices case. template struct outsize > { template static unsigned get(const Expr& e) { return outsize::get( e._data().head); } }; } namespace detail { template struct basic_vector_traits { typedef unsigned idx_t; typedef Ref ref_t; typedef const Cref cref_t; typedef T underlying_t; typedef ArrayT* arrayref_t; typedef const ArrayT* arraysrcref_t; template static ref_t at(Expr& e, unsigned i) { return e.evaluate()._data().array[i]; } template static cref_t at(const Expr& e, unsigned i) { return e.evaluate()._data().array[i]; } template static arrayref_t array(Expr& e) { return e.evaluate()._data().array; } template static arraysrcref_t array(const Expr& e) { return e.evaluate()._data().array; } }; template struct rtfixed_size_traits : basic_vector_traits { template static unsigned size(const Expr& e) { return vectors::outsize::get(e); } template static typename Expr::evaluated_t create_temporary(const Expr& e) { return typename Expr::evaluated_t(e.size()); } }; template struct fixed_size_traits : basic_vector_traits { template static unsigned size(const Expr& e) { return Expr::evaluated_t::data_t::size; } template static typename Expr::evaluated_t create_temporary(const Expr& e) { return typename Expr::evaluated_t(); } }; template struct wrapped_vector_traits : rtfixed_size_traits { typedef Size idx_t; template static Ref at(Expr& e, idx_t i) { return e.evaluate()._data().at(i); } template static Cref at(const Expr& e, idx_t i) { return e.evaluate()._data().at(i); } }; template struct rtfixed_size_data { const unsigned size; T* array; rtfixed_size_data(unsigned n) : size(n), array(new T[n]) {} ~rtfixed_size_data() {delete[] array;} rtfixed_size_data(const rtfixed_size_data& o) : size(o.size) { // TODO this is very non-optimal ... (?) array = new T[size]; for(unsigned i = 0;i < size;++i) { array[i] = o.array[i]; } } }; template struct fixed_size_data { static const unsigned size = n; T array[n]; }; } // detail template struct make_vector { typedef vector_expression, operations::immediate, detail::rtfixed_size_data > type; }; template struct make_vector_n { typedef vector_expression, operations::immediate, detail::fixed_size_data > type; }; template struct enable_vector_rules : mp::false_ { }; template struct enable_vector_rules< vector_expression > : mp::true_ { }; namespace rules { // temporary allocation inside ltuples template struct instantiate_temporaries, vector_expression > { typedef ltuple_expression Expr; typedef vector_expression T; static T get(const Expr& e) { return T(vectors::outsize::get(e)); } }; template struct binary_expression, operations::vector_at_op, T> { typedef typename Traits::underlying_t return_t; template static void doit(V& to, const vector_expression& v, T i) { to = Traits::at(v, i); } }; template struct to_string, traits::is_implemented > > >::type> { static std::string get(const Expr& e, int base) { // TODO inefficient std::string res = "("; for(typename Expr::idx_t i = 0;i < e.size();++i) { res += e[i].to_string(); if(i != e.size() - 1) res += ", "; } res += ")"; return res; } }; template struct equals >::type> { static bool get(const Expr& e1, const Expr& e2) { if(e1.size() != e2.size()) return false; for(typename Expr::idx_t i = 0;i < e1.size();++i) if(e1[i] != e2[i]) return false; return true; } }; namespace rvdetail { template struct translate_data; template struct translate_expr { typedef translate_data trdata_t; typedef typename Expr::underlying_t ul_t; typedef typename ul_t::template make_helper< typename Expr::operation_t, typename trdata_t::type> make_helper; typedef typename make_helper::type type; template static type make(const Expr& e, Idx idx) { return make_helper::make(trdata_t::make(e._data(), idx)); } }; template struct translate_expr >::type> { typedef typename Expr::cref_t type; template static type make(const Expr& e, Idx idx) { return e[idx]; } }; template struct translate_data > { typedef translate_expr::type> trexpr; typedef translate_data trtail; typedef tuple type; template static type make(const tuple& e, Idx idx) { return type(trexpr::make(e.head, idx), trtail::make(e.tail, idx)); } }; template<> struct translate_data { typedef empty_tuple type; template static type make(empty_tuple, Idx) {return empty_tuple();} }; template struct enable_evaluation : mp::false_ {typedef void vector_t;}; template struct enable_evaluation::type> >::type> : enable_vector_rules::type::evaluated_t> { typedef typename traits::basetype::type::evaluated_t vector_t; }; template struct enable_evaluation > : mp::and_, enable_evaluation > { typedef typename enable_evaluation::vector_t vector_t; }; template<> struct enable_evaluation : mp::true_ { }; } //rvdetail // TODO this is a bit greedy .. template struct evaluation >::type> { typedef rvdetail::translate_data translator; typedef typename translator::type trdata_t; typedef typename mp::find_evaluation< Op, trdata_t, result_is_temporary>::type rule_t; typedef typename rvdetail::enable_evaluation::vector_t vector_t; typedef typename vector_t::evaluated_t return_t; // TODO typedef typename rule_t::temporaries_t temporaries_t; typedef typename rule_t::return_t trreturn_t; template static void doit(const Data& input, temporaries_t temps, Return* output) { for(typename return_t::idx_t i = 0;i < output->size();++i) { rule_t::doit(translator::make(input, i), temps, &((*output)[i])); } } }; // TODO scalar multiplication etc } // rules } // flint #endif flint2-2.8.4/fmpq.h000066400000000000000000000404461414523752600140600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPQ_H #define FMPQ_H #ifdef FMPQ_INLINES_C #define FMPQ_INLINE FLINT_DLL #else #define FMPQ_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #ifdef __cplusplus extern "C" { #endif typedef struct { fmpz num; fmpz den; } fmpq; typedef fmpq fmpq_t[1]; #define fmpq_numref(__x) (&(__x)->num) #define fmpq_denref(__y) (&(__y)->den) 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) { fmpz_swap(fmpq_numref(op1), fmpq_numref(op2)); fmpz_swap(fmpq_denref(op1), fmpq_denref(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)); } FLINT_DLL int _fmpq_cmp(const fmpz_t p, const fmpz_t q, const fmpz_t r, const fmpz_t s); FLINT_DLL int fmpq_cmp(const fmpq_t x, const fmpq_t y); FLINT_DLL int _fmpq_cmp_fmpz(const fmpz_t p, const fmpz_t q, const fmpz_t r); FLINT_DLL int fmpq_cmp_fmpz(const fmpq_t x, const fmpz_t y); FLINT_DLL int _fmpq_cmp_ui(const fmpz_t p, const fmpz_t q, ulong c); FLINT_DLL int fmpq_cmp_ui(const fmpq_t x, ulong c); FLINT_DLL int _fmpq_cmp_si(const fmpz_t p, const fmpz_t q, slong c); FLINT_DLL int fmpq_cmp_si(const fmpq_t x, slong c); FLINT_DLL void _fmpq_canonicalise(fmpz_t num, fmpz_t den); FLINT_DLL void fmpq_canonicalise(fmpq_t res); FLINT_DLL int _fmpq_is_canonical(const fmpz_t num, const fmpz_t den); FLINT_DLL int fmpq_is_canonical(const fmpq_t x); FLINT_DLL void _fmpq_set_ui(fmpz_t rnum, fmpz_t rden, ulong p, ulong q); FLINT_DLL void fmpq_set_ui(fmpq_t res, ulong p, ulong q); FLINT_DLL void _fmpq_set_si(fmpz_t rnum, fmpz_t rden, slong p, ulong q); FLINT_DLL void fmpq_set_si(fmpq_t res, slong p, ulong q); FMPQ_INLINE int fmpq_equal_ui(fmpq_t q, slong 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); } FLINT_DLL void fmpq_set_fmpz_frac(fmpq_t res, const fmpz_t p, const fmpz_t q); FLINT_DLL 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)); } FLINT_DLL double fmpq_get_d(const fmpq_t a); FLINT_DLL int fmpq_get_mpfr(mpfr_t r, const fmpq_t x, mpfr_rnd_t rnd); FLINT_DLL void fmpq_get_mpz_frac(mpz_t a, mpz_t b, fmpq_t c); FLINT_DLL void flint_mpq_init_set_readonly(mpq_t z, const fmpq_t f); FLINT_DLL void flint_mpq_clear_readonly(mpq_t z); FLINT_DLL void fmpq_init_set_readonly(fmpq_t f, const mpq_t z); FLINT_DLL void fmpq_clear_readonly(fmpq_t f); FLINT_DLL void fmpq_init_set_mpz_frac_readonly(fmpq_t z, const mpz_t num, const mpz_t den); FLINT_DLL char * _fmpq_get_str(char * str, int b, const fmpz_t num, const fmpz_t den); FLINT_DLL char * fmpq_get_str(char * str, int b, const fmpq_t x); FLINT_DLL int _fmpq_fprint(FILE * file, const fmpz_t num, const fmpz_t den); FLINT_DLL int fmpq_fprint(FILE * file, const fmpq_t x); FMPQ_INLINE int _fmpq_print(const fmpz_t num, const fmpz_t den) { return _fmpq_fprint(stdout, num, den); } FMPQ_INLINE int fmpq_print(const fmpq_t x) { return fmpq_fprint(stdout, x); } FLINT_DLL void _fmpq_randtest(fmpz_t num, fmpz_t den, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void fmpq_randtest(fmpq_t res, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void fmpq_randtest_not_zero(fmpq_t res, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void _fmpq_randbits(fmpz_t num, fmpz_t den, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void fmpq_randbits(fmpq_t res, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void _fmpq_add_small(fmpz_t rnum, fmpz_t rden, slong p1, ulong q1, slong p2, ulong q2); FLINT_DLL void _fmpq_mul_small(fmpz_t rnum, fmpz_t rden, slong p1, ulong q1, slong p2, ulong q2); FLINT_DLL 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); FLINT_DLL void fmpq_add(fmpq_t res, const fmpq_t op1, const fmpq_t op2); FLINT_DLL void _fmpq_add_si(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, slong r); FLINT_DLL void fmpq_add_si(fmpq_t res, const fmpq_t op1, slong c); FLINT_DLL void _fmpq_add_ui(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, ulong r); FLINT_DLL void fmpq_add_ui(fmpq_t res, const fmpq_t op1, ulong c); FLINT_DLL void _fmpq_add_fmpz(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r); FLINT_DLL void fmpq_add_fmpz(fmpq_t res, const fmpq_t op1, const fmpz_t c); FLINT_DLL 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); FLINT_DLL void fmpq_sub(fmpq_t res, const fmpq_t op1, const fmpq_t op2); FLINT_DLL void _fmpq_sub_si(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, slong r); FLINT_DLL void fmpq_sub_si(fmpq_t res, const fmpq_t op1, slong c); FLINT_DLL void _fmpq_sub_ui(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, ulong r); FLINT_DLL void fmpq_sub_ui(fmpq_t res, const fmpq_t op1, ulong c); FLINT_DLL void _fmpq_sub_fmpz(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, const fmpz_t r); FLINT_DLL void fmpq_sub_fmpz(fmpq_t res, const fmpq_t op1, const fmpz_t c); FLINT_DLL void _fmpq_mul_si(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, slong r); FLINT_DLL void fmpq_mul_si(fmpq_t res, const fmpq_t op1, slong c); FLINT_DLL void _fmpq_mul_ui(fmpz_t rnum, fmpz_t rden, const fmpz_t p, const fmpz_t q, ulong r); FLINT_DLL void fmpq_mul_ui(fmpq_t res, const fmpq_t op1, ulong c); FLINT_DLL 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); FLINT_DLL void fmpq_mul(fmpq_t res, const fmpq_t op1, const fmpq_t op2); FLINT_DLL void fmpq_mul_fmpz(fmpq_t res, const fmpq_t op, const fmpz_t x); FLINT_DLL void _fmpq_pow_si(fmpz_t rnum, fmpz_t rden, const fmpz_t opnum, const fmpz_t opden, slong e); FLINT_DLL void fmpq_pow_si(fmpq_t rop, const fmpq_t op, slong e); FLINT_DLL int fmpq_pow_fmpz(fmpq_t a, const fmpq_t b, const fmpz_t e); FLINT_DLL 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); FLINT_DLL void fmpq_addmul(fmpq_t res, const fmpq_t op1, const fmpq_t op2); FLINT_DLL 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); FLINT_DLL void fmpq_submul(fmpq_t res, const fmpq_t op1, const fmpq_t op2); FLINT_DLL void fmpq_inv(fmpq_t dest, const fmpq_t src); FLINT_DLL 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); FLINT_DLL void fmpq_div(fmpq_t res, const fmpq_t op1, const fmpq_t op2); FLINT_DLL void fmpq_div_fmpz(fmpq_t res, const fmpq_t op, const fmpz_t x); FLINT_DLL void fmpq_mul_2exp(fmpq_t res, const fmpq_t x, flint_bitcnt_t exp); FLINT_DLL void fmpq_div_2exp(fmpq_t res, const fmpq_t x, flint_bitcnt_t exp); FLINT_DLL int _fmpq_mod_fmpz(fmpz_t res, const fmpz_t num, const fmpz_t den, const fmpz_t mod); FLINT_DLL int fmpq_mod_fmpz(fmpz_t res, const fmpq_t x, const fmpz_t mod); FMPQ_INLINE 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); } FMPQ_INLINE 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_DLL 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); FMPQ_INLINE 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_DLL int _fmpq_reconstruct_fmpz(fmpz_t num, fmpz_t den, const fmpz_t a, const fmpz_t m); FLINT_DLL int fmpq_reconstruct_fmpz(fmpq_t res, const fmpz_t a, const fmpz_t m); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_DLL flint_bitcnt_t fmpq_height_bits(const fmpq_t x); FLINT_DLL void fmpq_height(fmpz_t height, const fmpq_t x); FLINT_DLL void _fmpq_next_calkin_wilf(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den); FLINT_DLL void fmpq_next_calkin_wilf(fmpq_t res, const fmpq_t x); FLINT_DLL void _fmpq_next_signed_calkin_wilf(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den); FLINT_DLL void fmpq_next_signed_calkin_wilf(fmpq_t res, const fmpq_t x); FLINT_DLL void _fmpq_next_minimal(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den); FLINT_DLL void fmpq_next_minimal(fmpq_t res, const fmpq_t x); FLINT_DLL void _fmpq_next_signed_minimal(fmpz_t rnum, fmpz_t rden, const fmpz_t num, const fmpz_t den); FLINT_DLL void fmpq_next_signed_minimal(fmpq_t res, const fmpq_t x); FLINT_DLL void fmpq_farey_neighbors(fmpq_t left, fmpq_t right, const fmpq_t mid, const fmpz_t Q); FLINT_DLL void fmpq_simplest_between(fmpq_t mid, const fmpq_t l, const fmpq_t r); FLINT_DLL 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); FLINT_DLL slong fmpq_get_cfrac_naive(fmpz * c, fmpq_t rem, const fmpq_t x, slong n); FLINT_DLL slong fmpq_get_cfrac(fmpz * c, fmpq_t rem, const fmpq_t x, slong n); FLINT_DLL void fmpq_set_cfrac(fmpq_t x, const fmpz * c, slong n); FLINT_DLL slong fmpq_cfrac_bound(const fmpq_t x); FLINT_DLL void fmpq_dedekind_sum_naive(fmpq_t s, const fmpz_t h, const fmpz_t k); FLINT_DLL void fmpq_dedekind_sum(fmpq_t s, const fmpz_t h, const fmpz_t k); FLINT_DLL void _fmpq_harmonic_ui(fmpz_t num, fmpz_t den, ulong n); FLINT_DLL void fmpq_harmonic_ui(fmpq_t x, ulong n); FLINT_DLL fmpq * _fmpq_vec_init(slong len); FMPQ_INLINE void _fmpq_vec_clear(fmpq * vec, slong len) { _fmpz_vec_clear((fmpz *) vec, 2 * len); } /*********************** 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]; FLINT_DLL void _fmpz_mat22_init(_fmpz_mat22_t M); FLINT_DLL void _fmpz_mat22_clear(_fmpz_mat22_t M); FLINT_DLL void _fmpz_mat22_one(_fmpz_mat22_t M); FLINT_DLL int _fmpz_mat22_is_one(_fmpz_mat22_t M); FLINT_DLL flint_bitcnt_t _fmpz_mat22_bits(const _fmpz_mat22_t N); FLINT_DLL void _fmpz_mat22_rmul(_fmpz_mat22_t M, const _fmpz_mat22_t N); FLINT_DLL void _fmpz_mat22_rmul_ui(_fmpz_mat22_t M, const _ui_mat22_t N); FLINT_DLL void _fmpz_mat22_rmul_inv_ui(_fmpz_mat22_t M, const _ui_mat22_t N); FLINT_DLL void _fmpz_mat22_rmul_elem(_fmpz_mat22_t M, const fmpz_t q); FLINT_DLL void _fmpz_mat22_rmul_inv_elem(_fmpz_mat22_t M, const fmpz_t q); FLINT_DLL 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]; FLINT_DLL void _fmpq_cfrac_list_init(_fmpq_cfrac_list_t v); FLINT_DLL void _fmpq_cfrac_list_clear(_fmpq_cfrac_list_t v); FLINT_DLL void _fmpq_cfrac_list_fit_length(_fmpq_cfrac_list_t v, slong len); FLINT_DLL void _fmpq_cfrac_list_push_back(_fmpq_cfrac_list_t v, const fmpz_t a); FLINT_DLL void _fmpq_cfrac_list_push_back_zero(_fmpq_cfrac_list_t v); FLINT_DLL void _fmpq_cfrac_list_append_ui(_fmpq_cfrac_list_t v, const ulong * a, slong n); FMPQ_INLINE void _fmpq_cfrac_list_swap(_fmpq_cfrac_list_t a, _fmpq_cfrac_list_t b) { _fmpq_cfrac_list_struct t = *a; *a = *b; *b = t; } /*************** 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]; FLINT_DLL void _fmpq_ball_init(_fmpq_ball_t x); FLINT_DLL void _fmpq_ball_clear(_fmpq_ball_t x); FMPQ_INLINE void _fmpq_ball_swap(_fmpq_ball_t x, _fmpq_ball_t y) { _fmpq_ball_struct t = *x; *x = *y; *y = t; } FLINT_DLL int _fmpq_ball_gt_one(const _fmpq_ball_t x); FLINT_DLL void _fmpq_hgcd(_fmpq_cfrac_list_t s, _fmpz_mat22_t M, fmpz_t x_num, fmpz_t x_den); FLINT_DLL void _fmpq_ball_get_cfrac(_fmpq_cfrac_list_t s, _fmpz_mat22_t M, int needM, _fmpq_ball_t x); /* Inlines *******************************************************************/ FLINT_DLL void fmpq_numerator(fmpz_t n, const fmpq_t q); FLINT_DLL void fmpq_denominator(fmpz_t n, const fmpq_t q); FLINT_DLL fmpz * fmpq_numerator_ptr(fmpq_t q); FLINT_DLL fmpz * fmpq_denominator_ptr(fmpq_t q); FLINT_DLL int fmpq_equal_fmpz(fmpq_t q, fmpz_t n); #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpq/000077500000000000000000000000001414523752600136775ustar00rootroot00000000000000flint2-2.8.4/fmpq/add.c000066400000000000000000000064211414523752600145760ustar00rootroot00000000000000/* Copyright (C) 2011, 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" 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)); } flint2-2.8.4/fmpq/add_fmpz.c000066400000000000000000000024371414523752600156350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" 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); } flint2-2.8.4/fmpq/add_si.c000066400000000000000000000025401414523752600152670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" 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); } flint2-2.8.4/fmpq/add_small.c000066400000000000000000000106041414523752600157640ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq/add_ui.c000066400000000000000000000024011414523752600152650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" 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); } flint2-2.8.4/fmpq/addmul.c000066400000000000000000000017121414523752600153120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/fmpq/ball.c000066400000000000000000000013401414523752600147530ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpq/canonicalise.c000066400000000000000000000017041414523752600164750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/fmpq/cfrac_bound.c000066400000000000000000000011561414523752600163130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq/clear_readonly.c000066400000000000000000000010171414523752600170250ustar00rootroot00000000000000/* 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 2.1 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)); } flint2-2.8.4/fmpq/cmp.c000066400000000000000000000024371414523752600146300ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 (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; if (s1 == 0) return -s2; if (s2 == 0) return -s1; 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; 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)); } flint2-2.8.4/fmpq/cmp_fmpz.c000066400000000000000000000022371414523752600156620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" int _fmpq_cmp_fmpz(const fmpz_t p, const fmpz_t q, const fmpz_t r) { int s1, s2, res; flint_bitcnt_t bp, bq, br, bs; fmpz_t u; if (fmpz_is_one(q)) return fmpz_cmp(p, r); s1 = fmpz_sgn(p); s2 = fmpz_sgn(r); if (s1 != s2) return s1 < s2 ? -1 : 1; if (s1 == 0) return -s2; if (s2 == 0) return -s1; bp = fmpz_bits(p); bq = fmpz_bits(q); br = fmpz_bits(r); bs = 1; if (bp + bs + 1 < br + bq) return -s1; if (bp + bs > br + bq + 1) return s1; fmpz_init(u); fmpz_mul(u, q, r); res = fmpz_cmp(p, u); fmpz_clear(u); return res; } int fmpq_cmp_fmpz(const fmpq_t x, const fmpz_t y) { return _fmpq_cmp_fmpz(fmpq_numref(x), fmpq_denref(x), y); } flint2-2.8.4/fmpq/cmp_si.c000066400000000000000000000024111414523752600153130ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2016, 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" 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); 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); } flint2-2.8.4/fmpq/cmp_ui.c000066400000000000000000000022321414523752600153160ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" 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); s1 = fmpz_sgn(p); s2 = (c > 0); if (s1 != s2) return s1 < s2 ? -1 : 1; if (s1 == 0) return -s2; if (s2 == 0) return -s1; 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); } flint2-2.8.4/fmpq/dedekind_sum.c000066400000000000000000000077541414523752600165130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #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 */ } flint2-2.8.4/fmpq/dedekind_sum_naive.c000066400000000000000000000027761414523752600176740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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, r1, q2, r2; if (fmpz_is_zero(k)) { fmpq_zero(s); return; } fmpz_init(i); fmpz_init(j); fmpz_init(q1); fmpz_init(r1); 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_qr(q1, r1, i, k); if (fmpz_is_zero(r1)) continue; 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(r1); fmpz_clear(q2); fmpz_clear(r2); } flint2-2.8.4/fmpq/div.c000066400000000000000000000030671414523752600146330ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (fmpq_div). Division by zero.\n"); flint_abort(); } _fmpq_div(fmpq_numref(res), fmpq_denref(res), fmpq_numref(op1), fmpq_denref(op1), fmpq_numref(op2), fmpq_denref(op2)); } flint2-2.8.4/fmpq/div_2exp.c000066400000000000000000000017031414523752600155640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } } flint2-2.8.4/fmpq/div_fmpz.c000066400000000000000000000024061414523752600156630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" void fmpq_div_fmpz(fmpq_t res, const fmpq_t op, const fmpz_t x) { fmpz_t y; if (fmpz_is_zero(x)) { flint_printf("Exception (fmpq_div_fmpz). Division by zero.\n"); flint_abort(); } 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)); } } flint2-2.8.4/fmpq/farey_neighbors.c000066400000000000000000000044241414523752600172150ustar00rootroot00000000000000/* 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 2.1 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; /* 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); /* 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))) { fmpz_clear(fmpq_numref(mid)); fmpz_clear(fmpq_denref(mid)); fmpz_clear(Q); fmpz_clear(t); flint_throw(FLINT_ERROR, "Exception in fmpq_farey_neighbors: bad input"); } 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); } flint2-2.8.4/fmpq/fmpz_vector.c000066400000000000000000000071651414523752600164120ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpq/fprint.c000066400000000000000000000025331414523752600153500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" /* 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.'' */ FLINT_DLL 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); } flint2-2.8.4/fmpq/gcd_cofactors.c000066400000000000000000000036201414523752600166440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq/get_cfrac.c000066400000000000000000000067561414523752600157760ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq/get_cfrac_helpers.c000066400000000000000000001014241414523752600175040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #include "longlong.h" #include "fmpq.h" #include "fmpz_poly.h" #include "mpn_extras.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; count_leading_zeros(x_lzcnt, 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_MPZ_PTR_SWAP(xn, yn); FLINT_MPZ_PTR_SWAP(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; count_leading_zeros(x_lzcnt, 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_MPZ_PTR_SWAP(xln, yln); FLINT_MPZ_PTR_SWAP(xld, yld); FLINT_MPZ_PTR_SWAP(xrn, yrn); FLINT_MPZ_PTR_SWAP(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); 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); } 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); if (N->det == 1) { fmpz_addmul(x->left_num, N->_22, q); fmpz_submul(x->left_num, N->_12, r); fmpz_addmul(x->left_den, N->_11, r); fmpz_submul(x->left_den, N->_21, q); } else { FLINT_ASSERT(N->det == -1); fmpz_addmul(x->left_num, N->_12, r); fmpz_submul(x->left_num, N->_22, q); fmpz_addmul(x->left_den, N->_21, q); fmpz_submul(x->left_den, N->_11, 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) */ if (N->det == 1) { fmpz_one(r); fmpz_mul_2exp(r, r, k); fmpz_fdiv_r_2exp(q, x->left_den, k); fmpz_sub(r, r, q); fmpz_fdiv_r_2exp(q, x->left_num, k); fmpz_mul_2exp(x->left_num, y->left_num, k); fmpz_addmul(x->left_num, q, N->_22); fmpz_addmul(x->left_num, r, N->_12); fmpz_mul_2exp(x->left_den, y->left_den, k); fmpz_submul(x->left_den, q, N->_21); fmpz_submul(x->left_den, r, N->_11); fmpz_one(q); fmpz_mul_2exp(q, q, k); fmpz_fdiv_r_2exp(r, x->right_num, k); fmpz_sub(q, q, r); fmpz_fdiv_r_2exp(r, x->right_den, k); fmpz_mul_2exp(x->right_num, y->right_num, k); fmpz_submul(x->right_num, q, N->_22); fmpz_submul(x->right_num, r, N->_12); fmpz_mul_2exp(x->right_den, y->right_den, k); fmpz_addmul(x->right_den, q, N->_21); fmpz_addmul(x->right_den, r, N->_11); } else { FLINT_ASSERT(N->det == -1); fmpz_one(r); fmpz_mul_2exp(r, r, k); fmpz_fdiv_r_2exp(q, x->left_den, k); fmpz_sub(r, r, q); fmpz_fdiv_r_2exp(q, x->left_num, k); fmpz_mul_2exp(x->left_num, y->right_num, k); fmpz_submul(x->left_num, q, N->_22); fmpz_submul(x->left_num, r, N->_12); fmpz_mul_2exp(x->left_den, y->right_den, k); fmpz_addmul(x->left_den, q, N->_21); fmpz_addmul(x->left_den, r, N->_11); fmpz_one(q); fmpz_mul_2exp(q, q, k); fmpz_fdiv_r_2exp(r, x->right_num, k); fmpz_sub(q, q, r); fmpz_fdiv_r_2exp(r, x->right_den, k); fmpz_mul_2exp(x->right_num, y->left_num, k); fmpz_addmul(x->right_num, q, N->_22); fmpz_addmul(x->right_num, r, N->_12); fmpz_mul_2exp(x->right_den, y->left_den, k); fmpz_submul(x->right_den, q, N->_21); fmpz_submul(x->right_den, r, N->_11); fmpz_swap(x->right_num, x->left_num); fmpz_swap(x->right_den, x->left_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; } flint2-2.8.4/fmpq/get_d.c000066400000000000000000000010761414523752600151310ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq/get_mpfr.c000066400000000000000000000021241414523752600156450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq/get_mpz_frac.c000066400000000000000000000010611414523752600165010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gmp.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)); } flint2-2.8.4/fmpq/get_str.c000066400000000000000000000021231414523752600155100ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (_fmpq_get_str). Not enough memory.\n"); flint_abort(); } } 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)); } flint2-2.8.4/fmpq/harmonic_ui.c000066400000000000000000000154161414523752600163470ustar00rootroot00000000000000/* 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 2.1 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_abort(); 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); } flint2-2.8.4/fmpq/height.c000066400000000000000000000011361414523752600153140ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/fmpq/height_bits.c000066400000000000000000000011051414523752600163310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq/init_set_mpz_frac_readonly.c000066400000000000000000000011511414523752600214350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "gmp.h" #include "fmpq.h" void fmpq_init_set_mpz_frac_readonly(fmpq_t z, const mpz_t num, const mpz_t den) { fmpz_init_set_readonly(fmpq_numref(z), num); fmpz_init_set_readonly(fmpq_denref(z), den); } flint2-2.8.4/fmpq/init_set_readonly.c000066400000000000000000000011051414523752600175530ustar00rootroot00000000000000/* 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 2.1 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)); } flint2-2.8.4/fmpq/inlines.c000066400000000000000000000017571414523752600155160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPQ_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #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); } flint2-2.8.4/fmpq/inv.c000066400000000000000000000013331414523752600146370ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fmpq/is_canonical.c000066400000000000000000000015131414523752600164650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/fmpq/mat22.c000066400000000000000000000103471414523752600147750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.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); M->det *= N->det; fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); } /* 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; } flint2-2.8.4/fmpq/mod_fmpz.c000066400000000000000000000014711414523752600156610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq/mpq_clear_readonly.c000066400000000000000000000010331414523752600177000ustar00rootroot00000000000000/* 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 2.1 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)); } flint2-2.8.4/fmpq/mpq_init_set_readonly.c000066400000000000000000000011241414523752600204310ustar00rootroot00000000000000/* 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 2.1 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)); } flint2-2.8.4/fmpq/mul.c000066400000000000000000000046671414523752600146550ustar00rootroot00000000000000/* Copyright (C) 2011, 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" 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)); } flint2-2.8.4/fmpq/mul_2exp.c000066400000000000000000000017031414523752600155770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } } flint2-2.8.4/fmpq/mul_fmpz.c000066400000000000000000000011341414523752600156730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" 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); } flint2-2.8.4/fmpq/mul_si.c000066400000000000000000000034211414523752600153330ustar00rootroot00000000000000/* Copyright (C) 2020 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 2.1 of the License, or (at your option) any later version. See . */ #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_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); } flint2-2.8.4/fmpq/mul_small.c000066400000000000000000000034601414523752600160330ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.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); } flint2-2.8.4/fmpq/mul_ui.c000066400000000000000000000027431414523752600153430ustar00rootroot00000000000000/* Copyright (C) 2020 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 2.1 of the License, or (at your option) any later version. See . */ #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_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); } flint2-2.8.4/fmpq/next_calkin_wilf.c000066400000000000000000000023641414523752600173700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/fmpq/next_minimal.c000066400000000000000000000035111414523752600165270ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpq/next_signed_calkin_wilf.c000066400000000000000000000015711414523752600207200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/fmpq/next_signed_minimal.c000066400000000000000000000015511414523752600200620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/fmpq/pow_fmpz.c000066400000000000000000000021701414523752600157040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } } flint2-2.8.4/fmpq/pow_si.c000066400000000000000000000026411414523752600153460ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (fmpq_pow_si). Division by zero.\n"); flint_abort(); } _fmpq_pow_si(fmpq_numref(rop), fmpq_denref(rop), fmpq_numref(op), fmpq_denref(op), e); } flint2-2.8.4/fmpq/profile/000077500000000000000000000000001414523752600153375ustar00rootroot00000000000000flint2-2.8.4/fmpq/profile/p-get_cfrac.c000066400000000000000000000062571414523752600176670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); /* too slow 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); */ _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; } flint2-2.8.4/fmpq/profile/p-reconstruct_fmpz_2.c000066400000000000000000000117541414523752600216000ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq/randbits.c000066400000000000000000000014331414523752600156520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq/randtest.c000066400000000000000000000031521414523752600156700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpq_randtest_not_zero). bits == 0.\n"); flint_abort(); } do { fmpq_randtest(f, state, bits); } while (fmpq_is_zero(f)); } flint2-2.8.4/fmpq/reconstruct_fmpz.c000066400000000000000000000016431414523752600174560ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpq/reconstruct_fmpz_2.c000066400000000000000000000620451414523752600177020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "mpn_extras.h" #define FMPQ_RECONSTRUCT_ARRAY_LIMIT 12 #define FMPQ_RECONSTRUCT_HGCD_CUTOFF 500 /* 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); count_leading_zeros(n_lzcnt, 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; } count_leading_zeros(a_lzcnt, 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) ? mpn_mul(R, Q, Qlen, m11, m_len) : 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); count_leading_zeros(n_lzcnt, 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); count_leading_zeros(a_lzcnt, 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_MPZ_PTR_SWAP(a, s); FLINT_MPZ_PTR_SWAP(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); } flint2-2.8.4/fmpq/reconstruct_fmpz_2_naive.c000066400000000000000000000030521414523752600210550ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq/set_cfrac.c000066400000000000000000000022501414523752600157730ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/fmpq/set_fmpz_frac.c000066400000000000000000000026071414523752600166720ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/fmpq/set_si.c000066400000000000000000000017061414523752600153350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq/set_str.c000066400000000000000000000012101414523752600155200ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq/set_ui.c000066400000000000000000000014771414523752600153440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq/simplest_between.c000066400000000000000000000062501414523752600174170ustar00rootroot00000000000000/* 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 2.1 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)); } } flint2-2.8.4/fmpq/sub.c000066400000000000000000000054461414523752600146450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/fmpq/sub_fmpz.c000066400000000000000000000024301414523752600156670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" 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); } flint2-2.8.4/fmpq/sub_si.c000066400000000000000000000025301414523752600153270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" 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); } flint2-2.8.4/fmpq/sub_ui.c000066400000000000000000000024121414523752600153300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" 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); } flint2-2.8.4/fmpq/submul.c000066400000000000000000000017121414523752600153530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/fmpq/test/000077500000000000000000000000001414523752600146565ustar00rootroot00000000000000flint2-2.8.4/fmpq/test/t-abs.c000066400000000000000000000036231414523752600160340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpq.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("abs...."); fflush(stdout); 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); fmpq_abs(b, a); mpq_abs(c, c); fmpq_get_mpq(d, b); result = (mpq_cmp(c, d) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Qd, d = %Qd\n", c, d); abort(); } fmpq_clear(a); fmpq_clear(b); mpq_clear(c); mpq_clear(d); } /* Check aliasing */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpq_t a; mpq_t c, d; fmpq_init(a); mpq_init(c); mpq_init(d); fmpq_randtest(a, state, 200); fmpq_get_mpq(c, a); fmpq_abs(a, a); mpq_abs(c, c); fmpq_get_mpq(d, a); result = (mpq_cmp(c, d) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Qd, d = %Qd\n", c, d); abort(); } fmpq_clear(a); mpq_clear(c); mpq_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-add.c000066400000000000000000000072141414523752600160170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); /* 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_add(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); abort(); } mpq_add(X, Y, Z); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { 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 = "); fmpq_print(z); flint_printf("\n"); 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_add(x, x, y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); abort(); } mpq_add(X, X, Y); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_add(x,x,y) != mpq_add(X,X,Y)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); 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_add(x, y, x); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); abort(); } mpq_add(X, Y, X); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_add(x,y,x) != mpq_add(X,Y,X)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-add_fmpz.c000066400000000000000000000057201414523752600170530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("add_fmpz...."); fflush(stdout); /* 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_add_fmpz(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); abort(); } fmpq_add(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"); 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_add_fmpz(x, x, y); fmpq_add(X, X, Y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); 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"); abort(); } fmpq_clear(x); fmpz_clear(y); fmpz_clear(one); fmpq_clear(X); fmpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-add_si.c000066400000000000000000000053301414523752600165070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("add_si...."); fflush(stdout); /* 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_add_si(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); abort(); } fmpq_add(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"); 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_add_si(x, x, y); fmpq_add(X, X, Y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); 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"); abort(); } fmpq_clear(x); fmpq_clear(X); fmpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-add_ui.c000066400000000000000000000053361414523752600165170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("add_ui...."); fflush(stdout); /* 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_add_ui(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); abort(); } fmpq_add(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"); 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_add_ui(x, x, y); fmpq_add(X, X, Y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); 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"); abort(); } fmpq_clear(x); fmpq_clear(X); fmpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-addmul.c000066400000000000000000000075021414523752600165350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.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); } int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("addmul...."); fflush(stdout); /* 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_addmul(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); abort(); } mpq_addmul(X, Y, Z); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_addmul(x,y,z) != mpq_addmul(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"); 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_addmul(x, x, y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); abort(); } mpq_addmul(X, X, Y); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_addmul(x,x,y) != mpq_addmul(X,X,Y)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); 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_addmul(x, y, x); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); abort(); } mpq_addmul(X, Y, X); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_addmul(x,y,x) != mpq_addmul(X,Y,X)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-canonicalise.c000066400000000000000000000044411414523752600177160ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("canonicalise...."); fflush(stdout); 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_clear(mult); fmpq_clear(x); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-cfrac_bound.c000066400000000000000000000031051414523752600175270ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("cfrac_bound...."); fflush(stdout); for (i = 0; i < 10000; 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); abort(); } _fmpz_vec_clear(c, bound + 10); fmpq_clear(x); fmpq_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-cmp.c000066400000000000000000000030521414523752600160420ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("cmp...."); fflush(stdout); for (i = 0; i < 10000; i++) { fmpq_t x, y; mpq_t X, Y; int c1, c2; 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); c1 = fmpq_cmp(x, y); c2 = mpq_cmp(X, Y); if (c1 < 0) c1 = -1; if (c1 > 0) c1 = 1; if (c2 < 0) c2 = -1; if (c2 > 0) c2 = 1; if (c1 != c2) { flint_printf("FAIL\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\ncmp(x,y) = %d, cmp(X,Y) = %d\n", c1, c2); abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-cmp_fmpz.c000066400000000000000000000031251414523752600170770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("cmp_fmpz...."); fflush(stdout); for (i = 0; i < 10000; i++) { fmpq_t x, y; mpq_t X, Y; int c1, c2; fmpq_init(x); fmpq_init(y); mpq_init(X); mpq_init(Y); fmpq_randtest(x, state, 200); fmpq_randtest(y, state, 200); fmpz_one(fmpq_denref(y)); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); c1 = fmpq_cmp_fmpz(x, fmpq_numref(y)); c2 = mpq_cmp(X, Y); if (c1 < 0) c1 = -1; if (c1 > 0) c1 = 1; if (c2 < 0) c2 = -1; if (c2 > 0) c2 = 1; if (c1 != c2) { flint_printf("FAIL\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\ncmp(x,y) = %d, cmp(X,Y) = %d\n", c1, c2); abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-cmp_si.c000066400000000000000000000030271414523752600165370ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson Copyright (C) 2016, 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("cmp_si...."); fflush(stdout); for (i = 0; i < 10000; i++) { fmpq_t x; slong y; mpq_t X, Y; int c1, c2; fmpq_init(x); mpq_init(X); mpq_init(Y); fmpq_randtest(x, state, 200); y = z_randtest(state); fmpq_get_mpq(X, x); flint_mpq_set_si(Y, y, 1); c1 = fmpq_cmp_si(x, y); c2 = mpq_cmp(X, Y); if (c1 < 0) c1 = -1; if (c1 > 0) c1 = 1; if (c2 < 0) c2 = -1; if (c2 > 0) c2 = 1; if (c1 != c2) { flint_printf("FAIL\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = %wd", y); flint_printf("\ncmp(x,y) = %d, cmp(X,Y) = %d\n", c1, c2); abort(); } fmpq_clear(x); mpq_clear(X); mpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-cmp_ui.c000066400000000000000000000027701414523752600165450ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("cmp_ui...."); fflush(stdout); for (i = 0; i < 10000; i++) { fmpq_t x; ulong y; mpq_t X, Y; int c1, c2; fmpq_init(x); mpq_init(X); mpq_init(Y); fmpq_randtest(x, state, 200); y = n_randtest(state); fmpq_get_mpq(X, x); flint_mpq_set_ui(Y, y, 1); c1 = fmpq_cmp_ui(x, y); c2 = mpq_cmp(X, Y); if (c1 < 0) c1 = -1; if (c1 > 0) c1 = 1; if (c2 < 0) c2 = -1; if (c2 > 0) c2 = 1; if (c1 != c2) { flint_printf("FAIL\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = %wu", y); flint_printf("\ncmp(x,y) = %d, cmp(X,Y) = %d\n", c1, c2); abort(); } fmpq_clear(x); mpq_clear(X); mpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-dedekind_sum.c000066400000000000000000000176741414523752600177350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "ulong_extras.h" #include "math.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} }; int main(void) { fmpz_t hh, kk; fmpq_t s1, s2; slong i, h, k; FLINT_TEST_INIT(state); flint_printf("dedekind_sum...."); fflush(stdout); fmpz_init(hh); fmpz_init(kk); fmpq_init(s1); fmpq_init(s2); for (k = -200; k < 200; k++) { for (h = -200; h < 200; 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"); 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"); 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"); 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); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-div.c000066400000000000000000000102111414523752600160400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("div...."); fflush(stdout); /* 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); 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_div(x, y, z); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fmpq_print(x); flint_printf("\n"); fmpq_print(y); flint_printf("\n"); fmpq_print(z); flint_printf("\n"); abort(); } mpq_div(X, Y, Z); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_div(x,y,z) != mpq_div(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"); 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); do { fmpq_randtest(y, state, 200); } while (fmpq_is_zero(y)); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); fmpq_div(x, x, y); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fmpq_print(x); flint_printf("\n"); fmpq_print(y); flint_printf("\n"); abort(); } mpq_div(X, X, Y); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_div(x,x,y) != mpq_div(X,X,Y)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); 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); do { fmpq_randtest(x, state, 200); } while (fmpq_is_zero(x)); fmpq_randtest(y, state, 200); fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); fmpq_div(x, y, x); if (!fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); fmpq_print(x); flint_printf("\n"); fmpq_print(y); flint_printf("\n"); abort(); } mpq_div(X, Y, X); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_div(x,y,x) != mpq_div(X,Y,X)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-div_2exp.c000066400000000000000000000066211414523752600170100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("div_2exp...."); fflush(stdout); /* 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_div_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); abort(); } fmpq_get_mpq(X, x); fmpq_get_mpq(Y, y); mpq_div_2exp(X, Y, c); fmpq_get_mpq(Y, x); if (!mpq_equal(X, Y)) { flint_printf("FAIL: fmpq_div_2exp(x,y,c) != mpq_div_2exp(X,Y,c)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\n"); 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_div_2exp(x, y, c); fmpq_div_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); abort(); } if (!fmpq_equal(x, y)) { flint_printf("FAIL: fmpq_div_2exp(x,y,c) != fmpq_div_2exp(y,y,c)\n"); flint_printf("x = "); fmpq_print(x); flint_printf("\ny = "); fmpq_print(y); flint_printf("\nc = %wu\n", c); abort(); } fmpq_clear(x); fmpq_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-div_fmpz.c000066400000000000000000000045111414523752600171020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_fmpz...."); fflush(stdout); /* 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"); 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"); abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq/test/t-farey_neighbors.c000066400000000000000000000044631414523752600204400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq.h" int main(void) { slong i, q, steps; FLINT_TEST_INIT(state); flint_printf("farey_neighbors...."); fflush(stdout); /* 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); 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); 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); flint_abort(); } fmpz_clear(Q); fmpq_clear(s); fmpq_clear(t); fmpq_clear(cur); fmpq_clear(left); fmpq_clear(right); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-gcd_cofactors.c000066400000000000000000000045371414523752600200740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("gcd_cofactors...."); fflush(stdout); 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-get_cfrac.c000066400000000000000000000047721414523752600172120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("get_cfrac...."); fflush(stdout); 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"); 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); 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"); flint_abort(); } _fmpz_vec_clear(c1, bound); _fmpz_vec_clear(c2, bound); fmpq_clear(x); fmpq_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-get_d.c000066400000000000000000000033651414523752600163540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq.h" int main(void) { const flint_bitcnt_t bound = 1000; slong i; FLINT_TEST_INIT(state); flint_printf("get_d...."); fflush(stdout); 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); flint_abort(); } } fmpq_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-get_mpfr.c000066400000000000000000000037531414523752600170760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("get_mpfr...."); fflush(stdout); 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"); abort(); } fmpq_clear(x); mpq_clear(y); mpfr_clear(f1); mpfr_clear(f2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-get_set_str.c000066400000000000000000000044201414523752600176050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.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"); flint_abort(); } fmpq_clear(r); } int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("get_str...."); fflush(stdout); check_invalid("x5/3", 6); check_invalid("5x/3", 6); check_invalid("5/x3", 6); check_invalid("5/3x", 6); for (i = 0; i < 100000; 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); 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); abort(); } flint_free(str1); flint_free(str2); fmpq_clear(a); fmpq_clear(a2); mpq_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-harmonic_ui.c000066400000000000000000000064401414523752600175640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "ulong_extras.h" void numerical_test(fmpq_t res, slong n, double ans) { const double tol = 1e-13; double err; mpq_t tmp; mpq_init(tmp); fmpq_harmonic_ui(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); 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) { mpq_set_ui(res, 0, UWORD(1)); for (k = a; k <= b; k++) { 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); } int main(void) { ulong i; mpq_t x, y; fmpq_t t; FLINT_TEST_INIT(state); flint_printf("harmonic_ui...."); fflush(stdout); fmpq_init(t); mpq_init(x); mpq_init(y); for (i = 0; i < 1000; i++) { mpq_harmonic_balanced(x, 1, i); fmpq_harmonic_ui(t, i); fmpq_get_mpq(y, t); if (!mpq_equal(x, y)) { flint_printf("FAIL: %wd\n", i); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-height.c000066400000000000000000000023221414523752600165320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("height...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-init_set_readonly.c000066400000000000000000000044331414523752600210020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "long_extras.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init_set_readonly...."); fflush(stdout); /* 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, FLINT_BITS - 2); 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 < 100000; i++) { fmpq_t f; mpq_t z; fmpq_init(f); fmpq_randtest(f, state, FLINT_BITS - 2); 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 < 100000; 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-inv.c000066400000000000000000000057321414523752600160660ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("inv...."); fflush(stdout); /* 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"); abort(); } if (!fmpq_is_canonical(y) || !fmpq_is_canonical(x)) { flint_printf("FAIL: result not canonical!\n"); 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"); 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"); 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"); abort(); } fmpq_clear(x); mpq_clear(X); mpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-mpq_init_set_readonly.c000066400000000000000000000040261414523752600216550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "long_extras.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("mpq_init_set_readonly...."); fflush(stdout); /* 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, FLINT_BITS - 2); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-mul.c000066400000000000000000000072141414523752600160640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-mul_2exp.c000066400000000000000000000066211414523752600170230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("mul_2exp...."); fflush(stdout); /* 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); 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"); 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); 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); abort(); } fmpq_clear(x); fmpq_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-mul_fmpz.c000066400000000000000000000044011414523752600171130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_fmpz...."); fflush(stdout); /* 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"); 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"); abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq/test/t-mul_si.c000066400000000000000000000053311414523752600165550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("mul_si...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } fmpq_clear(x); fmpq_clear(X); fmpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-mul_ui.c000066400000000000000000000053301414523752600165560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("mul_ui...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } fmpq_clear(x); fmpq_clear(X); fmpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-next_calkin_wilf.c000066400000000000000000000050311414523752600206020ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { slong i; fmpq_t r, ans; FLINT_TEST_INIT(state); flint_printf("next_calkin_wilf...."); fflush(stdout); fmpq_init(r); fmpq_init(ans); fmpq_set_si(r, 0, 1); fmpq_set_si(ans, 191, 1287); for (i = 0; i < 1000000; 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"); abort(); } fmpq_set_si(r, 0, 1); fmpq_set_si(ans, -191, 1096); for (i = 0; i < 1000000; 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"); abort(); } fmpz_set_str(fmpq_numref(r), "18446744073709551615", 10); fmpz_set_str(fmpq_denref(r), "18446744073709551616", 10); fmpz_set_str(fmpq_numref(ans), "18538977794078099355206", 10); fmpz_set_str(fmpq_denref(ans), "22062305912156623710275", 10); for (i = 0; i < 1000000; 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"); abort(); } fmpz_set_str(fmpq_numref(r), "18446744073709551615", 10); fmpz_set_str(fmpq_denref(r), "18446744073709551616", 10); fmpz_set_str(fmpq_numref(ans), "15015649675999575000951", 10); fmpz_set_str(fmpq_denref(ans), "18538977794078099356211", 10); for (i = 0; i < 1000000; 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"); abort(); } fmpq_clear(r); fmpq_clear(ans); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-next_minimal.c000066400000000000000000000047341414523752600177570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { slong i; fmpq_t r, ans; FLINT_TEST_INIT(state); flint_printf("next_minimal...."); fflush(stdout); fmpq_init(r); fmpq_init(ans); fmpq_set_si(r, 0, 1); fmpq_set_si(ans, 289, 1283); for (i = 0; i < 1000000; 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"); abort(); } fmpq_set_si(r, 0, 1); fmpq_set_si(ans, -471, 907); for (i = 0; i < 1000000; 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"); abort(); } fmpz_set_str(fmpq_numref(r), "36893488147419102231", 10); fmpz_set_str(fmpq_denref(r), "36893488147419103232", 10); fmpz_set_str(fmpq_numref(ans), "830822", 10); fmpz_set_str(fmpq_denref(ans), "36893488147419103233", 10); for (i = 0; i < 1000000; 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"); abort(); } fmpz_set_str(fmpq_numref(r), "36893488147419102231", 10); fmpz_set_str(fmpq_denref(r), "36893488147419103232", 10); fmpz_set_str(fmpq_numref(ans), "414994", 10); fmpz_set_str(fmpq_denref(ans), "36893488147419103233", 10); for (i = 0; i < 1000000; 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"); abort(); } fmpq_clear(r); fmpq_clear(ans); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-one.c000066400000000000000000000036571414523752600160570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("one...."); fflush(stdout); /* 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"); 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"); abort(); } fmpq_clear(x); fmpq_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq/test/t-pow_si.c000066400000000000000000000050231414523752600165630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "long_extras.h" #include "ulong_extras.h" #include "fmpq.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow_si...."); fflush(stdout); /* 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); 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); abort(); } fmpq_clear(a); fmpq_clear(b); fmpq_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-randtest.c000066400000000000000000000023061414523752600171100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("randtest...."); fflush(stdout); 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"); abort(); } fmpq_clear(x); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-reconstruct_fmpz.c000066400000000000000000000040431414523752600206730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("reconstruct_fmpz...."); fflush(stdout); 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"); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(mod); fmpz_clear(res); mpz_clear(tmp); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-reconstruct_fmpz_2.c000066400000000000000000000121341414523752600211140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("reconstruct_fmpz_2...."); fflush(stdout); /* 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); } fmpz_mul(mod, N, D); fmpz_mul_ui(mod, mod, 2); 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_printf("FAIL: reconstruction failed\n"); flint_printf("success = %d\n", success); flint_printf("x = "); fmpq_print(x); flint_printf("\n"); flint_printf("N = "); fmpz_print(N); flint_printf("\n"); flint_printf("D = "); fmpz_print(D); flint_printf("\n"); flint_printf("mod = "); fmpz_print(mod); flint_printf("\n"); flint_printf("res = "); fmpz_print(res); flint_printf("\n"); flint_printf("y = "); fmpq_print(y); flint_printf("\n"); flint_abort(); } 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_printf("FAIL:\n"); flint_printf("check match with naive: i = %wd\n", i); flint_abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(mod); fmpz_clear(res); fmpz_clear(N); fmpz_clear(D); fmpz_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-set_cfrac.c000066400000000000000000000030461414523752600172170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("set_cfrac...."); fflush(stdout); 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"); abort(); } _fmpz_vec_clear(c, bound); fmpq_clear(x); fmpq_clear(y); fmpq_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-set_fmpz_frac.c000066400000000000000000000031661414523752600201130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("set_fmpz_frac...."); fflush(stdout); 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"); abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(p); fmpz_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-set_si.c000066400000000000000000000031721414523752600165540ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("set_si...."); fflush(stdout); 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"); abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(p); fmpz_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-set_ui.c000066400000000000000000000032241414523752600165540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("set_ui...."); fflush(stdout); 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"); abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(p); fmpz_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-simplest_between.c000066400000000000000000000075501414523752600206430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq.h" #include "fmpz_poly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("simplest_between...."); fflush(stdout); 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); 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); 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); 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); flint_abort(); } } else { printf("FAIL\n"); flint_printf("Check return has positive denominator, i = %wd\n", i); 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); 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); flint_abort(); } fmpq_clear(m2); fmpq_clear(m1); fmpq_clear(m); fmpq_clear(l); fmpq_clear(r); fmpq_clear(l1); fmpq_clear(r1); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-sub.c000066400000000000000000000072141414523752600160600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-sub_fmpz.c000066400000000000000000000057201414523752600171140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("sub_fmpz...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } fmpq_clear(x); fmpz_clear(y); fmpz_clear(one); fmpq_clear(X); fmpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-sub_si.c000066400000000000000000000053301414523752600165500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("sub_si...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } fmpq_clear(x); fmpq_clear(X); fmpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-sub_ui.c000066400000000000000000000053371414523752600165610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("sub_ui...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } fmpq_clear(x); fmpq_clear(X); fmpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq/test/t-submul.c000066400000000000000000000075021414523752600165760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.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); } int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("submul...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); abort(); } fmpq_clear(x); fmpq_clear(y); mpq_clear(X); mpq_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat.h000066400000000000000000000247571414523752600147300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define FMPQ_MAT_INLINE static __inline__ #endif #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_poly.h" #include "fmpq.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]; 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; } FLINT_DLL void fmpq_mat_init(fmpq_mat_t mat, slong rows, slong cols); FLINT_DLL void fmpq_mat_init_set(fmpq_mat_t mat1, const fmpq_mat_t mat2); FLINT_DLL void fmpq_mat_clear(fmpq_mat_t mat); FLINT_DLL void fmpq_mat_swap(fmpq_mat_t mat1, fmpq_mat_t mat2); FMPQ_MAT_INLINE 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)); } /* Windows and concatenation */ FLINT_DLL void fmpq_mat_window_init(fmpq_mat_t window, const fmpq_mat_t mat, slong r1, slong c1, slong r2, slong c2); FLINT_DLL void fmpq_mat_window_clear(fmpq_mat_t window); FLINT_DLL void fmpq_mat_concat_horizontal(fmpq_mat_t res, const fmpq_mat_t mat1, const fmpq_mat_t mat2); FLINT_DLL void fmpq_mat_concat_vertical(fmpq_mat_t res, const fmpq_mat_t mat1, const fmpq_mat_t mat2); /* Input and output */ FLINT_DLL void fmpq_mat_print(const fmpq_mat_t mat); /* Random matrix generation **************************************************/ FLINT_DLL void fmpq_mat_randbits(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void fmpq_mat_randtest(fmpq_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); /* Special matrices **********************************************************/ FLINT_DLL void fmpq_mat_hilbert_matrix(fmpq_mat_t mat); /* Basic assignment **********************************************************/ FLINT_DLL void fmpq_mat_set(fmpq_mat_t dest, const fmpq_mat_t src); FLINT_DLL void fmpq_mat_zero(fmpq_mat_t mat); FLINT_DLL void fmpq_mat_one(fmpq_mat_t mat); FLINT_DLL void fmpq_mat_transpose(fmpq_mat_t rop, const fmpq_mat_t op); /* Addition, scalar multiplication ******************************************/ FLINT_DLL void fmpq_mat_add(fmpq_mat_t mat, const fmpq_mat_t mat1, const fmpq_mat_t mat2); FLINT_DLL void fmpq_mat_sub(fmpq_mat_t mat, const fmpq_mat_t mat1, const fmpq_mat_t mat2); FLINT_DLL void fmpq_mat_neg(fmpq_mat_t rop, const fmpq_mat_t op); FLINT_DLL void fmpq_mat_scalar_mul_fmpq(fmpq_mat_t rop, const fmpq_mat_t op, const fmpq_t x); FLINT_DLL void fmpq_mat_scalar_mul_fmpz(fmpq_mat_t rop, const fmpq_mat_t op, const fmpz_t x); FLINT_DLL void fmpq_mat_scalar_div_fmpz(fmpq_mat_t rop, const fmpq_mat_t op, const fmpz_t x); /* Basic comparison and properties *******************************************/ FLINT_DLL int fmpq_mat_equal(const fmpq_mat_t mat1, const fmpq_mat_t mat2); FLINT_DLL int fmpq_mat_is_integral(const fmpq_mat_t mat); FLINT_DLL int fmpq_mat_is_zero(const fmpq_mat_t mat); FLINT_DLL 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 *************************************************/ FLINT_DLL int fmpq_mat_get_fmpz_mat(fmpz_mat_t dest, const fmpq_mat_t mat); FLINT_DLL void fmpq_mat_get_fmpz_mat_entrywise(fmpz_mat_t num, fmpz_mat_t den, const fmpq_mat_t mat); FLINT_DLL void fmpq_mat_get_fmpz_mat_matwise(fmpz_mat_t num, fmpz_t den, const fmpq_mat_t mat); FLINT_DLL void fmpq_mat_get_fmpz_mat_rowwise(fmpz_mat_t num, fmpz * den, const fmpq_mat_t mat); FLINT_DLL void fmpq_mat_get_fmpz_mat_colwise(fmpz_mat_t num, fmpz * den, const fmpq_mat_t mat); FLINT_DLL 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); FLINT_DLL void fmpq_mat_get_fmpz_mat_mod_fmpz(fmpz_mat_t dest, const fmpq_mat_t mat, const fmpz_t mod); FLINT_DLL void fmpq_mat_set_fmpz_mat(fmpq_mat_t dest, const fmpz_mat_t src); FLINT_DLL void fmpq_mat_set_fmpz_mat_div_fmpz(fmpq_mat_t X, const fmpz_mat_t Xmod, const fmpz_t div); FLINT_DLL int fmpq_mat_set_fmpz_mat_mod_fmpz(fmpq_mat_t X, const fmpz_mat_t Xmod, const fmpz_t mod); /* Matrix multiplication *****************************************************/ FLINT_DLL void fmpq_mat_mul_direct(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B); FLINT_DLL void fmpq_mat_mul_cleared(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B); FLINT_DLL void fmpq_mat_mul(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B); FLINT_DLL void fmpq_mat_mul_fmpz_mat(fmpq_mat_t C, const fmpq_mat_t A, const fmpz_mat_t B); FLINT_DLL void fmpq_mat_mul_r_fmpz_mat(fmpq_mat_t C, const fmpz_mat_t A, const fmpq_mat_t B); /* Kronecker product *********************************************************/ FLINT_DLL void fmpq_mat_kronecker_product(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B); /* Permutations **************************************************************/ FMPQ_MAT_INLINE void fmpq_mat_swap_rows(fmpq_mat_t mat, slong * perm, slong r, slong s) { if (r != s && !fmpq_mat_is_empty(mat)) { fmpq * 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; } } FMPQ_MAT_INLINE 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); } FMPQ_MAT_INLINE void fmpq_mat_swap_cols(fmpq_mat_t mat, slong * perm, slong r, slong s) { if (r != s && !fmpq_mat_is_empty(mat)) { slong t; if (perm) { t = perm[s]; perm[s] = perm[r]; perm[r] = t; } for (t = 0; t < mat->r; t++) { fmpq_swap(fmpq_mat_entry(mat, t, r), fmpq_mat_entry(mat, t, s)); } } } FMPQ_MAT_INLINE void fmpq_mat_invert_cols(fmpq_mat_t mat, slong * perm) { if (!fmpq_mat_is_empty(mat)) { slong t; slong i; slong c = mat->c; slong k = mat->c/2; if (perm) { for (i =0; i < k; i++) { t = perm[i]; perm[i] = perm[c - i]; perm[c - i] = t; } } 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)); } } } } /* Trace *********************************************************************/ FLINT_DLL void fmpq_mat_trace(fmpq_t trace, const fmpq_mat_t mat); /* Determinant ***************************************************************/ FLINT_DLL void fmpq_mat_det(fmpq_t det, const fmpq_mat_t mat); /* Nonsingular solving *******************************************************/ FLINT_DLL int fmpq_mat_solve_fmpz_mat_fraction_free(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL int fmpq_mat_solve_fraction_free(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); FLINT_DLL int fmpq_mat_solve_fmpz_mat_dixon(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL int fmpq_mat_solve_dixon(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); FLINT_DLL int fmpq_mat_solve_fmpz_mat_multi_mod(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL int fmpq_mat_solve_multi_mod(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); FLINT_DLL int fmpq_mat_can_solve_fmpz_mat_multi_mod(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL int fmpq_mat_can_solve_multi_mod(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); FLINT_DLL int fmpq_mat_solve_fmpz_mat(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL int fmpq_mat_solve(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B); /* Inverse *******************************************************************/ FLINT_DLL int fmpq_mat_inv(fmpq_mat_t B, const fmpq_mat_t A); /* Echelon form **************************************************************/ FLINT_DLL int fmpq_mat_pivot(slong * perm, fmpq_mat_t mat, slong r, slong c); FLINT_DLL slong fmpq_mat_rref_classical(fmpq_mat_t B, const fmpq_mat_t A); FLINT_DLL slong fmpq_mat_rref_fraction_free(fmpq_mat_t B, const fmpq_mat_t A); FLINT_DLL slong fmpq_mat_rref(fmpq_mat_t B, const fmpq_mat_t A); /* Gram-Schmidt Orthogonalisation *******************************************/ FLINT_DLL void fmpq_mat_gso(fmpq_mat_t B, const fmpq_mat_t A); /* Characteristic polynomial *************************************************/ FLINT_DLL void fmpq_mat_similarity(fmpq_mat_t A, slong r, fmpq_t d); /* Characteristic polynomial *************************************************/ FLINT_DLL void _fmpq_mat_charpoly(fmpz * coeffs, fmpz_t den, const fmpq_mat_t mat); FLINT_DLL void fmpq_mat_charpoly(fmpq_poly_t pol, const fmpq_mat_t mat); /* Minimal polynomial ********************************************************/ FLINT_DLL slong _fmpq_mat_minpoly(fmpz * coeffs, fmpz_t den, const fmpq_mat_t mat); FLINT_DLL void fmpq_mat_minpoly(fmpq_poly_t pol, const fmpq_mat_t mat); #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpq_mat/000077500000000000000000000000001414523752600145405ustar00rootroot00000000000000flint2-2.8.4/fmpq_mat/add.c000066400000000000000000000013041414523752600154320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpq_mat/can_solve_multi_mod.c000066400000000000000000000164061414523752600207350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpq_mat_can_solve_fmpz_mat_multi_mod). Incompatible matrix dimensions.\n"); flint_abort(); } 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_printf("Exception (fmpq_mat_can_solve_multi_mod). Incompatible matrix dimensions.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpq_mat/charpoly.c000066400000000000000000000030131414523752600165220ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (fmpq_mat_charpoly). Non-square matrix.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_mat/clear.c000066400000000000000000000013031414523752600157670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/concat_horizontal.c000066400000000000000000000017131414523752600204260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } } } flint2-2.8.4/fmpq_mat/concat_vertical.c000066400000000000000000000017111414523752600200440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } } } flint2-2.8.4/fmpq_mat/det.c000066400000000000000000000026061414523752600154640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpq_mat/equal.c000066400000000000000000000014661414523752600160220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mat/get_fmpz_mat.c000066400000000000000000000014731414523752600173650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mat/get_fmpz_mat_colwise.c000066400000000000000000000027371414523752600211160ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/get_fmpz_mat_entrywise.c000066400000000000000000000014721414523752600214750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } } } flint2-2.8.4/fmpq_mat/get_fmpz_mat_matwise.c000066400000000000000000000026671414523752600211240ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/get_fmpz_mat_mod_fmpz.c000066400000000000000000000015321414523752600212540ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } } flint2-2.8.4/fmpq_mat/get_fmpz_mat_rowwise.c000066400000000000000000000044271414523752600211460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/gso.c000066400000000000000000000040241414523752600154740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpq_mat_gso). Incompatible dimensions.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_mat/hilbert_matrix.c000066400000000000000000000011421414523752600177170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/init.c000066400000000000000000000022451414523752600156520ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq_mat/init_set.c000066400000000000000000000011011414523752600165130ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpq_mat/inlines.c000066400000000000000000000010601414523752600163420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPQ_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "fmpq_mat.h" flint2-2.8.4/fmpq_mat/inv.c000066400000000000000000000044571414523752600155120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/fmpq_mat/is_integral.c000066400000000000000000000012501414523752600172020ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mat/is_one.c000066400000000000000000000014641414523752600161650ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq_mat/is_zero.c000066400000000000000000000012411414523752600163540ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mat/kronecker_product.c000066400000000000000000000017251414523752600204340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } } } } } flint2-2.8.4/fmpq_mat/minpoly.c000066400000000000000000000031041414523752600163710ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (fmpq_mat_minpoly). Non-square matrix.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_mat/mul.c000066400000000000000000000011051414523752600154760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mat/mul_cleared.c000066400000000000000000000025751414523752600171710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/mul_direct.c000066400000000000000000000022561414523752600170400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpq_mat_mul_direct). Aliasing not implemented.\n"); flint_abort(); } 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)); } } } } flint2-2.8.4/fmpq_mat/mul_fmpz_mat.c000066400000000000000000000022151414523752600173760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/mul_r_fmpz_mat.c000066400000000000000000000022171414523752600177210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/neg.c000066400000000000000000000012131414523752600154520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpq_mat/one.c000066400000000000000000000013001414523752600154570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpq_mat/pivot.c000066400000000000000000000017311414523752600160470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mat/print.c000066400000000000000000000015061414523752600160420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" 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"); } flint2-2.8.4/fmpq_mat/randbits.c000066400000000000000000000012041414523752600165070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/randtest.c000066400000000000000000000012041414523752600165250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/rref.c000066400000000000000000000011331414523752600156400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mat/rref_classical.c000066400000000000000000000034531414523752600176650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mat/rref_fraction_free.c000066400000000000000000000016331414523752600205330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mat/scalar_div_fmpz.c000066400000000000000000000013231414523752600200460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/scalar_mul_fmpq.c000066400000000000000000000013321414523752600200500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/scalar_mul_fmpz.c000066400000000000000000000013231414523752600200610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/set.c000066400000000000000000000011651414523752600155020ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpq_mat/set_fmpz_mat.c000066400000000000000000000013341414523752600173750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } } } flint2-2.8.4/fmpq_mat/set_fmpz_mat_div_fmpz.c000066400000000000000000000026521414523752600212770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } } } } flint2-2.8.4/fmpq_mat/set_fmpz_mat_mod_fmpz.c000066400000000000000000000027431414523752600212750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mat/similarity.c000066400000000000000000000020411414523752600170670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #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); } } flint2-2.8.4/fmpq_mat/solve.c000066400000000000000000000020341414523752600160330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mat/solve_dixon.c000066400000000000000000000125351414523752600172430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_mat_solve_fmpz_mat_dixon). Non-square system matrix.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpq_mat/solve_fraction_free.c000066400000000000000000000033471414523752600207310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mat/solve_multi_mod.c000066400000000000000000000117021414523752600201060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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, X->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; } 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_printf("Exception (fmpq_mat_solve_fmpz_mat_multi_mod). Non-square system matrix.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpq_mat/sub.c000066400000000000000000000013041414523752600154730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpq_mat/swap.c000066400000000000000000000011661414523752600156620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mat.h" void fmpq_mat_swap(fmpq_mat_t mat1, fmpq_mat_t mat2) { if (mat1 != mat2) { fmpq_mat_struct tmp; tmp = *mat1; *mat1 = *mat2; *mat2 = tmp; } } flint2-2.8.4/fmpq_mat/test/000077500000000000000000000000001414523752600155175ustar00rootroot00000000000000flint2-2.8.4/fmpq_mat/test/t-add.c000066400000000000000000000071171414523752600166620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq_mat/test/t-can_solve_multi_mod.c000066400000000000000000000076601414523752600221570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("can_solve_multi_mod...."); fflush(stdout); /* 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_init(A, n, k); 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); 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_init(A, n, k); 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); abort(); } fmpz_clear(den); fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpq_mat_clear(AX); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-charpoly.c000066400000000000000000000037341414523752600177540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq_poly.h" #include "fmpq_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep; FLINT_TEST_INIT(state); flint_printf("charpoly...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-concat_horizontal.c000066400000000000000000000034651414523752600216540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_vec.h" #include "fmpq_mat.h" #include "ulong_extras.h" int main(void) { fmpq_mat_t A, B, C; fmpq_mat_t window1, window2; slong i; FLINT_TEST_INIT(state); flint_printf("concat_horizontal...."); fflush(stdout); 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"); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_window_clear(window1); fmpq_mat_window_clear(window2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-concat_vertical.c000066400000000000000000000034521414523752600212700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, B, C; fmpz_mat_t window1, window2; slong i; FLINT_TEST_INIT(state); flint_printf("concat_vertical...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_window_clear(window1); fmpz_mat_window_clear(window2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-det.c000066400000000000000000000037511414523752600167060ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("det...."); fflush(stdout); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-gso.c000066400000000000000000000042241414523752600167160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" #include "fmpq_vec.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gso...."); fflush(stdout); 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); 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); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_clear(dot); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq_mat/test/t-init_clear.c000066400000000000000000000021541414523752600202370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-inv.c000066400000000000000000000077471414523752600167370ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("inv...."); fflush(stdout); 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); 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); 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); abort(); } fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); } fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-invert_rows_cols.c000066400000000000000000000033141414523752600215260ustar00rootroot00000000000000/* Copyright (C) 2019 Tommy Hofmann Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" #include "ulong_extras.h" int main(void) { slong n, rep; FLINT_TEST_INIT(state); flint_printf("invert_rows/cols...."); fflush(stdout); /* 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); abort(); } } } fmpq_mat_clear(A); fmpq_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-is_integral.c000066400000000000000000000030171414523752600204250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_integral...."); fflush(stdout); 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"); 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"); abort(); } } fmpq_mat_clear(A); fmpz_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-is_one.c000066400000000000000000000024231414523752600174010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_one...."); fflush(stdout); 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"); abort(); } if (rows && cols) { fmpq_mat_randbits(A, state, 100); if (fmpq_mat_is_one(A)) { flint_printf("FAIL!\n"); abort(); } } fmpq_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-kronecker_product.c000066400000000000000000000045051414523752600216530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int r, result; fmpq_mat_t A, B, C; fmpq_mat_t window1, window2; slong m, n, k, l, i, j; slong bits; FLINT_TEST_INIT(state); flint_printf("kronecker_product...."); fflush(stdout); 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); abort(); } fmpq_mat_window_clear(window1); fmpq_mat_window_clear(window2); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq_mat/test/t-minpoly.c000066400000000000000000000067061414523752600176240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq_poly.h" #include "fmpq_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep, i, j; FLINT_TEST_INIT(state); flint_printf("minpoly...."); fflush(stdout); 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"); 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"); abort(); } fmpq_clear(d); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_poly_clear(f); fmpq_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-mul.c000066400000000000000000000050601414523752600167220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); 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); 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"); flint_abort(); } fmpq_mat_window_clear(A_window); fmpq_mat_clear(A); fmpq_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq_mat/test/t-neg.c000066400000000000000000000042261414523752600167010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg...."); fflush(stdout); /* 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); 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); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq_mat/test/t-one.c000066400000000000000000000033131414523752600167050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("one...."); fflush(stdout); /* 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); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(I); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq_mat/test/t-rref.c000066400000000000000000000051671414523752600170730ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("rref...."); fflush(stdout); 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); 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"); 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); abort(); } fmpz_mat_clear(M); fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); } fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-scalar_div_fmpz.c000066400000000000000000000052611414523752600212730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_div_fmpz...."); fflush(stdout); /* 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); 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); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(D); fmpz_clear(x); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq_mat/test/t-scalar_mul_fmpq.c000066400000000000000000000052611414523752600212750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpq...."); fflush(stdout); /* 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); 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); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(D); fmpq_clear(x); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq_mat/test/t-scalar_mul_fmpz.c000066400000000000000000000052371414523752600213110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpz...."); fflush(stdout); /* 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); 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); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(D); fmpz_clear(x); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq_mat/test/t-solve.c000066400000000000000000000071221414523752600172560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("solve...."); fflush(stdout); /* 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); 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"); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpz_mat_clear(M); fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-solve_dixon.c000066400000000000000000000062461414523752600204650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("solve_dixon...."); fflush(stdout); /* 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); 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"); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpz_mat_clear(M); fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-solve_fmpz_mat.c000066400000000000000000000060121414523752600211500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("solve_fmpz_mat...."); fflush(stdout); 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); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpq_mat_clear(X); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-solve_fmpz_mat_dixon.c000066400000000000000000000060341414523752600223550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("solve_fmpz_mat_dixon...."); fflush(stdout); 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); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpq_mat_clear(X); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-solve_fmpz_mat_fraction_free.c000066400000000000000000000060641414523752600240450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("solve_fmpz_mat_fraction_free...."); fflush(stdout); 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); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpq_mat_clear(X); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-solve_fmpz_mat_multi_mod.c000066400000000000000000000060501414523752600232230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("solve_fmpz_mat_multi_mod...."); fflush(stdout); 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); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpq_mat_clear(X); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-solve_fraction_free.c000066400000000000000000000062341414523752600221470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("solve_fraction_free...."); fflush(stdout); 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); 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"); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpz_mat_clear(M); fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-solve_multi_mod.c000066400000000000000000000062621414523752600213330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("solve_multi_mod...."); fflush(stdout); /* 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); 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"); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(X); fmpz_mat_clear(M); fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-sub.c000066400000000000000000000071571414523752600167270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(C); fmpq_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq_mat/test/t-trace.c000066400000000000000000000040251414523752600172230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("trace...."); fflush(stdout); /* 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"); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); fmpq_mat_clear(AB); fmpq_mat_clear(BA); fmpq_clear(trab); fmpq_clear(trba); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/test/t-transpose.c000066400000000000000000000045221414523752600201450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("transpose...."); fflush(stdout); /* 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); 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); abort(); } fmpq_mat_clear(A); fmpq_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq_mat/test/t-window_init_clear.c000066400000000000000000000031301414523752600216210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("window_init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mat/trace.c000066400000000000000000000013151414523752600160020ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } } flint2-2.8.4/fmpq_mat/transpose.c000066400000000000000000000016141414523752600167240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } } flint2-2.8.4/fmpq_mat/window_clear.c000066400000000000000000000010041414523752600173540ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpq_mat/window_init.c000066400000000000000000000017231414523752600172410ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq_mat/zero.c000066400000000000000000000011101414523752600156540ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpq_matxx.h000066400000000000000000000407011414523752600152730ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPQ_MATXX_H #define FMPQ_MATXX_H FMPQ_MATXX_H #include "fmpq_mat.h" #include "fmpqxx.h" #include "fmpz_matxx.h" #include "fmpz_vecxx.h" #include "flintxx/ltuple.h" #include "flintxx/matrix.h" // TODO wrap entry_num, entry_den? // TODO numden_rowwise_2 // TODO rref members namespace flint { FLINT_DEFINE_BINOP(hilbert_matrix) FLINT_DEFINE_BINOP(mul_direct) FLINT_DEFINE_BINOP(mul_cleared) FLINT_DEFINE_BINOP(solve_fraction_free) FLINT_DEFINE_UNOP(numden_colwise) FLINT_DEFINE_UNOP(numden_entrywise) FLINT_DEFINE_UNOP(numden_matwise) FLINT_DEFINE_UNOP(numden_rowwise) FLINT_DEFINE_UNOP(num_rowwise) FLINT_DEFINE_UNOP(num_colwise) FLINT_DEFINE_UNOP(rref_classical) FLINT_DEFINE_UNOP(rref_fraction_free) namespace detail { template struct fmpq_matxx_traits : matrices::generic_traits { }; typedef make_ltuple::type>::type fmpq_matxx_numden_entrywise_rt; typedef make_ltuple::type>::type fmpq_matxx_numden_matwise_rt; typedef make_ltuple::type>::type fmpq_matxx_numden_rowwise_rt; typedef fmpq_matxx_numden_rowwise_rt fmpq_matxx_numden_colwise_rt; } // detail template class fmpq_matxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef detail::fmpq_matxx_traits traits_t; FLINTXX_DEFINE_BASICS(fmpq_matxx_expression) FLINTXX_DEFINE_CTORS(fmpq_matxx_expression) FLINTXX_DEFINE_C_REF(fmpq_matxx_expression, fmpq_mat_struct, _mat) template static evaluated_t create_temporary_rowscols( const Expr&, slong rows, slong cols) { return evaluated_t(rows, cols); } FLINTXX_DEFINE_MATRIX_METHODS(traits_t) template static fmpq_matxx_expression reconstruct(const Fmpz_mat& mat, const Fmpz& mod, typename mp::enable_if >::type* = 0, typename mp::enable_if >::type* = 0) { fmpq_matxx_expression res(mat.rows(), mat.cols()); res.set_reconstruct(mat, mod); return res; } template static fmpq_matxx_expression frac(const Fmpz_mat& num, const Fmpz& den, typename mp::enable_if >::type* = 0, typename mp::enable_if >::type* = 0) { fmpq_matxx_expression res(num.rows(), num.cols()); res.set_frac(num, den); return res; } template static fmpq_matxx_expression integer_matrix(const Fmpz_mat& mat, typename mp::enable_if >::type* = 0) { fmpq_matxx_expression res(mat.rows(), mat.cols()); res = mat; return res; } static fmpq_matxx_expression randbits(slong rows, slong cols, frandxx& state, flint_bitcnt_t bits) { fmpq_matxx_expression res(rows, cols); res.set_randbits(state, bits); return res; } static fmpq_matxx_expression randtest(slong rows, slong cols, frandxx& state, flint_bitcnt_t bits) { fmpq_matxx_expression res(rows, cols); res.set_randtest(state, bits); return res; } static fmpq_matxx_expression zero(slong rows, slong cols) {return fmpq_matxx_expression(rows, cols);} static fmpq_matxx_expression one(slong rows, slong cols) { fmpq_matxx_expression res(rows, cols); res.set_one(); return res; } // these only make sense with targets void set_randbits(frandxx& state, flint_bitcnt_t bits) {fmpq_mat_randbits(_mat(), state._data(), bits);} void set_randtest(frandxx& state, flint_bitcnt_t bits) {fmpq_mat_randtest(_mat(), state._data(), bits);} void set_hilbert_matrix() {fmpq_mat_hilbert_matrix(_mat());} void set_zero() {fmpq_mat_zero(_mat());} void set_one() {fmpq_mat_one(_mat());} template void set_frac(const Fmpz_mat& num, const Fmpz& den, typename mp::enable_if >::type* = 0, typename mp::enable_if >::type* = 0) { fmpq_mat_set_fmpz_mat_div_fmpz(num.evaluate()._mat(), den.evaluate()._fmpz()); } template void set_reconstruct(const Fmpz_mat& mat, const Fmpz& mod, typename mp::enable_if >::type* = 0, typename mp::enable_if >::type* = 0) { execution_check(fmpq_mat_set_fmpz_mat_mod_fmpz( _mat(), mat.evaluate()._mat(), mod.evaluate()._fmpz()), "reconstruct", "fmpq_matxx"); } bool pivot(slong r, slong c, permxx* perm = 0) {return fmpq_mat_pivot(maybe_perm_data(perm), _mat(), r, c);} // these cause evaluation slong rank() const {return fmpq_mat_rank(this->evaluate()._mat());} bool is_zero() const {return fmpq_mat_is_zero(this->evaluate()._mat());} bool is_empty() const {return fmpq_mat_is_empty(this->evaluate()._mat());} bool is_square() const {return fmpq_mat_is_square(this->evaluate()._mat());} bool is_integral() const {return fmpq_mat_is_integral(this->evaluate()._mat());} // forwarded lazy ops FLINTXX_DEFINE_MEMBER_UNOP(inv) FLINTXX_DEFINE_MEMBER_UNOP(transpose) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpqxx, det) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpqxx, trace) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(detail::fmpq_matxx_numden_entrywise_rt, numden_entrywise) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(detail::fmpq_matxx_numden_matwise_rt, numden_matwise) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(detail::fmpq_matxx_numden_rowwise_rt, numden_rowwise) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(detail::fmpq_matxx_numden_colwise_rt, numden_colwise) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE_(fmpz_matxx, num_rowwise, num_rowwise) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE_(fmpz_matxx, num_colwise, num_colwise) FLINTXX_DEFINE_MEMBER_BINOP(mul_cleared) FLINTXX_DEFINE_MEMBER_BINOP(mul_direct) FLINTXX_DEFINE_MEMBER_BINOP(solve_dixon) FLINTXX_DEFINE_MEMBER_BINOP(solve_fraction_free) }; namespace detail { struct fmpq_mat_data; } // detail typedef fmpq_matxx_expression fmpq_matxx; typedef fmpq_matxx_expression > fmpq_matxx_ref; typedef fmpq_matxx_expression > fmpq_matxx_srcref; template<> struct matrix_traits { template static slong rows(const M& m) { return fmpq_mat_nrows(m._mat()); } template static slong cols(const M& m) { return fmpq_mat_ncols(m._mat()); } template static fmpqxx_srcref at(const M& m, slong i, slong j) { return fmpqxx_srcref::make(fmpq_mat_entry(m._mat(), i, j)); } template static fmpqxx_ref at(M& m, slong i, slong j) { return fmpqxx_ref::make(fmpq_mat_entry(m._mat(), i, j)); } }; namespace detail { template<> struct fmpq_matxx_traits : matrices::generic_traits_srcref { }; template<> struct fmpq_matxx_traits : matrices::generic_traits_ref { }; template<> struct fmpq_matxx_traits : matrices::generic_traits_nonref { }; struct fmpq_mat_data { typedef fmpq_mat_t& data_ref_t; typedef const fmpq_mat_t& data_srcref_t; fmpq_mat_t inner; fmpq_mat_data(slong m, slong n) { fmpq_mat_init(inner, m, n); } fmpq_mat_data(const fmpq_mat_data& o) { fmpq_mat_init(inner, fmpq_mat_nrows(o.inner), fmpq_mat_ncols(o.inner)); fmpq_mat_set(inner, o.inner); } fmpq_mat_data(fmpq_matxx_srcref o) { fmpq_mat_init(inner, o.rows(), o.cols()); fmpq_mat_set(inner, o._data().inner); } ~fmpq_mat_data() {fmpq_mat_clear(inner);} }; } // detail #define FMPQ_MATXX_COND_S FLINTXX_COND_S(fmpq_matxx) #define FMPQ_MATXX_COND_T FLINTXX_COND_T(fmpq_matxx) namespace traits { template struct is_fmpq_matxx : flint_classes::is_Base { }; } // traits namespace mp { template struct all_fmpq_matxx : mp::and_, all_fmpq_matxx > { }; template struct all_fmpq_matxx : traits::is_fmpq_matxx { }; template struct enable_all_fmpq_matxx : mp::enable_if, Out> { }; } // mp namespace matrices { template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize { template static slong rows(const Expr& e) {return e._data().first();} template static slong cols(const Expr& e) {return e._data().second();} }; template<> struct outsize { template static slong rows(const Expr& e) {return e._data().first().rows();} template static slong cols(const Expr& e) {return e._data().first().cols();} }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; } // matrices namespace vectors { template<> struct outsize { template static unsigned get(const Expr& e) { return e._data().first().rows(); } }; template<> struct outsize { template static unsigned get(const Expr& e) { return e._data().first().cols(); } }; } // vectors // temporary instantiation stuff FLINTXX_DEFINE_TEMPORARY_RULES(fmpq_matxx) namespace rules { FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_MATXX_COND_T, FMPQ_MATXX_COND_S, fmpq_mat_set(to._mat(), from._mat())) FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_MATXX_COND_T, FMPZ_MATXX_COND_S, fmpq_mat_set_fmpz_mat(to._mat(), from._mat())) FLINTXX_DEFINE_SWAP(fmpq_matxx, fmpq_mat_swap(e1._mat(), e2._mat())) FLINTXX_DEFINE_EQUALS(fmpq_matxx, fmpq_mat_equal(e1._mat(), e2._mat())) FLINT_DEFINE_PRINT_COND(FMPQ_MATXX_COND_S, (fmpq_mat_print(from._mat()), 1)) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, fmpq_mat_mul(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpq_matxx, FMPZ_MATXX_COND_S, FMPQ_MATXX_COND_S, fmpq_mat_mul_r_fmpz_mat(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpq_matxx, FMPQ_MATXX_COND_S, FMPZ_MATXX_COND_S, fmpq_mat_mul_fmpz_mat(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_matxx, FMPQ_MATXX_COND_S, FMPZXX_COND_S, fmpq_mat_scalar_mul_fmpz(to._mat(), e1._mat(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpq_matxx, FMPQ_MATXX_COND_S, FMPZXX_COND_S, fmpq_mat_scalar_div_fmpz(to._mat(), e1._mat(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(mul_direct_op, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, fmpq_mat_mul_direct(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(mul_cleared_op, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, fmpq_mat_mul_cleared(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, fmpq_mat_add(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, fmpq_mat_sub(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpq_matxx, FMPQ_MATXX_COND_S, fmpq_mat_neg(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(transpose_op, fmpq_matxx, FMPQ_MATXX_COND_S, fmpq_mat_transpose(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(trace_op, fmpqxx, FMPQ_MATXX_COND_S, fmpq_mat_trace(to._fmpq(), from._mat())) FLINT_DEFINE_THREEARY_EXPR_COND3(mat_at_op, fmpqxx, FMPQ_MATXX_COND_S, traits::fits_into_slong, traits::fits_into_slong, fmpq_set(to._fmpq(), fmpq_mat_entry(e1._mat(), e2, e3))) FLINT_DEFINE_BINARY_EXPR_COND2(hilbert_matrix_op, fmpq_matxx, traits::fits_into_slong, traits::fits_into_slong, to.set_hilbert_matrix()) FLINT_DEFINE_UNARY_EXPR_COND(det_op, fmpqxx, FMPQ_MATXX_COND_S, fmpq_mat_det(to._fmpq(), from._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(solve_fraction_free_op, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, execution_check(fmpq_mat_solve_fraction_free( to._mat(), e1._mat(), e2._mat()), "solve", "fmpq_mat")) FLINT_DEFINE_BINARY_EXPR_COND2(solve_dixon_op, fmpq_matxx, FMPQ_MATXX_COND_S, FMPQ_MATXX_COND_S, execution_check(fmpq_mat_solve_dixon(to._mat(), e1._mat(), e2._mat()), "solve", "fmpq_mat")) FLINT_DEFINE_UNARY_EXPR_COND(inv_op, fmpq_matxx, FMPQ_MATXX_COND_S, execution_check(fmpq_mat_inv(to._mat(), from._mat()), "inv", "fmpq_mat")) FLINT_DEFINE_UNARY_EXPR_COND(num_rowwise_op, fmpz_matxx, FMPQ_MATXX_COND_S, fmpq_mat_get_fmpz_mat_rowwise(to._mat(), 0, from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(num_colwise_op, fmpz_matxx, FMPQ_MATXX_COND_S, fmpq_mat_get_fmpz_mat_colwise(to._mat(), 0, from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(numden_entrywise_op, detail::fmpq_matxx_numden_entrywise_rt, FMPQ_MATXX_COND_S, fmpq_mat_get_fmpz_mat_entrywise(to.template get<0>()._mat(), to.template get<1>()._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(numden_matwise_op, detail::fmpq_matxx_numden_matwise_rt, FMPQ_MATXX_COND_S, fmpq_mat_get_fmpz_mat_matwise(to.template get<0>()._mat(), to.template get<1>()._fmpz(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(numden_rowwise_op, detail::fmpq_matxx_numden_rowwise_rt, FMPQ_MATXX_COND_S, fmpq_mat_get_fmpz_mat_rowwise(to.template get<0>()._mat(), to.template get<1>()._array(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(numden_colwise_op, detail::fmpq_matxx_numden_colwise_rt, FMPQ_MATXX_COND_S, fmpq_mat_get_fmpz_mat_colwise(to.template get<0>()._mat(), to.template get<1>()._array(), from._mat())) namespace rdetail { typedef make_ltuple::type>::type fmpq_matxx_rref_rt; } FLINT_DEFINE_UNARY_EXPR_COND(rref_op, rdetail::fmpq_matxx_rref_rt, FMPQ_MATXX_COND_S, to.template get<0>() = fmpq_mat_rref(to.template get<1>()._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(rref_classical_op, rdetail::fmpq_matxx_rref_rt, FMPQ_MATXX_COND_S, to.template get<0>() = fmpq_mat_rref_classical(to.template get<1>()._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(rref_fraction_free_op, rdetail::fmpq_matxx_rref_rt, FMPQ_MATXX_COND_S, to.template get<0>() = fmpq_mat_rref_fraction_free(to.template get<1>()._mat(), from._mat())) } // rules } // flint #endif flint2-2.8.4/fmpq_mpoly.h000066400000000000000000001022501414523752600152700ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define FMPQ_MPOLY_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "fmpq_poly.h" #include "fmpz_mpoly.h" #ifdef __cplusplus extern "C" { #endif /* Context object ************************************************************/ typedef struct { fmpz_mpoly_ctx_t zctx; } fmpq_mpoly_ctx_struct; typedef fmpq_mpoly_ctx_struct fmpq_mpoly_ctx_t[1]; 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 ********************************************************/ /* 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]; 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 **************************************************************/ FLINT_DLL int fmpq_mpoly_set_str_pretty(fmpq_mpoly_t A, const char * str, const char ** x, const fmpq_mpoly_ctx_t ctx); FLINT_DLL char * fmpq_mpoly_get_str_pretty(const fmpq_mpoly_t A, const char ** x, const fmpq_mpoly_ctx_t ctx); FLINT_DLL int fmpq_mpoly_fprint_pretty(FILE * file, const fmpq_mpoly_t A, const char ** x, const fmpq_mpoly_ctx_t ctx); FMPQ_MPOLY_INLINE 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); } /* 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) { fmpq_mpoly_struct t = *A; *A = *B; *B = t; } /* 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); } FLINT_DLL void fmpq_mpoly_get_fmpq(fmpq_t c, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_set_fmpq(fmpq_mpoly_t A, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_set_fmpz(fmpq_mpoly_t A, const fmpz_t c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_set_ui(fmpq_mpoly_t A, ulong c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL int fmpq_mpoly_equal_fmpq(const fmpq_mpoly_t A, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL int fmpq_mpoly_equal_fmpz(const fmpq_mpoly_t A, const fmpz_t c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL int fmpq_mpoly_equal_ui(const fmpq_mpoly_t A, ulong c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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 *******************************************************************/ FMPQ_MPOLY_INLINE 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); } FMPQ_MPOLY_INLINE 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); } FMPQ_MPOLY_INLINE 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); } FMPQ_MPOLY_INLINE 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); } FMPQ_MPOLY_INLINE 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); } FMPQ_MPOLY_INLINE 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); } FMPQ_MPOLY_INLINE 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); } FMPQ_MPOLY_INLINE 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); } 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)); } FLINT_DLL int fmpq_mpoly_is_monic(const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _fmpq_mpoly_set_coeff_fmpq_fmpz(fmpq_mpoly_t A, const fmpq_t c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_set_coeff_fmpq_fmpz(fmpq_mpoly_t A, const fmpq_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_set_coeff_fmpq_ui(fmpq_mpoly_t A, const fmpq_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void _fmpq_mpoly_get_coeff_fmpq_fmpz(fmpq_t c, const fmpq_mpoly_t A, const fmpz * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_get_coeff_fmpq_fmpz(fmpq_t c, const fmpq_mpoly_t A, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_get_coeff_fmpq_ui(fmpq_t c, const fmpq_mpoly_t A, const ulong * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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 ****************************************************************/ FLINT_DLL int fmpq_mpoly_is_fmpq_poly(const fmpq_mpoly_t A, slong var, const fmpq_mpoly_ctx_t ctx); FLINT_DLL int fmpq_mpoly_get_fmpq_poly(fmpq_poly_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_set_fmpq_poly(fmpq_mpoly_t A, const fmpq_poly_t B, slong var, const fmpq_mpoly_ctx_t ctx); /* comparison ****************************************************************/ FLINT_DLL int fmpq_mpoly_cmp(const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); /* container operations ******************************************************/ FLINT_DLL 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); } FLINT_DLL void fmpq_mpoly_get_term_coeff_fmpq(fmpq_t c, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_set_term_coeff_fmpq(fmpq_mpoly_t A, slong i, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); FMPQ_MPOLY_INLINE 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); } FMPQ_MPOLY_INLINE 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_DLL void fmpq_mpoly_get_term_exp_fmpz(fmpz ** exps, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_get_term_exp_ui(ulong * exps, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_get_term_exp_si(slong * exps, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); FLINT_DLL ulong fmpq_mpoly_get_term_var_exp_ui(const fmpq_mpoly_t A, slong i, slong var, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL void fmpq_mpoly_get_term(fmpq_mpoly_t M, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_get_term_monomial(fmpq_mpoly_t M, const fmpq_mpoly_t A, slong i, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_push_term_fmpq_fmpz(fmpq_mpoly_t A, const fmpq_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_push_term_fmpz_fmpz(fmpq_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_push_term_ui_fmpz(fmpq_mpoly_t A, ulong c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_push_term_si_fmpz(fmpq_mpoly_t A, slong c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_push_term_fmpq_ui(fmpq_mpoly_t A, const fmpq_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_push_term_fmpz_ui(fmpq_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_push_term_ui_ui(fmpq_mpoly_t A, ulong c, const ulong * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_push_term_si_ui(fmpq_mpoly_t A, slong c, const ulong * exp, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_reduce(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL void fmpq_mpoly_reverse(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_assert_canonical(const fmpq_mpoly_t poly, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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 **********************************************************/ FLINT_DLL void fmpq_mpoly_add_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_add_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_add_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_add_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_sub_fmpq(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_t c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_sub_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_sub_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_sub_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_add(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_t C, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpq_mpoly_scalar_mul_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_scalar_mul_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpq_mpoly_scalar_div_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_scalar_div_si(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong c, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_make_monic(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void _fmpq_mpoly_make_monic_inplace(fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); /* Differentiation/Integration ***********************************************/ FLINT_DLL void fmpq_mpoly_derivative(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_integral(fmpq_mpoly_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx); /* Evaluation ****************************************************************/ FLINT_DLL int _fmpq_mpoly_rescale(fmpq_t Acontent, fmpz * Acoeff, const fmpq_mpoly_t B, const fmpq * scales, const fmpq_mpoly_ctx_t ctx); FLINT_DLL int fmpq_mpoly_evaluate_all_fmpq(fmpq_t ev, const fmpq_mpoly_t A, fmpq * const * vals, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ************************************************************/ FLINT_DLL 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 ******************************************************************/ FLINT_DLL int fmpq_mpoly_pow_fmpz(fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpz_t k, const fmpq_mpoly_ctx_t ctx); FLINT_DLL int fmpq_mpoly_pow_ui(fmpq_mpoly_t A, const fmpq_mpoly_t B, ulong k, const fmpq_mpoly_ctx_t ctx); /* Division ******************************************************************/ FLINT_DLL int fmpq_mpoly_divides(fmpq_mpoly_t poly1, const fmpq_mpoly_t poly2, const fmpq_mpoly_t poly3, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_div(fmpq_mpoly_t q, const fmpq_mpoly_t poly2, const fmpq_mpoly_t poly3, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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 ***************************************************************/ FLINT_DLL 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); } FLINT_DLL void fmpq_mpoly_term_content(fmpq_mpoly_t M, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int fmpq_mpoly_gcd(fmpq_mpoly_t G, const fmpq_mpoly_t A, const fmpq_mpoly_t B, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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) ******************************************************************************/ FLINT_DLL void mpoly_void_ring_init_fmpq_mpoly_ctx(mpoly_void_ring_t R, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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 ***************************************************************/ FLINT_DLL void fmpq_mpoly_univar_init(fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_univar_clear(fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_univar_fit_length(fmpq_mpoly_univar_t A, slong length, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_univar_print_pretty(const fmpq_mpoly_univar_t A, const char ** x, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_univar_assert_canonical(fmpq_mpoly_univar_t A, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_to_univar(fmpq_mpoly_univar_t A, const fmpq_mpoly_t B, slong var, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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) { fmpq_mpoly_univar_struct t = *A; *A = *B; *B = t; } 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 ******************************************************************************/ /* 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) */ FMPQ_MPOLY_INLINE 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); } #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpq_mpoly/000077500000000000000000000000001414523752600151175ustar00rootroot00000000000000flint2-2.8.4/fmpq_mpoly/add.c000066400000000000000000000021301414523752600160070ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpq_mpoly/add_fmpq.c000066400000000000000000000037031414523752600170410ustar00rootroot00000000000000/* 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 2.1 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)); } flint2-2.8.4/fmpq_mpoly/cmp.c000066400000000000000000000026651414523752600160530ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mpoly/compose_fmpq_mpoly.c000066400000000000000000000036721414523752600212030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mpoly/compose_fmpq_mpoly_gen.c000066400000000000000000000016141414523752600220260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly/compose_fmpq_poly.c000066400000000000000000000046431414523752600210250ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mpoly/content_vars.c000066400000000000000000000016201414523752600177670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly/derivative.c000066400000000000000000000013151414523752600174250ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/discriminant.c000066400000000000000000000022141414523752600177460ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq_mpoly/div.c000066400000000000000000000020451414523752600160460ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/divides.c000066400000000000000000000020201414523752600167040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly/divrem.c000066400000000000000000000024211414523752600165500ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/divrem_ideal.c000066400000000000000000000037731414523752600177210ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly/equal_fmpq.c000066400000000000000000000013631414523752600174200ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fmpq_mpoly/equal_fmpz.c000066400000000000000000000031451414523752600174310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fmpq_mpoly/evaluate_all.c000066400000000000000000000132471414523752600177300ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mpoly/evaluate_one.c000066400000000000000000000176271414523752600177470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mpoly/fprint_pretty.c000066400000000000000000000050401414523752600201730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" 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; } flint2-2.8.4/fmpq_mpoly/gcd.c000066400000000000000000000030161414523752600160200ustar00rootroot00000000000000/* 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 2.1 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) flint2-2.8.4/fmpq_mpoly/gcd_cofactors.c000066400000000000000000000025451414523752600200710ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly/get_coeff_fmpq_fmpz.c000066400000000000000000000040631414523752600212660ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mpoly/get_coeff_fmpq_monomial.c000066400000000000000000000014151414523752600221230ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/get_coeff_fmpq_ui.c000066400000000000000000000016351414523752600207310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly/get_coeff_vars_ui.c000066400000000000000000000014351414523752600207370ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/get_fmpq.c000066400000000000000000000013651414523752600170720ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/get_set_is_fmpq_poly.c000066400000000000000000000030351414523752600214770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly/get_str_pretty.c000066400000000000000000000067341414523752600203530ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/fmpq_mpoly/get_term.c000066400000000000000000000022141414523752600170700ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly/get_term_coeff_fmpq.c000066400000000000000000000014011414523752600212520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/get_term_exp_fmpz.c000066400000000000000000000017031414523752600210020ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly/get_term_exp_si.c000066400000000000000000000016771414523752600204530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly/get_term_exp_ui.c000066400000000000000000000016771414523752600204550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly/get_term_monomial.c000066400000000000000000000021671414523752600207720ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly/get_term_var_exp_si.c000066400000000000000000000016751414523752600213210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly/get_term_var_exp_ui.c000066400000000000000000000016751414523752600213230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly/inflate.c000066400000000000000000000012641414523752600167100ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/inlines.c000066400000000000000000000011431414523752600167230ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #define FMPQ_MPOLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpq_mpoly.h" flint2-2.8.4/fmpq_mpoly/integral.c000066400000000000000000000014071414523752600170720ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/is_canonical.c000066400000000000000000000036571414523752600177200ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly/is_monic.c000066400000000000000000000015541414523752600170700ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq_mpoly/make_monic.c000066400000000000000000000022401414523752600173630ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/mul.c000066400000000000000000000014251414523752600160620ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/pow_fmpz.c000066400000000000000000000013301414523752600171210ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq_mpoly/pow_ui.c000066400000000000000000000024061414523752600165670ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly/push_term_fmpq_fmpz.c000066400000000000000000000041241414523752600213510ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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_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_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); } flint2-2.8.4/fmpq_mpoly/push_term_fmpq_ui.c000066400000000000000000000055571414523752600210250ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly/reduce.c000066400000000000000000000032201414523752600165270ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly/reduce_easy.c000066400000000000000000000017621414523752600175610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpq_mpoly/repack_bits.c000066400000000000000000000013521414523752600175520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly/rescale.c000066400000000000000000000150461414523752600167070ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mpoly/resultant.c000066400000000000000000000025671414523752600173160ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq_mpoly/scalar_div_fmpq.c000066400000000000000000000011671414523752600204220ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/scalar_div_fmpz.c000066400000000000000000000021461414523752600204310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/scalar_mul_fmpq.c000066400000000000000000000013541414523752600204330ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fmpq_mpoly/scalar_mul_fmpz.c000066400000000000000000000023331414523752600204420ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/set_coeff_fmpq_fmpz.c000066400000000000000000000075241414523752600213070ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mpoly/set_coeff_fmpq_monomial.c000066400000000000000000000022761414523752600221450ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mpoly/set_coeff_fmpq_ui.c000066400000000000000000000016161414523752600207440ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly/set_fmpq.c000066400000000000000000000013071414523752600171020ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fmpq_mpoly/set_fmpz.c000066400000000000000000000025531414523752600171170ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fmpq_mpoly/set_str_pretty.c000066400000000000000000000024271414523752600203620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/fmpq_mpoly/set_term_coeff_fmpq.c000066400000000000000000000040711414523752600212740ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpq_mpoly/sqrt.c000066400000000000000000000020521414523752600162530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly/sub.c000066400000000000000000000021561414523752600160600ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpq_mpoly/sub_fmpq.c000066400000000000000000000037461414523752600171110ustar00rootroot00000000000000/* 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 2.1 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)); } flint2-2.8.4/fmpq_mpoly/term_content.c000066400000000000000000000013711414523752600177660ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly/test/000077500000000000000000000000001414523752600160765ustar00rootroot00000000000000flint2-2.8.4/fmpq_mpoly/test/t-add_sub.c000066400000000000000000000317131414523752600201110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("add/sub...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); 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); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-add_sub_fmpq.c000066400000000000000000000074641414523752600211420ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("add/sub_fmpq...."); fflush(stdout); /* 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"); 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"); 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"); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-add_sub_fmpz.c000066400000000000000000000064711414523752600211500ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("add/sub_fmpz...."); fflush(stdout); /* 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); 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); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-cmp.c000066400000000000000000000137261414523752600172730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { int result; slong i, j1, j2; FLINT_TEST_INIT(state); flint_printf("cmp...."); fflush(stdout); /* 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-compose_fmpq_mpoly.c000066400000000000000000000245471414523752600224270ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { slong i, j, v; FLINT_TEST_INIT(state); flint_printf("compose_fmpq_mpoly...."); fflush(stdout); { 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); 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); 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); 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); 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); 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); flint_abort(); } if (!fmpq_mpoly_equal(f, g, ctx)) { printf("FAIL\n"); flint_printf("Check composition with identity\ni: %wd\n", i); 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/nvars1 + 1); len2 = n_randint(state, 25/nvars2 + 1); exp_bound1 = n_randint(state, 15/nvars1 + 2) + 1; exp_bound2 = n_randint(state, 15/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); 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); 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); flint_abort(); } if (!fmpq_equal(fe, ge)) { printf("FAIL\n"); flint_printf("Check composition and evalall commute\ni: %wd\n", i); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-compose_fmpq_poly.c000066400000000000000000000211261414523752600222400ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { slong i, v; FLINT_TEST_INIT(state); flint_printf("compose_fmpq_poly...."); fflush(stdout); /* 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/nvars1 + 1); len2 = n_randint(state, 40); exp_bound1 = n_randint(state, 100/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); 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); 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/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); 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); 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-content.c000066400000000000000000000035301414523752600201560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("content...."); fflush(stdout); /* 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); flint_abort(); } } fmpq_clear(g1); fmpq_clear(g2); fmpq_clear(t); fmpq_mpoly_clear(f, ctx); fmpq_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-content_vars.c000066400000000000000000000073541414523752600212210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("content_vars...."); fflush(stdout); 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; 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); SLONG_SWAP(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"); flint_abort(); } if (fmpq_mpoly_is_zero(g, ctx)) { if (!fmpq_mpoly_is_zero(f, ctx)) { flint_printf("FAIL: check zero content\n"); 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"); flint_abort(); } } if (!fmpq_mpoly_divides(t, f, g, ctx)) { flint_printf("FAIL: check content divides\n"); flint_abort(); } if (!fmpq_mpoly_content_vars(t, t, vars, num_vars, ctx)) { flint_printf("FAIL: check cofactor content could be computed\n"); flint_abort(); } if (!fmpq_mpoly_is_one(t, ctx)) { flint_printf("FAIL: check cofactor content is one\n"); flint_abort(); } } if (!fmpq_mpoly_content_vars(f, f, vars, num_vars, ctx)) { flint_printf("FAIL: check aliased content could be computed\n"); flint_abort(); } if (!fmpq_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: check aliasing\n"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-degree.c000066400000000000000000000101131414523752600177320ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("degree...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-degrees_term_exp_fits_ui_si.c000066400000000000000000000202471414523752600242460ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("degrees_term_exp_fits_ui_si...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); flint_abort(); } } else { printf("FAIL\nFLINT_BITS is not 64 or 32\n"); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-derivative_integral.c000066400000000000000000000203221414523752600225310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("derivative/integral...."); fflush(stdout); /* 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; ordering_t ord; slong nvars, len, len1, len2; slong idx, coeff_bits, exp_bits, exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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); flint_abort(); 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; ordering_t ord; slong nvars, len, len1, len2; slong idx, coeff_bits, exp_bits, exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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); 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; ordering_t ord; slong nvars, len, len1, len2; slong idx, coeff_bits, exp_bits, exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(f1, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-div.c000066400000000000000000000310051414523752600172640ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("div...."); fflush(stdout); { 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"); 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); 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/nvars/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); 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/nvars/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); 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/nvars/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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-divides.c000066400000000000000000000311561414523752600201400ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int main(void) { int i, j, result, ok1, ok2; FLINT_TEST_INIT(state); flint_printf("divides...."); fflush(stdout); /* 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); 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; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits, exp_bits, exp_bits1, exp_bits2, maxbits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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/nvars + 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); 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); 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; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits, exp_bits, exp_bits1, exp_bits2, maxbits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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/nvars + 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); 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); 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; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits, exp_bits, exp_bits1, exp_bits2, maxbits; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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/nvars + 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); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-divrem.c000066400000000000000000000324651414523752600200030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("divrem...."); fflush(stdout); /* 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; ordering_t ord; slong nvars, len, len1, len2; slong coeff_bits, exp_bits, exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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); 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; 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; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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; exp_bound = n_randint(state, 25/nvars + 1) + 2; exp_bound1 = n_randint(state, 35/nvars + 1) + 4; exp_bound2 = n_randint(state, 30/nvars + 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); 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; 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; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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; exp_bound = n_randint(state, 35/nvars + 1) + 2; exp_bound1 = n_randint(state, 35/nvars + 1) + 4; exp_bound2 = n_randint(state, 30/nvars + 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); 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; 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; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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; exp_bound = n_randint(state, 25/nvars + 1) + 2; exp_bound1 = n_randint(state, 35/nvars + 1) + 4; exp_bound2 = n_randint(state, 30/nvars + 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); 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; 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; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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; exp_bound = n_randint(state, 25/nvars + 1) + 2; exp_bound1 = n_randint(state, 35/nvars + 1) + 4; exp_bound2 = n_randint(state, 30/nvars + 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); 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; 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; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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; exp_bound = n_randint(state, 25/nvars + 1) + 2; exp_bound1 = n_randint(state, 35/nvars + 1) + 4; exp_bound2 = n_randint(state, 30/nvars + 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-divrem_ideal.c000066400000000000000000000171031414523752600211310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { int i, j, w, result; FLINT_TEST_INIT(state); flint_printf("divrem_ideal...."); fflush(stdout); /* 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; ordering_t ord; 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)); ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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/nvars + 1) + 2; exp_bound1 = n_randint(state, 25/nvars + 1) + 2; exp_bound2 = n_randint(state, 20/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); 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; ordering_t ord; 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)); ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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/nvars + 1) + 2; exp_bound1 = n_randint(state, 25/nvars + 1) + 2; exp_bound2 = n_randint(state, 20/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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-equal_is_fmpq.c000066400000000000000000000213421414523752600213320ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { int result; FLINT_TEST_INIT(state); flint_printf("equal_is_fmpq...."); fflush(stdout); { 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-evaluate.c000066400000000000000000000175021414523752600203160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { slong i, j, v; FLINT_TEST_INIT(state); flint_printf("evaluate...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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; 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); exp_bound1 = n_randint(state, 2000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 2000/nvars/nvars) + 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-gcd.c000066400000000000000000000614201414523752600172430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" 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); 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); 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpq_mpoly_clear(ca, ctx); fmpq_mpoly_clear(cb, ctx); fmpq_mpoly_clear(cg, ctx); } int main(void) { const slong max_threads = 5; slong i, j, k, tmul = 5; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 1; #endif flint_printf("gcd...."); fflush(stdout); { 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-gcd_brown.c000066400000000000000000000115641414523752600204560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_mpoly.h" #include "ulong_extras.h" 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpq_mpoly_clear(ca, ctx); fmpq_mpoly_clear(cb, ctx); fmpq_mpoly_clear(cg, ctx); } int main(void) { slong tmul = 10; slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_brown...."); fflush(stdout); { 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; 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); degbound = 1 + 50/fmpq_mpoly_ctx_nvars(ctx)/fmpq_mpoly_ctx_nvars(ctx); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-gcd_cofactors.c000066400000000000000000000777371414523752600213300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); } int main(void) { const slong max_threads = 5; slong i, j, k, tmul = 3; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 1; #endif flint_printf("gcd_cofactors...."); fflush(stdout); { 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-gcd_hensel.c000066400000000000000000000125601414523752600206020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpq_mpoly_clear(ca, ctx); fmpq_mpoly_clear(cb, ctx); fmpq_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("gcd_hensel...."); fflush(stdout); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-gcd_subresultant.c000066400000000000000000000123621414523752600220570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpq_mpoly_clear(ca, ctx); fmpq_mpoly_clear(cb, ctx); fmpq_mpoly_clear(cg, ctx); } int main(void) { slong i, j; slong tmul = 5; FLINT_TEST_INIT(state); flint_printf("gcd_subresultant...."); fflush(stdout); { 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/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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-gcd_zippel.c000066400000000000000000000102741414523752600206270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int main(void) { slong i, j; slong tmul = 10; FLINT_TEST_INIT(state); flint_printf("gcd_zippel...."); fflush(stdout); 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); 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); 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); 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); 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-gcd_zippel2.c000066400000000000000000000130421414523752600207050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpq_mpoly_clear(ca, ctx); fmpq_mpoly_clear(cb, ctx); fmpq_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("gcd_zippel2...."); fflush(stdout); { 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-gen.c000066400000000000000000000046321414523752600172610ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gen/is_gen...."); fflush(stdout); 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); 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); 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); flint_abort(); } fmpq_mpoly_clear(f1, ctx); fmpq_mpoly_clear(f2, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-get_coeff_vars_ui.c000066400000000000000000000123601414523752600221560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j1, j2; FLINT_TEST_INIT(state); flint_printf("get_coeff_vars_ui...."); fflush(stdout); /* 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"); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-get_set_coeff_fmpq_fmpz.c000066400000000000000000000043141414523752600233600ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { int i, j, k, result; FLINT_TEST_INIT(state); flint_printf("get/set_term_fmpq_fmpz...."); fflush(stdout); /* 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-get_set_coeff_fmpq_monomial.c000066400000000000000000000074401414523752600242220ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("get_set_coeff_fmpq_monomial...."); fflush(stdout); 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); 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); 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); flint_abort(); } } for (k = 0; k < ctx->zctx->minfo->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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-get_set_coeff_fmpq_ui.c000066400000000000000000000040231414523752600230160ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { int i, j, k, result; FLINT_TEST_INIT(state); flint_printf("get/set_term_fmpq_ui...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp); } fmpq_mpoly_clear(f, ctx); fmpq_clear(c); fmpq_clear(d); fmpq_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-get_set_is_fmpq.c000066400000000000000000000042301414523752600216520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("get_set_is_fmpq...."); fflush(stdout); /* 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); 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); 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); flint_abort(); } fmpq_mpoly_clear(f, ctx); fmpq_clear(c); fmpq_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-get_set_str_pretty.c000066400000000000000000000034761414523752600224460ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("get/set_str_pretty...."); fflush(stdout); { 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); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(f1, ctx); } } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-get_set_term_coeff_fmpq.c000066400000000000000000000043011414523752600233470ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("get_set_term_coeff_fmpq...."); fflush(stdout); /* 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); 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); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_clear(c); fmpq_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-get_set_term_exp_fmpz.c000066400000000000000000000057671414523752600231130ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get_set_term_exp_fmpz...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpq_mpoly_clear(f, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-get_set_term_exp_si.c000066400000000000000000000055711414523752600225430ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get_set_term_exp_si...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-get_set_term_exp_ui.c000066400000000000000000000054761414523752600225510ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get_set_term_exp_ui...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-get_term.c000066400000000000000000000042101414523752600203060ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("get_term...."); fflush(stdout); /* 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); flint_abort(); } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-get_term_monomial.c000066400000000000000000000050141414523752600222040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("get_term_monomial...."); fflush(stdout); /* 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-mul.c000066400000000000000000000137401414523752600173050ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); /* 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); 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); 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); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-pow_fmpz.c000066400000000000000000000042731414523752600203520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int main(void) { int i, j, k, result; FLINT_TEST_INIT(state); flint_printf("pow_fmpz...."); fflush(stdout); /* 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-pow_ui.c000066400000000000000000000100371414523752600200060ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int main(void) { int i, j, k, result; FLINT_TEST_INIT(state); flint_printf("pow_ui...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-push_term_fmpq_fmpz.c000066400000000000000000000076501414523752600226000ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("push_back_fmpq_fmpz...."); fflush(stdout); /* 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; fmpz ** 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 = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); exp2 = (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]); } 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); /* 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); /* 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); 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); 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); 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); for (k = 0; k < nvars; k++) { fmpz_clear(exp2[k]); flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(exp2); flint_free(exp); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-push_term_fmpq_ui.c000066400000000000000000000067321414523752600222410ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("push_back_fmpq_ui...."); fflush(stdout); /* 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-resultant_discriminant.c000066400000000000000000000201761414523752600232760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("resultant_discriminant...."); fflush(stdout); /* 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"); flint_abort(); } if (!fmpq_mpoly_equal(d, d1, ctx)) { flint_printf("FAIL: Check quadratic polynomial\n"); 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_rand(ctx, state, 1); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-scalar_mul_div_fmpq.c000066400000000000000000000067321414523752600225220ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul/div_fmpq...."); fflush(stdout); /* 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); 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); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-scalar_mul_div_fmpz.c000066400000000000000000000067221414523752600225320ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul/div_fmpz...."); fflush(stdout); /* 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); 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); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-scalar_mul_fmpq.c000066400000000000000000000103451414523752600216530ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpq...."); fflush(stdout); /* 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; ordering_t ord; fmpq_t a, b, c; slong nvars, len, coeff_bits, exp_bits; fmpq_init(a); fmpq_init(b); fmpq_init(c); ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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); 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; ordering_t ord; fmpq_t c; slong nvars, len, coeff_bits, exp_bits; fmpq_init(c); ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpq_mpoly_ctx_init(ctx, nvars, ord); 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); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-sqrt.c000066400000000000000000000131131414523752600174730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("sqrt...."); fflush(stdout); /* 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"); 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); 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); flint_abort(); } } else if (!fmpq_mpoly_is_zero(g, ctx)) { flint_printf("FAIL: Check nonsquare returns 0 sqrt\n"); 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"); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(h, ctx); fmpq_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-term_content.c000066400000000000000000000072411414523752600212100ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("term_content...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); flint_abort(); } } fmpq_mpoly_clear(f, ctx); fmpq_mpoly_clear(g, ctx); fmpq_mpoly_clear(k, ctx); fmpq_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-total_degree.c000066400000000000000000000120071414523752600211410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); } int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("total_degree...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/test/t-univar.c000066400000000000000000000066561414523752600200240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("univar...."); fflush(stdout); /* 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_mpoly/univar.c000066400000000000000000000260751414523752600166010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly/void_ring.c000066400000000000000000000071701414523752600172500ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq_mpoly_factor.h000066400000000000000000000073731414523752600166400ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define FMPQ_MPOLY_FACTOR_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "fmpq_mpoly.h" #include "fmpz_mpoly_factor.h" #ifdef __cplusplus extern "C" { #endif 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]; FLINT_DLL void fmpq_mpoly_factor_init(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_factor_realloc(fmpq_mpoly_factor_t f, slong alloc, const fmpq_mpoly_ctx_t ctx); FLINT_DLL void fmpq_mpoly_factor_fit_length(fmpq_mpoly_factor_t f, slong len, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL void fmpq_mpoly_factor_sort(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx); FLINT_DLL int fmpq_mpoly_factor_make_monic(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx); FLINT_DLL int fmpq_mpoly_factor_make_integral(fmpq_mpoly_factor_t f, const fmpq_mpoly_ctx_t ctx); FLINT_DLL int fmpq_mpoly_factor_squarefree(fmpq_mpoly_factor_t f, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); FLINT_DLL int fmpq_mpoly_factor(fmpq_mpoly_factor_t f, const fmpq_mpoly_t A, const fmpq_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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 flint2-2.8.4/fmpq_mpoly_factor/000077500000000000000000000000001414523752600164555ustar00rootroot00000000000000flint2-2.8.4/fmpq_mpoly_factor/clear.c000066400000000000000000000014051414523752600177070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly_factor/expand.c000066400000000000000000000021121414523752600200740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly_factor/factor.c000066400000000000000000000015451414523752600201040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly_factor/factor_make_integral.c000066400000000000000000000017201414523752600227610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly_factor/factor_make_monic.c000066400000000000000000000023321414523752600222610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly_factor/factor_squarefree.c000066400000000000000000000015341414523752600223240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpq_mpoly_factor/fit_length.c000066400000000000000000000012771414523752600207530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fmpq_mpoly_factor/init.c000066400000000000000000000011651414523752600175670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly_factor/inlines.c000066400000000000000000000011611414523752600202610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #define FMPQ_MPOLY_FACTOR_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpq_mpoly_factor.h" flint2-2.8.4/fmpq_mpoly_factor/realloc.c000066400000000000000000000036501414523752600202460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpq_mpoly_factor/sort.c000066400000000000000000000034251414523752600176140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_mpoly_factor/swap_fmpz_mpoly_factor.c000066400000000000000000000017251414523752600234120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpq_mpoly_factor/test/000077500000000000000000000000001414523752600174345ustar00rootroot00000000000000flint2-2.8.4/fmpq_mpoly_factor/test/t-factor.c000066400000000000000000000107141414523752600213220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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); } int main(void) { slong i, j, tmul = 25; FLINT_TEST_INIT(state); flint_printf("factor...."); fflush(stdout); 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 nfacs, len; ulong expbound, powbound, pow; fmpq_mpoly_ctx_init_rand(ctx, state, 8); fmpq_mpoly_init(a, ctx); fmpq_mpoly_init(t, ctx); nfacs = 1 + (5 + n_randint(state, 5))/ctx->zctx->minfo->nvars; expbound = 3 + 40/nfacs/ctx->zctx->minfo->nvars; 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly.h000066400000000000000000001033441414523752600151200ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPQ_POLY_INLINE static __inline__ #endif #include #include "fmpz.h" #include "fmpq.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "flint.h" #ifdef __cplusplus extern "C" { #endif /* Type definitions ********************************************************/ typedef struct { fmpz * coeffs; fmpz_t den; slong alloc; slong length; } fmpq_poly_struct; typedef fmpq_poly_struct fmpq_poly_t[1]; 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 *******************************************************/ FLINT_DLL void fmpq_poly_init(fmpq_poly_t poly); FLINT_DLL void fmpq_poly_init2(fmpq_poly_t poly, slong alloc); FLINT_DLL void fmpq_poly_realloc(fmpq_poly_t poly, slong alloc); FLINT_DLL void fmpq_poly_fit_length(fmpq_poly_t poly, slong len); FLINT_DLL void _fmpq_poly_set_length(fmpq_poly_t poly, slong len); FLINT_DLL void fmpq_poly_clear(fmpq_poly_t poly); FLINT_DLL 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) FMPQ_POLY_INLINE 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); } FMPQ_POLY_INLINE void fmpq_poly_get_denominator(fmpz_t den, const fmpq_poly_t poly) { fmpz_set(den, fmpq_poly_denref(poly)); } /* Canonicalisation *************************************/ FLINT_DLL void _fmpq_poly_canonicalise(fmpz * rpoly, fmpz_t den, slong len); FLINT_DLL void fmpq_poly_canonicalise(fmpq_poly_t poly); FLINT_DLL int _fmpq_poly_is_canonical(const fmpz * poly, const fmpz_t den, slong len); FLINT_DLL 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 ***********************************************************/ FLINT_DLL void fmpq_poly_randtest(fmpq_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits_in); FLINT_DLL void fmpq_poly_randtest_unsigned(fmpq_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits_in); FLINT_DLL 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 ***************************************/ FLINT_DLL void fmpq_poly_set(fmpq_poly_t poly1, const fmpq_poly_t poly2); FLINT_DLL void fmpq_poly_set_si(fmpq_poly_t poly, slong x); FLINT_DLL void fmpq_poly_set_ui(fmpq_poly_t poly, ulong x); FLINT_DLL void fmpq_poly_set_fmpz(fmpq_poly_t poly, const fmpz_t x); FLINT_DLL void fmpq_poly_set_fmpq(fmpq_poly_t poly, const fmpq_t x); FLINT_DLL void fmpq_poly_set_mpz(fmpq_poly_t poly, const mpz_t x); FLINT_DLL void fmpq_poly_set_mpq(fmpq_poly_t poly, const mpq_t x); FLINT_DLL void fmpq_poly_set_fmpz_poly(fmpq_poly_t rop, const fmpz_poly_t op); FLINT_DLL void _fmpq_poly_get_nmod_poly(nmod_poly_t rop, const fmpq_poly_t op); FLINT_DLL void fmpq_poly_get_nmod_poly_den(nmod_poly_t rop, const fmpq_poly_t op, int den); FLINT_DLL void fmpq_poly_get_nmod_poly(nmod_poly_t rop, const fmpq_poly_t op); FLINT_DLL void fmpq_poly_set_nmod_poly(fmpq_poly_t rop, const nmod_poly_t op); FLINT_DLL void _fmpq_poly_set_array_mpq(fmpz * poly, fmpz_t den, const mpq_t * a, slong n); FLINT_DLL void fmpq_poly_set_array_mpq(fmpq_poly_t poly, const mpq_t * a, slong n); FLINT_DLL int _fmpq_poly_set_str(fmpz * poly, fmpz_t den, const char * str, slong len); FLINT_DLL int fmpq_poly_set_str(fmpq_poly_t poly, const char * str); FLINT_DLL char * fmpq_poly_get_str(const fmpq_poly_t poly); FLINT_DLL char * fmpq_poly_get_str_pretty(const fmpq_poly_t poly, const char * var); FLINT_DLL char * _fmpq_poly_get_str_pretty(const fmpz *poly, const fmpz_t den, slong len, const char *var); FLINT_DLL void fmpq_poly_zero(fmpq_poly_t poly); FMPQ_POLY_INLINE 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_DLL void fmpq_poly_neg(fmpq_poly_t poly1, const fmpq_poly_t poly2); FLINT_DLL void fmpq_poly_inv(fmpq_poly_t poly1, const fmpq_poly_t poly2); FLINT_DLL void fmpq_poly_swap(fmpq_poly_t poly1, fmpq_poly_t poly2); FMPQ_POLY_INLINE 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_DLL void fmpq_poly_set_trunc(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void fmpq_poly_get_slice(fmpq_poly_t rop, const fmpq_poly_t op, slong i, slong j); FLINT_DLL void fmpq_poly_reverse(fmpq_poly_t res, const fmpq_poly_t poly, slong n); /* Getting and setting coefficients ****************************************/ FLINT_DLL void fmpq_poly_get_coeff_fmpz(fmpz_t x, const fmpq_poly_t poly, slong n); FLINT_DLL void fmpq_poly_get_coeff_fmpq(fmpq_t x, const fmpq_poly_t poly, slong n); FLINT_DLL void fmpq_poly_get_coeff_mpq(mpq_t x, const fmpq_poly_t poly, slong n); FLINT_DLL void fmpq_poly_set_coeff_si(fmpq_poly_t poly, slong n, slong x); FLINT_DLL void fmpq_poly_set_coeff_ui(fmpq_poly_t poly, slong n, ulong x); FLINT_DLL void fmpq_poly_set_coeff_fmpz(fmpq_poly_t poly, slong n, const fmpz_t x); FLINT_DLL void fmpq_poly_set_coeff_fmpq(fmpq_poly_t poly, slong n, const fmpq_t x); FLINT_DLL void fmpq_poly_set_coeff_mpz(fmpq_poly_t poly, slong n, const mpz_t x); FLINT_DLL void fmpq_poly_set_coeff_mpq(fmpq_poly_t poly, slong n, const mpq_t x); /* Comparison **************************************************************/ FLINT_DLL int fmpq_poly_equal(const fmpq_poly_t poly1, const fmpq_poly_t poly2); FLINT_DLL int _fmpq_poly_cmp(const fmpz * lpoly, const fmpz_t lden, const fmpz * rpoly, const fmpz_t rden, slong len); FLINT_DLL int fmpq_poly_cmp(const fmpq_poly_t left, const fmpq_poly_t right); FLINT_DLL 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); FLINT_DLL 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); } FMPQ_POLY_INLINE int fmpq_poly_is_one(const fmpq_poly_t poly) { return (poly->length == WORD(1)) && (fmpz_equal(poly->coeffs, poly->den)); } 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)); } /* Deprecated */ #define fmpq_poly_is_x fmpq_poly_is_gen /* Addition and subtraction ************************************************/ FLINT_DLL 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); FLINT_DLL void fmpq_poly_add(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2); FLINT_DLL 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); FLINT_DLL void fmpq_poly_add_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, int can); FLINT_DLL void fmpq_poly_add_si(fmpq_poly_t res, const fmpq_poly_t poly, slong c); FLINT_DLL void fmpq_poly_add_fmpz(fmpq_poly_t res, const fmpq_poly_t poly, const fmpz_t c); FLINT_DLL void fmpq_poly_add_fmpq(fmpq_poly_t res, const fmpq_poly_t poly, const fmpq_t c); FLINT_DLL 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); FLINT_DLL void fmpq_poly_add_series(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n); FLINT_DLL 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); FLINT_DLL void fmpq_poly_add_series_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n, int can); FLINT_DLL 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); FLINT_DLL void fmpq_poly_sub(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2); FLINT_DLL void fmpq_poly_sub_si(fmpq_poly_t res, const fmpq_poly_t poly, slong c); FLINT_DLL void fmpq_poly_si_sub(fmpq_poly_t res, slong c, const fmpq_poly_t poly); FLINT_DLL void fmpq_poly_sub_fmpz(fmpq_poly_t res, const fmpq_poly_t poly, const fmpz_t c); FLINT_DLL void fmpq_poly_fmpz_sub(fmpq_poly_t res, const fmpz_t c, const fmpq_poly_t poly); FLINT_DLL void fmpq_poly_sub_fmpq(fmpq_poly_t res, const fmpq_poly_t poly, const fmpq_t c); FLINT_DLL void fmpq_poly_fmpq_sub(fmpq_poly_t res, const fmpq_t c, const fmpq_poly_t poly); FLINT_DLL 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); FLINT_DLL void fmpq_poly_sub_can(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, int can); FLINT_DLL 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); FLINT_DLL void fmpq_poly_sub_series(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n); FLINT_DLL 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); FLINT_DLL 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 **************************************/ FLINT_DLL void _fmpq_poly_scalar_mul_si(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong c); FLINT_DLL void _fmpq_poly_scalar_mul_ui(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, ulong c); FLINT_DLL void _fmpq_poly_scalar_mul_fmpz(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t c); FLINT_DLL 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); FLINT_DLL void fmpq_poly_scalar_mul_si(fmpq_poly_t rop, const fmpq_poly_t op, slong c); FLINT_DLL void fmpq_poly_scalar_mul_ui(fmpq_poly_t rop, const fmpq_poly_t op, ulong c); FLINT_DLL void fmpq_poly_scalar_mul_fmpz(fmpq_poly_t rop, const fmpq_poly_t op, const fmpz_t c); FLINT_DLL void fmpq_poly_scalar_mul_fmpq(fmpq_poly_t rop, const fmpq_poly_t op, const fmpq_t c); FLINT_DLL void fmpq_poly_scalar_mul_mpz(fmpq_poly_t rop, const fmpq_poly_t op, const mpz_t c); FLINT_DLL void fmpq_poly_scalar_mul_mpq(fmpq_poly_t rop, const fmpq_poly_t op, const mpq_t c); FLINT_DLL void _fmpq_poly_scalar_div_si(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong c); FLINT_DLL void _fmpq_poly_scalar_div_ui(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, ulong c); FLINT_DLL void _fmpq_poly_scalar_div_fmpz(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t c); FLINT_DLL 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); FLINT_DLL void fmpq_poly_scalar_div_si(fmpq_poly_t rop, const fmpq_poly_t op, slong c); FLINT_DLL void fmpq_poly_scalar_div_ui(fmpq_poly_t rop, const fmpq_poly_t op, ulong c); FLINT_DLL void fmpq_poly_scalar_div_fmpz(fmpq_poly_t rop, const fmpq_poly_t op, const fmpz_t c); FLINT_DLL void fmpq_poly_scalar_div_fmpq(fmpq_poly_t rop, const fmpq_poly_t op, const fmpq_t c); FLINT_DLL void fmpq_poly_scalar_div_mpz(fmpq_poly_t rop, const fmpq_poly_t op, const mpz_t c); FLINT_DLL void fmpq_poly_scalar_div_mpq(fmpq_poly_t rop, const fmpq_poly_t op, const mpq_t c); /* Multiplication **********************************************************/ FLINT_DLL 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); FLINT_DLL void fmpq_poly_mul(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2); FLINT_DLL 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); FLINT_DLL 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 ****************************************************************/ FLINT_DLL void _fmpq_poly_pow(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, ulong e); FLINT_DLL void fmpq_poly_pow(fmpq_poly_t rpoly, const fmpq_poly_t poly, ulong e); FLINT_DLL void _fmpq_poly_pow_trunc(fmpz * res, fmpz_t resden, const fmpz * f, const fmpz_t fden, slong flen, ulong exp, slong len); FLINT_DLL void fmpq_poly_pow_trunc(fmpq_poly_t res, const fmpq_poly_t poly, ulong exp, slong len); /* Shifting ****************************************************************/ FLINT_DLL void fmpq_poly_shift_left(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void fmpq_poly_shift_right(fmpq_poly_t res, const fmpq_poly_t poly, slong n); /* Euclidean division ******************************************************/ FLINT_DLL 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); FLINT_DLL void fmpq_poly_divrem(fmpq_poly_t Q, fmpq_poly_t R, const fmpq_poly_t poly1, const fmpq_poly_t poly2); FLINT_DLL 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); FLINT_DLL void fmpq_poly_div(fmpq_poly_t Q, const fmpq_poly_t poly1, const fmpq_poly_t poly2); FLINT_DLL 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); FLINT_DLL void fmpq_poly_rem(fmpq_poly_t R, const fmpq_poly_t poly1, const fmpq_poly_t poly2); /* Precomputed inverse *****************************************************/ FLINT_DLL fmpq_poly_struct * _fmpq_poly_powers_precompute(const fmpz * B, const fmpz_t denB, slong len); FLINT_DLL void fmpq_poly_powers_precompute(fmpq_poly_powers_precomp_t pinv, fmpq_poly_t poly); FLINT_DLL void _fmpq_poly_powers_clear(fmpq_poly_struct * powers, slong len); FLINT_DLL void fmpq_poly_powers_clear(fmpq_poly_powers_precomp_t pinv); FLINT_DLL 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); FLINT_DLL 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 ******************************************************/ FLINT_DLL 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); FLINT_DLL int fmpq_poly_divides(fmpq_poly_t q, const fmpq_poly_t poly1, const fmpq_poly_t poly2); FLINT_DLL slong fmpq_poly_remove(fmpq_poly_t q, const fmpq_poly_t poly1, const fmpq_poly_t poly2); /* Power series division ***************************************************/ FLINT_DLL void _fmpq_poly_inv_series_newton(fmpz * Qinv, fmpz_t Qinvden, const fmpz * Q, const fmpz_t Qden, slong Qlen, slong n); FLINT_DLL 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); } FLINT_DLL 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); FLINT_DLL void fmpq_poly_div_series(fmpq_poly_t Q, const fmpq_poly_t A, const fmpq_poly_t B, slong n); /* Greatest common divisor **************************************************/ FLINT_DLL void _fmpq_poly_gcd(fmpz *G, fmpz_t denG, const fmpz *A, slong lenA, const fmpz *B, slong lenB); FLINT_DLL void fmpq_poly_gcd(fmpq_poly_t G, const fmpq_poly_t A, const fmpq_poly_t B); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _fmpq_poly_lcm(fmpz *G, fmpz_t denG, const fmpz *A, slong lenA, const fmpz *B, slong lenB); FLINT_DLL void fmpq_poly_lcm(fmpq_poly_t L, const fmpq_poly_t A, const fmpq_poly_t B); FLINT_DLL 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); FLINT_DLL void fmpq_poly_resultant(fmpq_t r, const fmpq_poly_t f, const fmpq_poly_t g); FLINT_DLL 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); FLINT_DLL 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 *************************************************/ FLINT_DLL void _fmpq_poly_derivative(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len); FLINT_DLL void fmpq_poly_derivative(fmpq_poly_t res, const fmpq_poly_t poly); FLINT_DLL void _fmpq_poly_integral(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len); FLINT_DLL void fmpq_poly_integral(fmpq_poly_t res, const fmpq_poly_t poly); /* Square roots ************************************************************/ FLINT_DLL void _fmpq_poly_invsqrt_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong n); FLINT_DLL void fmpq_poly_invsqrt_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_sqrt_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, slong n); FLINT_DLL void fmpq_poly_sqrt_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); /* Power sums ****************************************************************/ FLINT_DLL void _fmpq_poly_power_sums(fmpz * res, fmpz_t rden, const fmpz * poly, slong len, slong n); FLINT_DLL void fmpq_poly_power_sums(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_power_sums_to_poly(fmpz * res, const fmpz * poly, const fmpz_t den, slong len); FLINT_DLL void fmpq_poly_power_sums_to_fmpz_poly(fmpz_poly_t res, const fmpq_poly_t Q); FLINT_DLL void fmpq_poly_power_sums_to_poly(fmpq_poly_t res, const fmpq_poly_t Q); /* Transcendental functions ************************************************/ FLINT_DLL void _fmpq_poly_log_series(fmpz * g, fmpz_t gden, const fmpz * f, const fmpz_t fden, slong flen, slong n); FLINT_DLL void fmpq_poly_log_series(fmpq_poly_t res, const fmpq_poly_t f, slong n); FLINT_DLL void _fmpq_poly_exp_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); FLINT_DLL void fmpq_poly_exp_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL 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); FLINT_DLL void fmpq_poly_exp_expinv_series(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_atan_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); FLINT_DLL void fmpq_poly_atan_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_atanh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); FLINT_DLL void fmpq_poly_atanh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_asin_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); FLINT_DLL void fmpq_poly_asin_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_asinh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); FLINT_DLL void fmpq_poly_asinh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_tan_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); FLINT_DLL void fmpq_poly_tan_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_sin_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); FLINT_DLL void fmpq_poly_sin_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_cos_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); FLINT_DLL void fmpq_poly_cos_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL 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); FLINT_DLL void fmpq_poly_sin_cos_series(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_sinh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); FLINT_DLL void fmpq_poly_sinh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_cosh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); FLINT_DLL void fmpq_poly_cosh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL 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); FLINT_DLL void fmpq_poly_sinh_cosh_series(fmpq_poly_t res1, fmpq_poly_t res2, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_tanh_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, slong hlen, slong n); FLINT_DLL void fmpq_poly_tanh_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); /* Orthogonal polynomials ***************************************************/ FLINT_DLL void _fmpq_poly_legendre_p(fmpz * coeffs, fmpz_t den, ulong n); FLINT_DLL void fmpq_poly_legendre_p(fmpq_poly_t poly, ulong n); FLINT_DLL void _fmpq_poly_laguerre_l(fmpz * coeffs, fmpz_t den, ulong n); FLINT_DLL void fmpq_poly_laguerre_l(fmpq_poly_t poly, ulong n); FLINT_DLL void _fmpq_poly_gegenbauer_c(fmpz * coeffs, fmpz_t den, ulong n, const fmpq_t a); FLINT_DLL void fmpq_poly_gegenbauer_c(fmpq_poly_t poly, ulong n, const fmpq_t a); /* Evaluation **************************************************************/ FLINT_DLL void _fmpq_poly_evaluate_fmpz(fmpz_t rnum, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len, const fmpz_t a); FLINT_DLL void fmpq_poly_evaluate_fmpz(fmpq_t res, const fmpq_poly_t poly, const fmpz_t a); FLINT_DLL 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); FLINT_DLL void fmpq_poly_evaluate_fmpq(fmpq_t res, const fmpq_poly_t poly, const fmpq_t a); FLINT_DLL void fmpq_poly_evaluate_mpz(mpq_t res, const fmpq_poly_t poly, const mpz_t a); FLINT_DLL void fmpq_poly_evaluate_mpq(mpq_t res, const fmpq_poly_t poly, const mpq_t a); /* Interpolation ************************************************************/ FLINT_DLL void _fmpq_poly_interpolate_fmpz_vec(fmpz * poly, fmpz_t den, const fmpz * xs, const fmpz * ys, slong n); FLINT_DLL void fmpq_poly_interpolate_fmpz_vec(fmpq_poly_t poly, const fmpz * xs, const fmpz * ys, slong n); /* Composition *************************************************************/ FLINT_DLL 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); FLINT_DLL void fmpq_poly_compose(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2); FLINT_DLL 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); FLINT_DLL void fmpq_poly_rescale(fmpq_poly_t res, const fmpq_poly_t poly, const fmpq_t x); /* Power series composition ************************************************/ FLINT_DLL 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); FLINT_DLL void fmpq_poly_compose_series_horner(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n); FLINT_DLL 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); FLINT_DLL void fmpq_poly_compose_series_brent_kung(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n); FLINT_DLL 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); FLINT_DLL void fmpq_poly_compose_series(fmpq_poly_t res, const fmpq_poly_t poly1, const fmpq_poly_t poly2, slong n); /* Power series reversion ************************************************/ FLINT_DLL void _fmpq_poly_revert_series_lagrange(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, slong n); FLINT_DLL void fmpq_poly_revert_series_lagrange(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_revert_series_lagrange_fast(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, slong n); FLINT_DLL void fmpq_poly_revert_series_lagrange_fast(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_revert_series_newton(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, slong n); FLINT_DLL void fmpq_poly_revert_series_newton(fmpq_poly_t res, const fmpq_poly_t poly, slong n); FLINT_DLL void _fmpq_poly_revert_series(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, slong len1, slong n); FLINT_DLL void fmpq_poly_revert_series(fmpq_poly_t res, const fmpq_poly_t poly, slong n); /* Gaussian content ********************************************************/ FLINT_DLL void _fmpq_poly_content(fmpq_t res, const fmpz * poly, const fmpz_t den, slong len); FLINT_DLL void fmpq_poly_content(fmpq_t res, const fmpq_poly_t poly); FLINT_DLL void _fmpq_poly_primitive_part(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len); FLINT_DLL void fmpq_poly_primitive_part(fmpq_poly_t res, const fmpq_poly_t poly); FLINT_DLL int _fmpq_poly_is_monic(const fmpz * poly, const fmpz_t den, slong len); FLINT_DLL int fmpq_poly_is_monic(const fmpq_poly_t poly); FLINT_DLL void _fmpq_poly_make_monic(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len); FLINT_DLL void fmpq_poly_make_monic(fmpq_poly_t res, const fmpq_poly_t poly); /* Square-free *************************************************************/ FLINT_DLL int fmpq_poly_is_squarefree(const fmpq_poly_t poly); /* Input and output *********************************************************/ FLINT_DLL int fmpq_poly_debug(const fmpq_poly_t poly); FLINT_DLL int _fmpq_poly_fprint(FILE * file, const fmpz * poly, const fmpz_t den, slong len); FLINT_DLL int fmpq_poly_fprint(FILE * file, const fmpq_poly_t poly); FLINT_DLL int _fmpq_poly_fprint_pretty(FILE * file, const fmpz *poly, const fmpz_t den, slong len, const char * x); FLINT_DLL int fmpq_poly_fprint_pretty(FILE * file, const fmpq_poly_t poly, const char * var); FMPQ_POLY_INLINE int _fmpq_poly_print(const fmpz * poly, const fmpz_t den, slong len) { return _fmpq_poly_fprint(stdout, poly, den, len); } FMPQ_POLY_INLINE int fmpq_poly_print(const fmpq_poly_t poly) { return fmpq_poly_fprint(stdout, poly); } FMPQ_POLY_INLINE 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); } FMPQ_POLY_INLINE int fmpq_poly_print_pretty(const fmpq_poly_t poly, const char * var) { return fmpq_poly_fprint_pretty(stdout, poly, var); } FLINT_DLL int fmpq_poly_fread(FILE * file, fmpq_poly_t poly); FMPQ_POLY_INLINE int fmpq_poly_read(fmpq_poly_t poly) { return fmpq_poly_fread(stdin, poly); } #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpq_poly/000077500000000000000000000000001414523752600147425ustar00rootroot00000000000000flint2-2.8.4/fmpq_poly/add.c000066400000000000000000000141201414523752600156340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } } flint2-2.8.4/fmpq_poly/add_series.c000066400000000000000000000154611414523752600172170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } flint2-2.8.4/fmpq_poly/asin_series.c000066400000000000000000000044371414523752600174220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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; hlen = FLINT_MIN(hlen, 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, n); _fmpq_poly_canonicalise(u, uden, n); _fmpz_vec_neg(u, u, n); fmpz_set(u, uden); /* u += 1 */ _fmpq_poly_invsqrt_series(t, tden, u, uden, n, 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_printf("Exception (fmpq_poly_asin_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/asinh_series.c000066400000000000000000000044111414523752600175620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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; hlen = FLINT_MIN(hlen, 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, n); _fmpq_poly_canonicalise(u, uden, n); fmpz_set(u, uden); /* u += 1 */ _fmpq_poly_invsqrt_series(t, tden, u, uden, n, 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_printf("Exception (fmpq_poly_asinh_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/atan_series.c000066400000000000000000000043141414523752600174050ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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; hlen = FLINT_MIN(hlen, 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, n); _fmpq_poly_canonicalise(u, uden, n); 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, n, 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_printf("Exception (fmpq_poly_atan_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/atanh_series.c000066400000000000000000000043561414523752600175630ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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; hlen = FLINT_MIN(hlen, 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, n); _fmpq_poly_canonicalise(u, uden, n); _fmpz_vec_neg(u, u, n); 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, n, 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_printf("Exception (fmpq_poly_atanh_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/canonicalise.c000066400000000000000000000024241414523752600175400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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); } flint2-2.8.4/fmpq_poly/clear.c000066400000000000000000000013721414523752600161770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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); } flint2-2.8.4/fmpq_poly/cmp.c000066400000000000000000000045241414523752600156720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } flint2-2.8.4/fmpq_poly/compose.c000066400000000000000000000056671414523752600165710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpq_poly/compose_series.c000066400000000000000000000056141414523752600201330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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_printf("Exception (fmpq_poly_compose_series). Inner polynomial \n" "must have zero constant term,\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpq_poly/compose_series_brent_kung.c000066400000000000000000000135711414523752600223520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "fmpq.h" #include "fmpq_mat.h" #include "ulong_extras.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_printf("Exception (fmpq_poly_compose_series_brent_kung). \n" "Inner polynomial must have zero constant term.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpq_poly/compose_series_horner.c000066400000000000000000000101661414523752600215060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf("Exception (fmpq_poly_compose_series_horner). Inner polynomial \n" "must have zero constant term.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpq_poly/content.c000066400000000000000000000014671414523752600165700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpq_poly/cos_series.c000066400000000000000000000054531414523752600172530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf("Exception (fmpq_poly_cos_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/cosh_series.c000066400000000000000000000030351414523752600174150ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf("Exception (fmpq_poly_cosh_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/debug.c000066400000000000000000000015101414523752600161710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" 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; } flint2-2.8.4/fmpq_poly/derivative.c000066400000000000000000000020701414523752600172470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } flint2-2.8.4/fmpq_poly/div.c000066400000000000000000000057521414523752600157010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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_printf("Exception (fmpq_poly_div). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/div_series.c000066400000000000000000000033361414523752600172470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpq_poly_div_series). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/divides.c000066400000000000000000000055741414523752600165500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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; } flint2-2.8.4/fmpq_poly/divrem.c000066400000000000000000000111761414523752600164020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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_printf("Exception (fmpq_poly_divrem). Division by zero.\n"); flint_abort(); } if (Q == R) { flint_printf("Exception (fmpq_poly_divrem). Output arguments aliased.\n"); flint_abort(); } /* 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); } flint2-2.8.4/fmpq_poly/equal.c000066400000000000000000000013311414523752600162130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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)); } flint2-2.8.4/fmpq_poly/equal_trunc.c000066400000000000000000000043311414523752600174310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpq_poly/evaluate_fmpq.c000066400000000000000000000027111414523752600177400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "fmpq.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); } } flint2-2.8.4/fmpq_poly/evaluate_fmpz.c000066400000000000000000000022221414523752600177460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" 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); } flint2-2.8.4/fmpq_poly/evaluate_mpq.c000066400000000000000000000014541414523752600175750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "fmpq.h" void fmpq_poly_evaluate_mpq(mpq_t res, const fmpq_poly_t poly, const mpq_t a) { fmpq_t r, b; fmpq_init(r); fmpq_init(b); fmpq_set_mpq(b, a); fmpq_poly_evaluate_fmpq(r, poly, b); fmpq_get_mpq(res, r); fmpq_clear(r); fmpq_clear(b); } flint2-2.8.4/fmpq_poly/evaluate_mpz.c000066400000000000000000000014741414523752600176100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "fmpq.h" void fmpq_poly_evaluate_mpz(mpq_t res, const fmpq_poly_t poly, const mpz_t a) { fmpq_t r; fmpz_t b; fmpq_init(r); fmpz_init(b); fmpz_set_mpz(b, a); fmpq_poly_evaluate_fmpz(r, poly, b); fmpq_get_mpq(res, r); fmpq_clear(r); fmpz_clear(b); } flint2-2.8.4/fmpq_poly/exp_series.c000066400000000000000000000344341414523752600172640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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 j, 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++) { fmpz_mul(t, Aprime, B + k - 1); for (j = 2; j < FLINT_MIN(Alen, k + 1); j++) fmpz_addmul(t, Aprime + j - 1, B + k - j); 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_abort(); 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_printf("Exception (fmpq_poly_exp_series). Constant term != 0.\n"); flint_abort(); } 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_printf("Exception (fmpq_poly_exp_expinv_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/fit_length.c000066400000000000000000000014061414523752600172320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #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); } } flint2-2.8.4/fmpq_poly/fprint.c000066400000000000000000000040751414523752600164160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" /* 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_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, "%li", 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; } int fmpq_poly_fprint(FILE * file, const fmpq_poly_t poly) { return _fmpq_poly_fprint(file, poly->coeffs, poly->den, poly->length); } flint2-2.8.4/fmpq_poly/fprint_pretty.c000066400000000000000000000105251414523752600200220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpq_poly.h" /* 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_pretty(FILE * file, const fmpq_poly_t poly, const char * var) { return _fmpq_poly_fprint_pretty(file, poly->coeffs, poly->den, poly->length, var); } flint2-2.8.4/fmpq_poly/fread.c000066400000000000000000000024101414523752600161640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" 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_printf("Exception (fmpz_poly_fread). Length does not fit into a slong.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpq_poly/gcd.c000066400000000000000000000066261414523752600156550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } } flint2-2.8.4/fmpq_poly/gegenbauer_c.c000066400000000000000000000043461414523752600175230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_poly/get_coeff_fmpq.c000066400000000000000000000015321414523752600200530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #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); } flint2-2.8.4/fmpq_poly/get_coeff_fmpz.c000066400000000000000000000013661414523752600200710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpq_poly.h" 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); } flint2-2.8.4/fmpq_poly/get_coeff_mpq.c000066400000000000000000000015301414523752600177030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" void fmpq_poly_get_coeff_mpq(mpq_t x, const fmpq_poly_t poly, slong n) { if (n >= poly->length) /* Coefficient is beyond the end of poly */ { flint_mpq_set_si(x, 0, 1); return; } fmpz_get_mpz(mpq_numref(x), poly->coeffs + n); fmpz_get_mpz(mpq_denref(x), poly->den); mpq_canonicalize(x); } flint2-2.8.4/fmpq_poly/get_nmod_poly.c000066400000000000000000000025121414523752600177450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" #include "nmod_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 { slong i; nmod_poly_fit_length(rop, len); for (i = 0; i < len; i++) rop->coeffs[i] = fmpz_fdiv_ui(op->coeffs + i, rop->mod.n); _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_fdiv_ui(op->den, rop->mod.n), 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); } flint2-2.8.4/fmpq_poly/get_slice.c000066400000000000000000000023421414523752600170450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpq_poly/get_str.c000066400000000000000000000035541414523752600165640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include "flint.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, "%li", 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; } flint2-2.8.4/fmpq_poly/get_str_pretty.c000066400000000000000000000131371414523752600201710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" 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, "%li", 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, "%li", 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); } flint2-2.8.4/fmpq_poly/init.c000066400000000000000000000017141414523752600160540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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; } flint2-2.8.4/fmpq_poly/inlines.c000066400000000000000000000011371414523752600165510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPQ_POLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpq_poly.h" flint2-2.8.4/fmpq_poly/integral.c000066400000000000000000000070041414523752600167140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } flint2-2.8.4/fmpq_poly/interpolate_fmpz_vec.c000066400000000000000000000046141414523752600213320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpq_poly/inv.c000066400000000000000000000024611414523752600157050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpq_poly_inv). poly2 is not invertible.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpq_poly/inv_series_newton.c000066400000000000000000000072011414523752600206460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #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_printf("Exception (fmpq_poly_inv_series_newton). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/invsqrt_series.c000066400000000000000000000046761414523752600202030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.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_printf("Exception (fmpq_poly_invsqrt_series). Constant term != 1.\n"); flint_abort(); } 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? */ } flint2-2.8.4/fmpq_poly/is_canonical.c000066400000000000000000000021411414523752600175260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } flint2-2.8.4/fmpq_poly/is_monic.c000066400000000000000000000013521414523752600167070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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); } flint2-2.8.4/fmpq_poly/is_squarefree.c000066400000000000000000000011671414523752600177500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #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); } flint2-2.8.4/fmpq_poly/laguerre_l.c000066400000000000000000000024101414523752600172240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_poly/lcm.c000066400000000000000000000064421414523752600156670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpq_poly/legendre_p.c000066400000000000000000000032511414523752600172130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_poly/log_series.c000066400000000000000000000034671414523752600172530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf("Exception (fmpq_poly_log_series). Constant term != 1.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/make_monic.c000066400000000000000000000020251414523752600172070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpq_poly/mul.c000066400000000000000000000054061414523752600157100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpq_poly/mullow.c000066400000000000000000000035631414523752600164340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } flint2-2.8.4/fmpq_poly/neg.c000066400000000000000000000015761414523752600156700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpq_poly/normalise.c000066400000000000000000000012201414523752600170720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #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; } flint2-2.8.4/fmpq_poly/pow.c000066400000000000000000000026571414523752600157250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpq_poly/pow_trunc.c000066400000000000000000000112461414523752600171320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } } flint2-2.8.4/fmpq_poly/power_sums.c000066400000000000000000000072531414523752600173200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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_ui(res + k, poly + len - 1 - k, k); fmpz_mul(res + k, res + k, rden); for (i = 1; i < k - 1; i++) fmpz_mul(res + i, res + i, poly + len - 1); for (i = 1; i < k; i++) fmpz_addmul(res + k, poly + len - 1 - k + i, res + i); fmpz_neg(res + k, res + k); fmpz_mul(rden, rden, poly + len - 1); } for (k = len; k < n; k++) { fmpz_zero(res + k); for (i = k - len + 1; i < k - 1; i++) fmpz_mul(res + i, res + i, poly + len - 1); for (i = k - len + 1; i < k; i++) fmpz_addmul(res + k, poly + len - 1 - k + i, res + i); fmpz_neg(res + k, res + k); } for (i = n - len + 1; i < n - 1; i++) fmpz_mul(res + i, res + i, 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_printf ("Exception (fmpq_poly_power_sums_naive). Zero polynomial.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/power_sums_to_poly.c000066400000000000000000000061751414523752600210670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpq.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); else fmpz_zero(res + d - k); for (i = 1; i < FLINT_MIN(k, len); i++) fmpz_addmul(res + d - k, res + d - k + i, poly + i); 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); } } flint2-2.8.4/fmpq_poly/powers_clear.c000066400000000000000000000014131414523752600175720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #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); } flint2-2.8.4/fmpq_poly/powers_precompute.c000066400000000000000000000037741414523752600207030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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_printf("Exception (fmpz_poly_powers_precompute). Division by zero.\n"); flint_abort(); } pinv->powers = _fmpq_poly_powers_precompute(fmpq_poly_numref(poly), fmpq_poly_denref(poly), poly->length); pinv->len = poly->length; } flint2-2.8.4/fmpq_poly/primitive_part.c000066400000000000000000000021211414523752600201400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpq_poly/randtest.c000066400000000000000000000053211414523752600167330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" #include "ulong_extras.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_printf("Exception (fmpq_poly_randtest_not_zeo). bits == 0.\n"); flint_abort(); } fmpq_poly_randtest(f, state, len, bits); if (f->length == 0) fmpq_poly_set_ui(f, 1); } flint2-2.8.4/fmpq_poly/realloc.c000066400000000000000000000026101414523752600165260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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; } flint2-2.8.4/fmpq_poly/rem.c000066400000000000000000000060431414523752600156740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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_printf("Exception (fmpq_poly_rem). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/rem_powers_precomp.c000066400000000000000000000051531414523752600210210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } flint2-2.8.4/fmpq_poly/remove.c000066400000000000000000000051731414523752600164110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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_printf("Exception (fmpq_poly_remove). Division by zero.\n"); flint_abort(); } if (len2 == 1) { flint_printf("Exception (fmpq_poly_remove). Divisor must not be a unit.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpq_poly/rescale.c000066400000000000000000000036371414523752600165350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.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); } } flint2-2.8.4/fmpq_poly/resultant.c000066400000000000000000000112241414523752600171270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } } } flint2-2.8.4/fmpq_poly/resultant_modular_div.c000066400000000000000000000112051414523752600215130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } } } flint2-2.8.4/fmpq_poly/reverse.c000066400000000000000000000015621414523752600165650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } flint2-2.8.4/fmpq_poly/revert_series.c000066400000000000000000000035031414523752600177700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf("Exception (fmpq_poly_revert_series). Input must have \n" "zero constant term and nonzero coefficient of x^1.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/revert_series_lagrange.c000066400000000000000000000070771414523752600216420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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_printf("Exception (fmpq_poly_revert_series_lagrange). Input must have \n" "zero constant term and nonzero coefficient of x^1.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/revert_series_lagrange_fast.c000066400000000000000000000106221414523752600226450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "ulong_extras.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, k, m; fmpz *R, *Rden, *S, *T, *dens, *tmp; fmpz_t Sden, Tden, t; 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); fmpz_init(t); 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_mul(t, S + 0, Ri(j) + i + j - 1); for (k = 1; k <= i + j - 1; k++) fmpz_addmul(t, S + k, Ri(j) + i + j - 1 - k); fmpz_set(Qinv + i + j, t); 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_clear(t); _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_printf("Exception (fmpq_poly_revert_series_lagrange_fast). Input must \n" "have zero constant term and nonzero coefficient of x^1.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/revert_series_newton.c000066400000000000000000000063111414523752600213620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #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_printf("Exception (fmpq_poly_revert_series_newton). Input must have \n" "zero constant term and nonzero coefficient of x^1.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/scalar_div_fmpq.c000066400000000000000000000060021414523752600202360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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_printf("Exception (fmpq_poly_scalar_div_fmpq). Division by zero.\n"); flint_abort(); } 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)); } } flint2-2.8.4/fmpq_poly/scalar_div_fmpz.c000066400000000000000000000034351414523752600202560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" 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_printf("Exception (fmpq_poly_scalar_div_fmpz). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/scalar_div_mpq.c000066400000000000000000000013131414523752600200700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void fmpq_poly_scalar_div_mpq(fmpq_poly_t rop, const fmpq_poly_t op, const mpq_t c) { fmpq_t f; fmpq_init_set_readonly(f, c); fmpq_poly_scalar_div_fmpq(rop, op, f); fmpq_clear_readonly(f); } flint2-2.8.4/fmpq_poly/scalar_div_mpz.c000066400000000000000000000013131414523752600201010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void fmpq_poly_scalar_div_mpz(fmpq_poly_t rop, const fmpq_poly_t op, const mpz_t c) { fmpz_t f; fmpz_init_set_readonly(f, c); fmpq_poly_scalar_div_fmpz(rop, op, f); fmpz_clear_readonly(f); } flint2-2.8.4/fmpq_poly/scalar_div_si.c000066400000000000000000000037751414523752600177240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" 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_printf("Exception (fmpq_poly_scalar_div_si). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/scalar_div_ui.c000066400000000000000000000033211414523752600177110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" 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_printf("Exception (fmpq_poly_scalar_div_ui). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/scalar_mul_fmpq.c000066400000000000000000000056461414523752600202660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" 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)); } } flint2-2.8.4/fmpq_poly/scalar_mul_fmpz.c000066400000000000000000000032521414523752600202660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" 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); } flint2-2.8.4/fmpq_poly/scalar_mul_mpq.c000066400000000000000000000012671414523752600201130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void fmpq_poly_scalar_mul_mpq(fmpq_poly_t rop, const fmpq_poly_t op, const mpq_t c) { fmpq_t f; fmpq_init_set_readonly(f, c); fmpq_poly_scalar_mul_fmpq(rop, op, f); fmpq_clear_readonly(f); } flint2-2.8.4/fmpq_poly/scalar_mul_mpz.c000066400000000000000000000012701414523752600201160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void fmpq_poly_scalar_mul_mpz(fmpq_poly_t rop, const fmpq_poly_t op, const mpz_t c) { fmpz_t f; fmpz_init_set_readonly(f, c); fmpq_poly_scalar_mul_fmpz(rop, op, f); fmpz_clear_readonly(f); } flint2-2.8.4/fmpq_poly/scalar_mul_si.c000066400000000000000000000034531414523752600177300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" 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); } flint2-2.8.4/fmpq_poly/scalar_mul_ui.c000066400000000000000000000031071414523752600177260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" 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); } flint2-2.8.4/fmpq_poly/set.c000066400000000000000000000015611414523752600157040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } } flint2-2.8.4/fmpq_poly/set_array_mpq.c000066400000000000000000000025171414523752600177610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" 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); } 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); } } flint2-2.8.4/fmpq_poly/set_coeff_fmpq.c000066400000000000000000000043511414523752600200710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_vec.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); } } flint2-2.8.4/fmpq_poly/set_coeff_fmpz.c000066400000000000000000000023171414523752600201020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" 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); } } flint2-2.8.4/fmpq_poly/set_coeff_mpq.c000066400000000000000000000013421414523752600177200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" void fmpq_poly_set_coeff_mpq(fmpq_poly_t poly, slong n, const mpq_t x) { fmpq_t f; fmpq_init_set_readonly(f, x); fmpq_poly_set_coeff_fmpq(poly, n, f); fmpq_clear_readonly(f); } flint2-2.8.4/fmpq_poly/set_coeff_mpz.c000066400000000000000000000013131414523752600177270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" void fmpq_poly_set_coeff_mpz(fmpq_poly_t poly, slong n, const mpz_t x) { fmpz_t f; fmpz_init_set_readonly(f, x); fmpq_poly_set_coeff_fmpz(poly, n, f); fmpz_clear_readonly(f); } flint2-2.8.4/fmpq_poly/set_coeff_si.c000066400000000000000000000023141414523752600175360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" 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); } } flint2-2.8.4/fmpq_poly/set_coeff_ui.c000066400000000000000000000023151414523752600175410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" 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); } } flint2-2.8.4/fmpq_poly/set_fmpq.c000066400000000000000000000013131414523752600167220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" 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); } flint2-2.8.4/fmpq_poly/set_fmpz.c000066400000000000000000000012561414523752600167410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" 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); } flint2-2.8.4/fmpq_poly/set_fmpz_poly.c000066400000000000000000000015311414523752600200000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" 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); } } flint2-2.8.4/fmpq_poly/set_length.c000066400000000000000000000012471414523752600172460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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; } flint2-2.8.4/fmpq_poly/set_mpq.c000066400000000000000000000013171414523752600165600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" void fmpq_poly_set_mpq(fmpq_poly_t poly, const mpq_t x) { fmpq_poly_fit_length(poly, 1); fmpz_set_mpz(poly->coeffs, mpq_numref(x)); fmpz_set_mpz(poly->den, mpq_denref(x)); _fmpq_poly_set_length(poly, 1); _fmpq_poly_normalise(poly); } flint2-2.8.4/fmpq_poly/set_mpz.c000066400000000000000000000012601414523752600165660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" void fmpq_poly_set_mpz(fmpq_poly_t poly, const mpz_t x) { fmpq_poly_fit_length(poly, 1); fmpz_set_mpz(poly->coeffs, x); fmpz_one(poly->den); _fmpq_poly_set_length(poly, 1); _fmpq_poly_normalise(poly); } flint2-2.8.4/fmpq_poly/set_nmod_poly.c000066400000000000000000000016271414523752600177670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "nmod_poly.h" 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); } } flint2-2.8.4/fmpq_poly/set_si.c000066400000000000000000000012501414523752600163720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" 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); } flint2-2.8.4/fmpq_poly/set_str.c000066400000000000000000000060111414523752600165670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpq_poly.h" 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; } flint2-2.8.4/fmpq_poly/set_trunc.c000066400000000000000000000017471414523752600171250ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } } flint2-2.8.4/fmpq_poly/set_ui.c000066400000000000000000000012501414523752600163740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" 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); } flint2-2.8.4/fmpq_poly/shift_left.c000066400000000000000000000016651414523752600172450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpq_poly/shift_right.c000066400000000000000000000017241414523752600174240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpq_poly/sin_cos_series.c000066400000000000000000000111011414523752600201070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); 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_printf("Exception (fmpq_poly_sin_cos_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/sin_series.c000066400000000000000000000053271414523752600172600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf("Exception (fmpq_poly_sin_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/sinh_cosh_series.c000066400000000000000000000035061414523752600204410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpq_poly_sinh_cosh_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/sinh_series.c000066400000000000000000000027511414523752600174260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf("Exception (fmpq_poly_sinh_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/sqrt_series.c000066400000000000000000000034011414523752600174470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpq_poly_sqrt_series). Constant term != 1.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/sub.c000066400000000000000000000175561414523752600157150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } } flint2-2.8.4/fmpq_poly/sub_series.c000066400000000000000000000137051414523752600172570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } flint2-2.8.4/fmpq_poly/swap.c000066400000000000000000000016441414523752600160650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" void fmpq_poly_swap(fmpq_poly_t poly1, fmpq_poly_t poly2) { slong t; fmpz * tptr; t = poly1->length; poly1->length = poly2->length; poly2->length = t; t = poly1->alloc; poly1->alloc = poly2->alloc; poly2->alloc = t; tptr = poly1->coeffs; poly1->coeffs = poly2->coeffs; poly2->coeffs = tptr; fmpz_swap(poly1->den, poly2->den); } flint2-2.8.4/fmpq_poly/tan_series.c000066400000000000000000000054521414523752600172500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf("Exception (fmpq_poly_tan_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/tanh_series.c000066400000000000000000000041641414523752600174170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf("Exception (fmpq_poly_tanh_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpq_poly/test/000077500000000000000000000000001414523752600157215ustar00rootroot00000000000000flint2-2.8.4/fmpq_poly/test/t-add.c000066400000000000000000000077031414523752600170650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); fmpq_poly_clear(e); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-add_series.c000066400000000000000000000102001414523752600204210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("add_series...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(d); fmpq_poly_clear(e); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-add_sub_fmpq.c000066400000000000000000000046331414523752600207600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpq_poly.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("add_sub_fmpq...."); fflush(stdout); 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"); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(s); fmpq_poly_clear(t); fmpq_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-add_sub_fmpz.c000066400000000000000000000046331414523752600207710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpq_poly.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("add_sub_fmpz...."); fflush(stdout); 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"); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(s); fmpq_poly_clear(t); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-add_sub_si.c000066400000000000000000000045131414523752600204250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpq_poly.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("add_sub_si...."); fflush(stdout); 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"); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(s); fmpq_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-asin_series.c000066400000000000000000000063611414523752600206400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("asin_series...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(asinA); fmpq_poly_clear(atanB); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-asinh_series.c000066400000000000000000000063541414523752600210120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("asinh_series...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(asinhA); fmpq_poly_clear(atanhB); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-atan_series.c000066400000000000000000000066261414523752600206350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("atan_series...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(atanA); fmpq_poly_clear(atanB); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-atanh_series.c000066400000000000000000000066271414523752600210060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("atanh_series...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(A); fmpq_poly_clear(B); fmpq_poly_clear(atanhA); fmpq_poly_clear(atanhB); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-cmp.c000066400000000000000000000055461414523752600171170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cmp...."); fflush(stdout); /* 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"); 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"); 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)); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-compose.c000066400000000000000000000101521414523752600177720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("compose...."); fflush(stdout); /* 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); 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); 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; mpq_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); mpq_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_mpq(c, g, k); fmpq_poly_scalar_mul_mpq(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"); 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); mpq_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-compose_series.c000066400000000000000000000074021414523752600213500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_series...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); fmpq_poly_clear(s); fmpq_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-compose_series_brent_kung.c000066400000000000000000000075041414523752600235710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_series_brent_kung...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); fmpq_poly_clear(s); fmpq_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-compose_series_horner.c000066400000000000000000000074541414523752600227340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_series_horner...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); fmpq_poly_clear(s); fmpq_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-content.c000066400000000000000000000035211414523752600200010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("content...."); fflush(stdout); /* 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"); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_clear(a); fmpq_clear(b); fmpq_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-cos_series.c000066400000000000000000000063471414523752600204760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("cos_series...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-cosh_series.c000066400000000000000000000064001414523752600206340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("cosh_series...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-derivative.c000066400000000000000000000070301414523752600204700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("derivative...."); fflush(stdout); /* 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-div.c000066400000000000000000000102011414523752600171020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("div...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); fmpq_poly_clear(q2); fmpq_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-div_series.c000066400000000000000000000106461414523752600204710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("div_series...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(p); fmpq_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-divides.c000066400000000000000000000110001414523752600177450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result, d1, d2; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("divides...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); fmpq_poly_clear(q2); fmpq_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-divrem.c000066400000000000000000000117271414523752600176240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("divrem...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); fmpq_poly_clear(r); fmpq_poly_clear(rhs); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-equal_trunc.c000066400000000000000000000064041414523752600206540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("equal_trunc...."); fflush(stdout); /* 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); 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); abort(); } fmpq_clear(c); fmpq_poly_clear(a); fmpq_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-evaluate_fmpq.c000066400000000000000000000103321414523752600211560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_fmpq...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpq_poly_clear(f); fmpq_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-evaluate_fmpz.c000066400000000000000000000061001414523752600211650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_fmpz...."); fflush(stdout); /* 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"); 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"); abort(); } fmpq_clear(x); fmpq_clear(y); fmpz_clear(a); fmpq_poly_clear(f); fmpq_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-evaluate_mpq.c000066400000000000000000000103101414523752600210040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_mpq...."); fflush(stdout); /* Check aliasing */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b; mpq_t x, y; fmpq_poly_t f; fmpz_init(a); fmpz_init(b); mpq_init(x); mpq_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_get_mpz(mpq_numref(x), a); fmpz_get_mpz(mpq_denref(x), b); mpq_canonicalize(x); fmpq_poly_evaluate_mpq(y, f, x); fmpq_poly_evaluate_mpq(x, f, x); result = (mpq_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"); abort(); } fmpz_clear(a); fmpz_clear(b); mpq_clear(x); mpq_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; mpq_t x, y, z; fmpq_poly_t f, g; fmpz_init(a); fmpz_init(b); mpq_init(x); mpq_init(y); mpq_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_get_mpz(mpq_numref(x), a); fmpz_get_mpz(mpq_denref(x), b); mpq_canonicalize(x); fmpq_poly_evaluate_mpq(y, f, x); fmpq_poly_evaluate_mpq(z, g, x); mpq_add(y, y, z); fmpq_poly_add(f, f, g); fmpq_poly_evaluate_mpq(z, f, x); result = (mpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); abort(); } fmpz_clear(a); fmpz_clear(b); mpq_clear(x); mpq_clear(y); mpq_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; mpq_t x, y, z; fmpq_poly_t f, g; fmpz_init(a); fmpz_init(b); mpq_init(x); mpq_init(y); mpq_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_get_mpz(mpq_numref(x), a); fmpz_get_mpz(mpq_denref(x), b); mpq_canonicalize(x); fmpq_poly_evaluate_mpq(y, f, x); fmpq_poly_evaluate_mpq(z, g, x); mpq_mul(y, y, z); fmpq_poly_mul(f, f, g); fmpq_poly_evaluate_mpq(z, f, x); result = (mpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); abort(); } fmpz_clear(a); fmpz_clear(b); mpq_clear(x); mpq_clear(y); mpq_clear(z); fmpq_poly_clear(f); fmpq_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-evaluate_mpz.c000066400000000000000000000061171414523752600210270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_mpz...."); fflush(stdout); /* Check that (f+g)(a) = f(a) + g(a) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a; fmpq_t x; mpz_t b; mpq_t y, z; fmpq_poly_t f, g; fmpz_init(a); fmpq_init(x); mpz_init(b); mpq_init(y); mpq_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_get_mpz(b, a); fmpq_poly_evaluate_mpz(y, f, b); fmpq_poly_evaluate_mpz(z, g, b); mpq_add(y, y, z); fmpq_poly_add(f, f, g); fmpq_poly_evaluate_mpz(z, f, b); result = (mpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); gmp_printf("y = %Qd\n\n", y); gmp_printf("z = %Qd\n\n", z); abort(); } fmpz_clear(a); fmpq_clear(x); mpz_clear(b); mpq_clear(y); mpq_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; fmpq_t x; mpz_t b; mpq_t y, z; fmpq_poly_t f, g; fmpz_init(a); fmpq_init(x); mpz_init(b); mpq_init(y); mpq_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_get_mpz(b, a); fmpq_poly_evaluate_mpz(y, f, b); fmpq_poly_evaluate_mpz(z, g, b); mpq_mul(y, y, z); fmpq_poly_mul(f, f, g); fmpq_poly_evaluate_mpz(z, f, b); result = (mpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); gmp_printf("y = %Qd\n\n", y); gmp_printf("z = %Qd\n\n", z); abort(); } fmpz_clear(a); fmpq_clear(x); mpz_clear(b); mpq_clear(y); mpq_clear(z); fmpq_poly_clear(f); fmpq_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-exp_expinv_series.c000066400000000000000000000040371414523752600220710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("exp_expinv_series...."); fflush(stdout); 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"); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-exp_series.c000066400000000000000000000122471414523752600205020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("exp_series...."); fflush(stdout); /* 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); 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); 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"); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(expa); nmod_poly_clear(pa); nmod_poly_clear(pexpa); nmod_poly_clear(pexpa2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-gcd.c000066400000000000000000000167411414523752600170740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int cflags = 0, i, result; FLINT_TEST_INIT(state); flint_printf("gcd...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-gegenbauer_c.c000066400000000000000000000051461414523752600207420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_poly.h" #include "fmpq_vec.h" #define NRATS 20 int main() { fmpq_poly_t T0, T1, T2, t, tt; fmpq_t a, rat; fmpq *rats; slong n, d; flint_rand_t rand_state; FLINT_TEST_INIT(state); flint_printf("gegenbauer_c...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-get_nmod_poly.c000066400000000000000000000047231414523752600211730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("get/set_nmod_poly...."); fflush(stdout); 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"); 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"); abort(); } fmpq_poly_clear(A); nmod_poly_clear(M); nmod_poly_clear(M2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-get_set_coeff_fmpq.c000066400000000000000000000040131414523752600221430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, j, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("get/set_coeff_fmpq...."); fflush(stdout); 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"); abort(); } } fmpq_clear(x); fmpq_clear(y); fmpq_poly_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpq_poly/test/t-get_set_coeff_fmpz.c000066400000000000000000000042001414523752600221520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, j, result; ulong cflags = UWORD(0); mpq_t n1, n2; FLINT_TEST_INIT(state); flint_printf("get/set_coeff_fmpz...."); fflush(stdout); mpq_init(n1); mpq_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_get_mpz(mpq_numref(n1), x1); flint_mpz_set_si(mpq_denref(n1), 1); coeff = (slong) n_randint(state, len); fmpq_poly_set_coeff_fmpz(a, coeff, x1); fmpq_poly_get_coeff_mpq(n2, a, coeff); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; result = (mpq_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); gmp_printf("n1 = %Qd\n\n", n1); gmp_printf("n2 = %Qd\n\n", n2); abort(); } } fmpz_clear(x1); fmpz_clear(x2); fmpq_poly_clear(a); } mpq_clear(n1); mpq_clear(n2); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-get_set_coeff_mpq.c000066400000000000000000000043441414523752600220040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, j, result; ulong cflags = UWORD(0); mpq_t n1, n2; FLINT_TEST_INIT(state); flint_printf("get/set_coeff_mpq...."); fflush(stdout); mpq_init(n1); mpq_init(n2); for (i = 0; i < 50 * flint_test_multiplier(); i++) { fmpq_poly_t a; fmpz_t xnum, xden; slong coeff, len; fmpq_poly_init(a); fmpz_init(xnum); fmpz_init(xden); len = (slong) (n_randint(state, 100) + 1); for (j = 0; j < 50; j++) { fmpz_randtest(xnum, state, 200); fmpz_randtest_not_zero(xden, state, 200); fmpz_get_mpz(mpq_numref(n1), xnum); fmpz_get_mpz(mpq_denref(n1), xden); mpq_canonicalize(n1); coeff = (slong) n_randint(state, len); fmpq_poly_set_coeff_mpq(a, coeff, n1); fmpq_poly_get_coeff_mpq(n2, a, coeff); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; result = (mpq_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); gmp_printf("n1 = %Qd\n\n", n1); gmp_printf("n2 = %Qd\n\n", n2); abort(); } } fmpz_clear(xnum); fmpz_clear(xden); fmpq_poly_clear(a); } mpq_clear(n1); mpq_clear(n2); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-get_set_coeff_mpz.c000066400000000000000000000041031414523752600220060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, j, result; ulong cflags = UWORD(0); mpq_t n1, n2; FLINT_TEST_INIT(state); flint_printf("get/set_coeff_mpz...."); fflush(stdout); mpq_init(n1); mpq_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_get_mpz(mpq_numref(n1), x1); flint_mpz_set_si(mpq_denref(n1), 1); coeff = (slong) n_randint(state, len); fmpq_poly_set_coeff_mpz(a, coeff, mpq_numref(n1)); fmpq_poly_get_coeff_mpq(n2, a, coeff); result = (mpq_equal(n1, n2)); 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); gmp_printf("n1 = %Qd\n\n", n1); gmp_printf("n2 = %Qd\n\n", n2); abort(); } } fmpz_clear(x1); fmpz_clear(x2); fmpq_poly_clear(a); } mpq_clear(n1); mpq_clear(n2); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-get_set_coeff_si.c000066400000000000000000000037761414523752600216320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, j, result; ulong cflags = UWORD(0); slong n; mpq_t n_mpq; FLINT_TEST_INIT(state); flint_printf("get/set_coeff_si...."); fflush(stdout); mpq_init(n_mpq); 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_mpq(n_mpq, a, coeff); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; result = (flint_mpz_cmp_ui(mpq_denref(n_mpq), 1) == 0 && flint_mpz_cmp_si(mpq_numref(n_mpq), 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); gmp_printf("n_mpq = %Qd\n", n_mpq); abort(); } } fmpq_poly_clear(a); } mpq_clear(n_mpq); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-get_set_coeff_ui.c000066400000000000000000000040321414523752600216160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, j, result; ulong cflags = UWORD(0); ulong n; mpq_t n_mpq; FLINT_TEST_INIT(state); flint_printf("get/set_coeff_ui...."); fflush(stdout); mpq_init(n_mpq); 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_mpq(n_mpq, a, coeff); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; result = (flint_mpz_cmp_ui(mpq_denref(n_mpq), 1) == 0 && flint_mpz_cmp_ui(mpq_numref(n_mpq), 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); gmp_printf("n_mpq = %Qd\n", n_mpq); abort(); } } fmpq_poly_clear(a); } mpq_clear(n_mpq); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-get_set_str.c000066400000000000000000000051371414523752600206560ustar00rootroot00000000000000/* Copyright (C) 2018 Vincent Delecroix 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.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"); flint_abort(); } fmpq_poly_clear(p); } int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("get_set_str...."); fflush(stdout); /* 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); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); flint_free(str); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-get_slice.c000066400000000000000000000076251414523752600202760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("get_slice...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-init_realloc_clear.c000066400000000000000000000025351414523752600221450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/init2/realloc/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-integral.c000066400000000000000000000035731414523752600201430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("integral...."); fflush(stdout); /* 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-interpolate_fmpz_vec.c000066400000000000000000000037761414523752600225620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("interpolate_fmpz_vec...."); fflush(stdout); 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"); abort(); } } fmpq_clear(q); fmpq_poly_clear(P); _fmpz_vec_clear(x, n); _fmpz_vec_clear(y, n); _fmpz_vec_clear(z, n); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-inv.c000066400000000000000000000031551414523752600171260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("inv...."); fflush(stdout); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-inv_series_newton.c000066400000000000000000000057761414523752600221050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("inv_series_newton...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(one); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-invsqrt_series.c000066400000000000000000000055741414523752600214210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("invsqrt_series...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-is_squarefree.c000066400000000000000000000056401414523752600211700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_squarefree...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(f); fmpz_clear(N); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-laguerre_l.c000066400000000000000000000032701414523752600204510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_poly.h" int main() { fmpq_poly_t T0, T1, T2, t, tt; slong n; FLINT_TEST_INIT(state); flint_printf("laguerre_l...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-lcm.c000066400000000000000000000164261414523752600171120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int cflags = 0, i, result; FLINT_TEST_INIT(state); flint_printf("lcm...."); fflush(stdout); /* 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); 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); 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); 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"); 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); 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"); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lcm); fmpq_poly_clear(gcd); fmpq_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-legendre_p.c000066400000000000000000000033231414523752600204330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "profiler.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_poly.h" int main() { fmpq_poly_t Pn, Pn1, Pn2, R; slong n; FLINT_TEST_INIT(state); flint_printf("legendre_polynomial...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-log_series.c000066400000000000000000000071761414523752600204740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("log_series...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-make_monic.c000066400000000000000000000043061414523752600204330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("make_monic/is_monic...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-mul.c000066400000000000000000000074051414523752600171310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a1); fmpq_poly_clear(a2); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-mullow.c000066400000000000000000000033701414523752600176500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("mullow...."); fflush(stdout); /* 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-neg.c000066400000000000000000000031701414523752600171000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("neg...."); fflush(stdout); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-pow.c000066400000000000000000000056131414523752600171400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("pow...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-pow_trunc.c000066400000000000000000000063331414523752600203530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("pow_trunc...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-power_sums.c000066400000000000000000000141761414523752600205420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_poly.h" #include "fmpq_poly.h" int main(void) { 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; FLINT_TEST_INIT(state); flint_printf("power_sums...."); /* 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); 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"); 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"); 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"); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); fmpq_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-primitive_part.c000066400000000000000000000055611414523752600213730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("primitive_part...."); fflush(stdout); /* 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); 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); abort(); } fmpq_clear(x); fmpq_clear(y); fmpq_poly_clear(f); fmpq_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-print_read.c000066400000000000000000000142031414523752600204550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ #undef __STRICT_ANSI__ #endif #include #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) #include #endif #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) int main(void) { int i, j, n = 1000, result; FILE *in, *out; int fd[2]; pid_t childpid; FLINT_TEST_INIT(state); flint_printf("print/ read...."); fflush(stdout); /* 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"); abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); 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"); 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"); 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"); 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"); 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"); abort(); } ++i; } fmpq_poly_clear(t); fclose(in); } if (i != n) { flint_printf("FAIL:\n"); flint_printf("Only %d out of %d objects were processed.\n", i, n); 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"); abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); 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"); abort(); } r = flint_fprintf(out, "blah"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); 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"); 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); abort(); } ++i; } fmpq_poly_clear(t); fclose(in); } /* 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); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #else int main(void) { flint_printf("print/ read...."); fflush(stdout); flint_printf("SKIPPED\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fmpq_poly/test/t-rem.c000066400000000000000000000101751414523752600171150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("rem...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(q); fmpq_poly_clear(r); fmpq_poly_clear(r2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-rem_powers_precomp.c000066400000000000000000000105161414523752600222400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("rem_powers_precomp...."); fflush(stdout); /* 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-remove.c000066400000000000000000000120411414523752600176210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("remove...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(p); fmpq_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-rescale.c000066400000000000000000000052401414523752600177450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("rescale...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-resultant.c000066400000000000000000000132301414523752600203460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" #pragma GCC diagnostic ignored "-Woverlength-strings" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("resultant...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_clear(x); fmpq_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-resultant_div.c000066400000000000000000000106721414523752600212170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" #pragma GCC diagnostic ignored "-Woverlength-strings" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("resultant_div...."); fflush(stdout); 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-reverse.c000066400000000000000000000050361414523752600200050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("reverse...."); fflush(stdout); /* 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"); 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"); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-revert_series.c000066400000000000000000000055541414523752600212200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revert_series...."); fflush(stdout); /* 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"); 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"); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-revert_series_lagrange.c000066400000000000000000000056201414523752600230520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revert_series_lagrange...."); fflush(stdout); /* 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"); 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"); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-revert_series_lagrange_fast.c000066400000000000000000000056441414523752600240750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revert_series_lagrange_fast...."); fflush(stdout); /* 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"); 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"); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-revert_series_newton.c000066400000000000000000000056101414523752600226030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revert_series_newton...."); fflush(stdout); /* 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"); 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"); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-scalar_div_fmpq.c000066400000000000000000000111501414523752600214560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_div_fmpq...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_clear(z); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-scalar_div_fmpz.c000066400000000000000000000133761414523752600215030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_div_fmpz...."); fflush(stdout); /* 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); 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); 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); 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); abort(); } fmpz_clear(n); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-scalar_div_mpq.c000066400000000000000000000127631414523752600213230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_div_mpq...."); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpz_t r, s; mpq_t z; mpq_init(z); fmpz_init(r); fmpz_init(s); fmpz_randtest_not_zero(r, state, 100); fmpz_randtest_not_zero(s, state, 100); fmpz_get_mpz(mpq_numref(z), r); fmpz_get_mpz(mpq_denref(z), s); mpq_canonicalize(z); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_mpq(b, a, z); fmpq_poly_scalar_div_mpq(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"); gmp_printf("z = %Qd\n\n", z); flint_printf("cflags = %wu\n\n", cflags); abort(); } mpq_clear(z); fmpz_clear(r); fmpz_clear(s); 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; fmpz_t r, s; mpq_t z1, z2, z; fmpz_init(r); fmpz_init(s); mpq_init(z1); mpq_init(z2); mpq_init(z); fmpz_randtest_not_zero(r, state, 100); fmpz_randtest_not_zero(s, state, 100); fmpz_get_mpz(mpq_numref(z1), r); fmpz_get_mpz(mpq_denref(z1), s); mpq_canonicalize(z1); fmpz_randtest_not_zero(r, state, 100); fmpz_randtest_not_zero(s, state, 100); fmpz_get_mpz(mpq_numref(z2), r); fmpz_get_mpz(mpq_denref(z2), s); mpq_canonicalize(z2); mpq_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_mpq(lhs, a, z1); fmpq_poly_scalar_div_mpq(lhs, lhs, z2); fmpq_poly_scalar_div_mpq(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"); gmp_printf("z1 = %Qd\n\n", z1); gmp_printf("z2 = %Qd\n\n", z2); gmp_printf("z = %Qd\n\n", z); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); abort(); } mpq_clear(z1); mpq_clear(z2); mpq_clear(z); fmpz_clear(r); fmpz_clear(s); 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 r, s; mpq_t z; fmpz_init(r); fmpz_init(s); mpq_init(z); fmpz_randtest_not_zero(r, state, 100); fmpz_randtest_not_zero(s, state, 100); fmpz_get_mpz(mpq_numref(z), r); fmpz_get_mpz(mpq_denref(z), s); mpq_canonicalize(z); 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_mpq(lhs, a, z); fmpq_poly_scalar_div_mpq(rhs, b, z); fmpq_poly_add(rhs, lhs, rhs); fmpq_poly_add(lhs, a, b); fmpq_poly_scalar_div_mpq(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"); gmp_printf("z = %Qd\n\n", z); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); abort(); } mpq_clear(z); fmpz_clear(r); fmpz_clear(s); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-scalar_div_mpz.c000066400000000000000000000140421414523752600213240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_div_mpz...."); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpz_t n; mpz_t m; fmpz_init(n); mpz_init(m); fmpz_randtest_not_zero(n, state, 200); fmpz_get_mpz(m, n); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_div_mpz(b, a, m); fmpq_poly_scalar_div_mpz(a, a, m); 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); abort(); } fmpz_clear(n); mpz_clear(m); fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Compare with fmpq_poly_scalar_mul_si */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, c; mpz_t n1; slong n; n = z_randtest_not_zero(state); mpz_init(n1); flint_mpz_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_mpz(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"); flint_printf("%wd", n), 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); abort(); } mpz_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 < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, lhs, rhs; fmpz_t n1, n2; mpz_t m1, m2, m; fmpz_init(n1); fmpz_init(n2); mpz_init(m1); mpz_init(m2); mpz_init(m); fmpz_randtest_not_zero(n1, state, 100); fmpz_randtest_not_zero(n2, state, 100); fmpz_get_mpz(m1, n1); fmpz_get_mpz(m2, n2); mpz_mul(m, m1, m2); 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_mpz(lhs, a, m1); fmpq_poly_scalar_div_mpz(lhs, lhs, m2); fmpq_poly_scalar_div_mpz(rhs, a, m); 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"); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); abort(); } fmpz_clear(n1); fmpz_clear(n2); mpz_clear(m1); mpz_clear(m2); mpz_clear(m); 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 < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, lhs, rhs; fmpz_t n; mpz_t m; fmpz_init(n); mpz_init(m); fmpz_randtest_not_zero(n, state, 100); fmpz_get_mpz(m, n); 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_mpz(lhs, a, m); fmpq_poly_scalar_div_mpz(rhs, b, m); fmpq_poly_add(rhs, lhs, rhs); fmpq_poly_add(lhs, a, b); fmpq_poly_scalar_div_mpz(lhs, lhs, m); 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); abort(); } fmpz_clear(n); mpz_clear(m); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-scalar_div_si.c000066400000000000000000000076661414523752600211470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_div_si...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-scalar_div_ui.c000066400000000000000000000055621414523752600211420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_div_ui...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-scalar_mul_fmpq.c000066400000000000000000000114221414523752600214730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpq...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_clear(z); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-scalar_mul_fmpz.c000066400000000000000000000077241414523752600215160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpz...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpz_clear(n1); fmpq_poly_clear(a); fmpq_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-scalar_mul_mpq.c000066400000000000000000000127171414523752600213350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_mul_mpq...."); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpz_t r, s; mpq_t z; mpq_init(z); fmpz_init(r); fmpz_init(s); fmpz_randtest(r, state, 100); fmpz_randtest_not_zero(s, state, 100); fmpz_get_mpz(mpq_numref(z), r); fmpz_get_mpz(mpq_denref(z), s); mpq_canonicalize(z); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_mul_mpq(b, a, z); fmpq_poly_scalar_mul_mpq(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"); gmp_printf("z = %Qd\n\n", z); flint_printf("cflags = %wu\n\n", cflags); abort(); } mpq_clear(z); fmpz_clear(r); fmpz_clear(s); 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; fmpz_t r, s; mpq_t z1, z2, z; fmpz_init(r); fmpz_init(s); mpq_init(z1); mpq_init(z2); mpq_init(z); fmpz_randtest(r, state, 100); fmpz_randtest_not_zero(s, state, 100); fmpz_get_mpz(mpq_numref(z1), r); fmpz_get_mpz(mpq_denref(z1), s); mpq_canonicalize(z1); fmpz_randtest(r, state, 100); fmpz_randtest_not_zero(s, state, 100); fmpz_get_mpz(mpq_numref(z2), r); fmpz_get_mpz(mpq_denref(z2), s); mpq_canonicalize(z2); mpq_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_mpq(lhs, a, z1); fmpq_poly_scalar_mul_mpq(lhs, lhs, z2); fmpq_poly_scalar_mul_mpq(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"); gmp_printf("z1 = %Qd\n\n", z1); gmp_printf("z2 = %Qd\n\n", z2); gmp_printf("z = %Qd\n\n", z); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); abort(); } mpq_clear(z1); mpq_clear(z2); mpq_clear(z); fmpz_clear(r); fmpz_clear(s); 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 r, s; mpq_t z; fmpz_init(r); fmpz_init(s); mpq_init(z); fmpz_randtest(r, state, 100); fmpz_randtest_not_zero(s, state, 100); fmpz_get_mpz(mpq_numref(z), r); fmpz_get_mpz(mpq_denref(z), s); mpq_canonicalize(z); 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_mpq(lhs, a, z); fmpq_poly_scalar_mul_mpq(rhs, b, z); fmpq_poly_add(rhs, lhs, rhs); fmpq_poly_add(lhs, a, b); fmpq_poly_scalar_mul_mpq(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"); gmp_printf("z = %Qd\n\n", z); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); abort(); } mpq_clear(z); fmpz_clear(r); fmpz_clear(s); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-scalar_mul_mpz.c000066400000000000000000000101731414523752600213400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_mul_mpz...."); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpz_t n; mpz_t m; fmpz_init(n); mpz_init(m); fmpz_randtest(n, state, 200); fmpz_get_mpz(m, 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_mpz(b, a, m); fmpq_poly_scalar_mul_mpz(a, a, m); 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); abort(); } fmpz_clear(n); mpz_clear(m); fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check that n (a + b) == na + nb */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, lhs, rhs; fmpz_t n; mpz_t m; fmpz_init(n); mpz_init(m); fmpz_randtest(n, state, 200); fmpz_get_mpz(m, n); 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_mpz(lhs, a, m); fmpq_poly_scalar_mul_mpz(rhs, b, m); fmpq_poly_add(rhs, lhs, rhs); fmpq_poly_add(lhs, a, b); fmpq_poly_scalar_mul_mpz(lhs, lhs, m); 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); abort(); } fmpz_clear(n); mpz_clear(m); 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 < 100 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; mpz_t n1; slong n; n = z_randtest(state); mpz_init(n1); flint_mpz_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_mpz(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); abort(); } mpz_clear(n1); fmpq_poly_clear(a); fmpq_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-scalar_mul_si.c000066400000000000000000000075471414523752600211600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_mul_si...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-scalar_mul_ui.c000066400000000000000000000102051414523752600211430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_mul_ui...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-set_array_mpq.c000066400000000000000000000035251414523752600212010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("set_array_mpq...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { slong j, n = 100; fmpq_poly_t f, g; mpq_t * a; a = (mpq_t *) flint_malloc(n * sizeof(mpq_t)); for (j = 0; j < n; j++) mpq_init(a[j]); fmpq_poly_init(f); fmpq_poly_init(g); fmpq_poly_randtest(f, state, n_randint(state, n), 200); for (j = 0; j < f->length; j++) fmpq_poly_get_coeff_mpq(a[j], f, j); fmpq_poly_set_array_mpq(g, (const mpq_t *) a, n); cflags |= fmpq_poly_is_canonical(g) ? 0 : 1; result = (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("cflags = %wu\n\n", cflags); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); for (j = 0; j < n; j++) mpq_clear(a[j]); flint_free(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-set_equal.c000066400000000000000000000056301414523752600203140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set/equal...."); fflush(stdout); /* 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); 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); mpq_t x1, x2; fmpz_t x1fmpz; mpq_init(x1); mpq_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_mpq(x2, b, coeff); do { fmpz_randtest(x1fmpz, state, 200); fmpz_get_mpz(mpq_numref(x1), x1fmpz); flint_mpz_set_si(mpq_denref(x1), 1); } while (mpq_equal(x1, x2)); fmpq_poly_set_coeff_mpq(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); abort(); } mpq_clear(x1); mpq_clear(x2); fmpz_clear(x1fmpz); fmpq_poly_clear(a); fmpq_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-set_trunc.c000066400000000000000000000035301414523752600203350ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_trunc...."); fflush(stdout); 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"); 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"); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-shift_left_right.c000066400000000000000000000070461414523752600216610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("shift_left/right...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-sin_cos_series.c000066400000000000000000000075241414523752600213450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("sin_cos_series...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(sina1); fmpq_poly_clear(sina2); fmpq_poly_clear(cosa1); fmpq_poly_clear(cosa2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-sin_series.c000066400000000000000000000057151414523752600205010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("sin_series...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(sina); fmpq_poly_clear(asinsina); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-sinh_cosh_series.c000066400000000000000000000075751414523752600216730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("sinh_cosh_series...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(sinha1); fmpq_poly_clear(sinha2); fmpq_poly_clear(cosha1); fmpq_poly_clear(cosha2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-sinh_series.c000066400000000000000000000057541414523752600206540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("sinh_series...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(sinha); fmpq_poly_clear(asinhsinha); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-sqrt_series.c000066400000000000000000000055011414523752600206720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("sqrt_series...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-sub.c000066400000000000000000000074261414523752600171300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-sub_series.c000066400000000000000000000102001414523752600204620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("sub_series...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(d); fmpq_poly_clear(e); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-swap.c000066400000000000000000000027711414523752600173070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("swap...."); fflush(stdout); 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"); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-tan_series.c000066400000000000000000000057551414523752600204760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("tan_series...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(tana); fmpq_poly_clear(atantana); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-tanh_series.c000066400000000000000000000057541414523752600206450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("tanh_series...."); fflush(stdout); /* 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); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(tanha); fmpq_poly_clear(atanhtanha); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-xgcd.c000066400000000000000000000174321414523752600172620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int cflags = 0, i, result; FLINT_TEST_INIT(state); flint_printf("xgcd...."); fflush(stdout); /* 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); 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); 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); 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); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/test/t-zero.c000066400000000000000000000027511414523752600173120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("zero...."); fflush(stdout); 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); abort(); } fmpq_poly_clear(a); fmpq_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_poly/xgcd.c000066400000000000000000000143161414523752600160400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_div(C, primA, lenA, G, lenG, 0); _fmpz_poly_div(D, primB, lenB, G, lenG, 0); } 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_printf("Exception (fmpq_poly_xgcd). Output arguments aliased.\n"); flint_abort(); } 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); } } } } flint2-2.8.4/fmpq_poly/zero.c000066400000000000000000000011341414523752600160640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpq_polyxx.h000066400000000000000000000513571414523752600155060ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPQ_POLYXX_H #define FMPQ_POLYXX_H #include #include #include "flint.h" #include "fmpq_poly.h" #include "fmpqxx.h" #include "flintxx/expression.h" #include "flintxx/flint_classes.h" #include "flintxx/traits.h" // TODO exhibit this as a specialisation of a generic poly // TODO lazy version of numref? namespace flint { // function "declarations" FLINT_DEFINE_BINOP(fmpq_polyxx_get_coeff) FLINT_DEFINE_BINOP(fmpq_polyxx_interpolate) FLINT_DEFINE_UNOP(fmpq_polyxx_den) // TODO move to stdmath? // TODO move to stdmath? FLINT_DEFINE_BINOP(rescale) namespace detail { template struct fmpq_poly_traits { typedef FLINT_UNOP_BUILD_RETTYPE(fmpq_polyxx_den, fmpzxx, Poly) coeff_ref_t; typedef coeff_ref_t coeff_srcref_t; static coeff_srcref_t den(const Poly& p) {return fmpq_polyxx_den(p);} }; } // detail template class fmpq_polyxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef detail::fmpq_poly_traits poly_traits_t; typedef typename poly_traits_t::coeff_ref_t coeff_ref_t; typedef typename poly_traits_t::coeff_srcref_t coeff_srcref_t; FLINTXX_DEFINE_BASICS(fmpq_polyxx_expression) FLINTXX_DEFINE_CTORS(fmpq_polyxx_expression) FLINTXX_DEFINE_C_REF(fmpq_polyxx_expression, fmpq_poly_struct, _poly) // static methods which only make sense with fmpq_polyxx static fmpq_polyxx_expression randtest(frandxx& state, slong len, flint_bitcnt_t bits) { fmpq_polyxx_expression res; fmpq_poly_randtest(res._poly(), state._data(), len, bits); return res; } static fmpq_polyxx_expression randtest_unsigned(frandxx& state, slong len, flint_bitcnt_t bits) { fmpq_polyxx_expression res; fmpq_poly_randtest_unsigned(res._poly(), state._data(), len, bits); return res; } static fmpq_polyxx_expression randtest_not_zero(frandxx& state, slong len, flint_bitcnt_t bits) { fmpq_polyxx_expression res; fmpq_poly_randtest_not_zero(res._poly(), state._data(), len, bits); return res; } // TODO make lazy // TODO perhaps as member function (non-static?) template static fmpq_polyxx_expression get_slice(const Poly& p, slong i, slong j) { fmpq_polyxx_expression res; fmpq_poly_get_slice(res._poly(), p.evaluate()._poly(), i, j); return res; } template static FLINT_BINOP_ENABLE_RETTYPE(fmpq_polyxx_interpolate, Fmpq_vec1, Fmpq_vec2) interpolate(const Fmpq_vec1& xs, const Fmpq_vec2& ys) { return fmpq_polyxx_interpolate(xs, ys); } static fmpq_polyxx_expression zero() {return fmpq_polyxx_expression();} static fmpq_polyxx_expression one() { fmpq_polyxx_expression res; res.set_one(); return res; } // These only make sense with immediates void realloc(slong alloc) {fmpq_poly_realloc(_poly(), alloc);} void fit_length(slong len) {fmpq_poly_fit_length(_poly(), len);} void _normalise() {_fmpq_poly_normalise(_poly());} void _set_length(slong len) {_fmpq_poly_set_length(_poly(), len);} void canonicalise() {fmpq_poly_canonicalise(_poly());} bool is_canonical() const {return fmpq_poly_is_canonical(_poly());} void set_zero() {fmpq_poly_zero(_poly());} void set_one() {fmpq_poly_one(_poly());} coeff_ref_t get_coeff_numref(slong n) { return coeff_ref_t::make(fmpq_poly_numref(_poly()) + n); } coeff_srcref_t get_coeff_numref(slong n) const { return coeff_srcref_t::make(fmpq_poly_numref(_poly()) + n); } coeff_ref_t den() {return poly_traits_t::den(*this);} coeff_srcref_t den() const {return poly_traits_t::den(*this);} // These only make sense with target immediates template typename mp::enable_if >::type set_coeff(slong n, const Fmpz& x) { fmpq_poly_set_coeff_fmpz(_poly(), n, x.evaluate()._fmpz()); } template typename mp::enable_if >::type set_coeff(slong n, const Fmpq& x) { fmpq_poly_set_coeff_fmpq(_poly(), n, x.evaluate()._fmpq()); } template typename mp::enable_if >::type set_coeff(slong n, T x) { fmpq_poly_set_coeff_si(_poly(), n, x); } template typename mp::enable_if >::type set_coeff(slong n, T x) { fmpq_poly_set_coeff_ui(_poly(), n, x); } void truncate(slong n) {fmpq_poly_truncate(_poly(), n);} // These cause evaluation slong length() const {return fmpq_poly_length(this->evaluate()._poly());} slong degree() const {return fmpq_poly_degree(this->evaluate()._poly());} bool is_one() const {return fmpq_poly_is_one(this->evaluate()._poly());} bool is_zero() const {return fmpq_poly_is_zero(this->evaluate()._poly());} bool is_monic() const {return fmpq_poly_is_monic(this->evaluate()._poly());} bool is_squarefree() const {return fmpq_poly_is_squarefree(this->evaluate()._poly());} std::string pretty(const char* x) const { char* str = fmpq_poly_get_str_pretty(this->evaluate()._poly(), x); std::string res(str); flint_free(str); return res; } // lazy members FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval) template // NB: template to instantiate lazily FLINT_BINOP_ENABLE_RETTYPE( fmpq_polyxx_get_coeff, fmpq_polyxx_expression, Slong) get_coeff(const Slong& n) const { return fmpq_polyxx_get_coeff(*this, n); } FLINTXX_DEFINE_MEMBER_3OP(compose_series) FLINTXX_DEFINE_MEMBER_3OP(compose_series_brent_kung) FLINTXX_DEFINE_MEMBER_3OP(compose_series_horner) FLINTXX_DEFINE_MEMBER_3OP(div_series) FLINTXX_DEFINE_MEMBER_3OP(mullow) FLINTXX_DEFINE_MEMBER_BINOP(asinh_series) FLINTXX_DEFINE_MEMBER_BINOP(asin_series) FLINTXX_DEFINE_MEMBER_BINOP(atanh_series) FLINTXX_DEFINE_MEMBER_BINOP(atan_series) FLINTXX_DEFINE_MEMBER_BINOP(cosh_series) FLINTXX_DEFINE_MEMBER_BINOP(cos_series) FLINTXX_DEFINE_MEMBER_BINOP(divrem) FLINTXX_DEFINE_MEMBER_BINOP(exp_series) FLINTXX_DEFINE_MEMBER_BINOP(gcd) FLINTXX_DEFINE_MEMBER_BINOP(inv_series) FLINTXX_DEFINE_MEMBER_BINOP(inv_series_newton) FLINTXX_DEFINE_MEMBER_BINOP(invsqrt_series) FLINTXX_DEFINE_MEMBER_BINOP(lcm) FLINTXX_DEFINE_MEMBER_BINOP(log_series) FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_BINOP_(rescale, rescale) FLINTXX_DEFINE_MEMBER_BINOP(resultant) FLINTXX_DEFINE_MEMBER_BINOP(reverse) FLINTXX_DEFINE_MEMBER_BINOP(revert_series) FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange) FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange_fast) FLINTXX_DEFINE_MEMBER_BINOP(revert_series_newton) FLINTXX_DEFINE_MEMBER_BINOP_(shift_left, shift_left) FLINTXX_DEFINE_MEMBER_BINOP_(shift_right, shift_right) FLINTXX_DEFINE_MEMBER_BINOP(sinh_series) FLINTXX_DEFINE_MEMBER_BINOP(sin_series) FLINTXX_DEFINE_MEMBER_BINOP(sqrt_series) FLINTXX_DEFINE_MEMBER_BINOP(tanh_series) FLINTXX_DEFINE_MEMBER_BINOP(tan_series) FLINTXX_DEFINE_MEMBER_BINOP(xgcd) FLINTXX_DEFINE_MEMBER_UNOP(derivative) FLINTXX_DEFINE_MEMBER_UNOP(integral) FLINTXX_DEFINE_MEMBER_UNOP(inv) FLINTXX_DEFINE_MEMBER_UNOP(make_monic) FLINTXX_DEFINE_MEMBER_UNOP(primitive_part) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpqxx, content) }; namespace detail { struct fmpq_poly_data; } typedef fmpq_polyxx_expression fmpq_polyxx; typedef fmpq_polyxx_expression > fmpq_polyxx_ref; typedef fmpq_polyxx_expression > fmpq_polyxx_srcref; namespace detail { template<> struct fmpq_poly_traits { typedef fmpzxx_srcref coeff_ref_t; typedef fmpzxx_srcref coeff_srcref_t; template static coeff_srcref_t den(const P& p) {return coeff_srcref_t::make(fmpq_poly_denref(p._poly()));} }; template<> struct fmpq_poly_traits { typedef fmpzxx_ref coeff_ref_t; typedef fmpzxx_ref coeff_srcref_t; template static coeff_ref_t den(P p) {return coeff_ref_t::make(fmpq_poly_denref(p._poly()));} }; template<> struct fmpq_poly_traits { typedef fmpzxx_ref coeff_ref_t; typedef fmpzxx_srcref coeff_srcref_t; template static coeff_ref_t den(P& p) {return coeff_ref_t::make(fmpq_poly_denref(p._poly()));} template static coeff_srcref_t den(const P& p) {return coeff_srcref_t::make(fmpq_poly_denref(p._poly()));} }; struct fmpq_poly_data { fmpq_poly_t inner; typedef fmpq_poly_t& data_ref_t; typedef const fmpq_poly_t& data_srcref_t; fmpq_poly_data() {fmpq_poly_init(inner);} ~fmpq_poly_data() {fmpq_poly_clear(inner);} fmpq_poly_data(const fmpq_poly_data& o) { fmpq_poly_init(inner); fmpq_poly_set(inner, o.inner); } fmpq_poly_data(fmpq_polyxx_srcref r) { fmpq_poly_init(inner); fmpq_poly_set(inner, r._poly()); } fmpq_poly_data(slong alloc) { fmpq_poly_init2(inner, alloc); } fmpq_poly_data(const char* str) { fmpq_poly_init(inner); execution_check(!fmpq_poly_set_str(inner, str), "construct from string", "fmpq_polyxx"); } }; } // detail namespace traits { template struct is_fmpq_polyxx : mp::or_< traits::is_T_expr, flint_classes::is_source > { }; } // traits namespace mp { template struct all_fmpq_polyxx : mp::and_, all_fmpq_polyxx > { }; template struct all_fmpq_polyxx : traits::is_fmpq_polyxx { }; template struct enable_all_fmpq_polyxx : mp::enable_if, Out> { }; } // mp } // flint // here to deal with circular dependencies... #include "fmpz_polyxx.h" namespace flint { namespace rules { #define FMPQ_POLYXX_COND_S FLINTXX_COND_S(fmpq_polyxx) #define FMPQ_POLYXX_COND_T FLINTXX_COND_T(fmpq_polyxx) FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, FMPQ_POLYXX_COND_S, fmpq_poly_set(to._poly(), from._poly())) FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, traits::is_signed_integer, fmpq_poly_set_si(to._poly(), from)) FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, traits::is_unsigned_integer, fmpq_poly_set_ui(to._poly(), from)) FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, FMPZXX_COND_S, fmpq_poly_set_fmpz(to._poly(), from._fmpz())) FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, FMPQXX_COND_S, fmpq_poly_set_fmpq(to._poly(), from._fmpq())) FLINT_DEFINE_DOIT_COND2(assignment, FMPQ_POLYXX_COND_T, FMPZ_POLYXX_COND_S, fmpq_poly_set_fmpz_poly(to._poly(), from._poly())) FLINTXX_DEFINE_ASSIGN_STR(fmpq_polyxx, execution_check( !fmpq_poly_set_str(to._poly(), from), "assign string", "fmpq_polyxx")) FLINTXX_DEFINE_TO_STR(fmpq_polyxx, fmpq_poly_get_str(from._poly())) FLINTXX_DEFINE_SWAP(fmpq_polyxx, fmpq_poly_swap(e1._poly(), e2._poly())) FLINT_DEFINE_PRINT_COND(FMPQ_POLYXX_COND_S, fmpq_poly_fprint(to, from._poly())) FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPQ_POLYXX_COND_S, const char*, fmpq_poly_fprint_pretty(to, from._poly(), extra)) FLINT_DEFINE_READ_COND(FMPQ_POLYXX_COND_T, fmpq_poly_fread(from, to._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(reverse_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::fits_into_slong, fmpq_poly_reverse(to._poly(), e1._poly(), e2)) FLINTXX_DEFINE_CMP(fmpq_polyxx, fmpq_poly_cmp(e1._poly(), e2._poly())) FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpq_polyxx, FMPQ_POLYXX_COND_S, fmpq_poly_neg(to._poly(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(inv_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, fmpq_poly_inv(to._poly(), from._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(fmpq_polyxx_get_coeff_op, fmpqxx, FMPQ_POLYXX_COND_S, traits::fits_into_slong, fmpq_poly_get_coeff_fmpq(to._fmpq(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, fmpq_poly_add(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, fmpq_poly_sub(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPZXX_COND_S, fmpq_poly_scalar_mul_fmpz(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPQXX_COND_S, fmpq_poly_scalar_mul_fmpq(to._poly(), e1._poly(), e2._fmpq())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::is_signed_integer, fmpq_poly_scalar_mul_si(to._poly(), e1._poly(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::is_unsigned_integer, fmpq_poly_scalar_mul_ui(to._poly(), e1._poly(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPQXX_COND_S, fmpq_poly_scalar_div_fmpq(to._poly(), e1._poly(), e2._fmpq())) FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPZXX_COND_S, fmpq_poly_scalar_div_fmpz(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::is_unsigned_integer, fmpq_poly_scalar_div_ui(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::is_signed_integer, fmpq_poly_scalar_div_si(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, fmpq_poly_mul(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::is_unsigned_integer, fmpq_poly_pow(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::fits_into_slong, fmpq_poly_shift_left(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::fits_into_slong, fmpq_poly_shift_right(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, fmpq_poly_div(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, fmpq_poly_rem(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_newton_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::fits_into_slong, fmpq_poly_inv_series_newton(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::fits_into_slong, fmpq_poly_inv_series(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(gcd_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, fmpq_poly_gcd(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(lcm_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, fmpq_poly_lcm(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(resultant_op, fmpqxx, FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, fmpq_poly_resultant(to._fmpq(), e1._poly(), e2._poly())) FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, fmpq_poly_derivative(to._poly(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(integral_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, fmpq_poly_integral(to._poly(), from._poly())) #define FMPQ_POLYXX_DEFINE_SERIES(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_series_op, fmpq_polyxx, \ FMPQ_POLYXX_COND_S, traits::fits_into_slong, \ fmpq_poly_##name##_series(to._poly(), e1._poly(), e2)) FMPQ_POLYXX_DEFINE_SERIES(sqrt) FMPQ_POLYXX_DEFINE_SERIES(invsqrt) FMPQ_POLYXX_DEFINE_SERIES(exp) FMPQ_POLYXX_DEFINE_SERIES(log) FMPQ_POLYXX_DEFINE_SERIES(atan) FMPQ_POLYXX_DEFINE_SERIES(atanh) FMPQ_POLYXX_DEFINE_SERIES(asin) FMPQ_POLYXX_DEFINE_SERIES(asinh) FMPQ_POLYXX_DEFINE_SERIES(tan) FMPQ_POLYXX_DEFINE_SERIES(sin) FMPQ_POLYXX_DEFINE_SERIES(cos) FMPQ_POLYXX_DEFINE_SERIES(sinh) FMPQ_POLYXX_DEFINE_SERIES(cosh) FMPQ_POLYXX_DEFINE_SERIES(tanh) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpqxx, FMPQ_POLYXX_COND_S, FMPQXX_COND_S, fmpq_poly_evaluate_fmpq(to._fmpq(), e1._poly(), e2._fmpq())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpqxx, FMPQ_POLYXX_COND_S, FMPZXX_COND_S, fmpq_poly_evaluate_fmpz(to._fmpq(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(compose_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, fmpq_poly_compose(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(fmpq_polyxx_interpolate_op, fmpq_polyxx, FMPZ_VECXX_COND_S, FMPZ_VECXX_COND_S, fmpq_poly_interpolate_fmpz_vec(to._poly(), e1._data().array, e2._data().array, e2.size())) FLINT_DEFINE_BINARY_EXPR_COND2(rescale_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, FMPQXX_COND_S, fmpq_poly_rescale(to._poly(), e1._poly(), e2._fmpq())) FLINT_DEFINE_BINARY_EXPR_COND2(revert_series_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::fits_into_slong, fmpq_poly_revert_series(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(revert_series_lagrange_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::fits_into_slong, fmpq_poly_revert_series_lagrange(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(revert_series_lagrange_fast_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::fits_into_slong, fmpq_poly_revert_series_lagrange_fast(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(revert_series_newton_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, traits::fits_into_slong, fmpq_poly_revert_series_newton(to._poly(), e1._poly(), e2)) FLINT_DEFINE_UNARY_EXPR_COND(content_op, fmpqxx, FMPQ_POLYXX_COND_S, fmpq_poly_content(to._fmpq(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(primitive_part_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, fmpq_poly_primitive_part(to._poly(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(make_monic_op, fmpq_polyxx, FMPQ_POLYXX_COND_S, fmpq_poly_make_monic(to._poly(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(fmpq_polyxx_den_op, fmpzxx, FMPQ_POLYXX_COND_S, fmpz_set(to._fmpz(), fmpq_poly_denref(from._poly()))) namespace rdetail { typedef make_ltuple::type>::type fmpq_polyxx_triple; typedef make_ltuple::type>::type fmpq_polyxx_pair; } // rdetail FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_op, rdetail::fmpq_polyxx_triple, FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, fmpq_poly_xgcd(to.template get<0>()._poly(), to.template get<1>()._poly(), to.template get<2>()._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(divrem_op, rdetail::fmpq_polyxx_pair, FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, fmpq_poly_divrem(to.template get<0>()._poly(), to.template get<1>()._poly(), e1._poly(), e2._poly())) #define FMPQ_POLYXX_DEFINE_SERIES_FUNC(name) \ FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, fmpq_polyxx, \ FMPQ_POLYXX_COND_S, FMPQ_POLYXX_COND_S, traits::fits_into_slong, \ fmpq_poly_##name(to._poly(), e1._poly(), e2._poly(), e3)) FMPQ_POLYXX_DEFINE_SERIES_FUNC(mullow) FMPQ_POLYXX_DEFINE_SERIES_FUNC(div_series) FMPQ_POLYXX_DEFINE_SERIES_FUNC(compose_series) FMPQ_POLYXX_DEFINE_SERIES_FUNC(compose_series_brent_kung) FMPQ_POLYXX_DEFINE_SERIES_FUNC(compose_series_horner) } // rules // NB: fmpq_poly addmul is just done by hand currently, no need to wrap that .. } // flint #endif flint2-2.8.4/fmpq_vec.h000066400000000000000000000035751414523752600147170ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPQ_VEC_INLINE static __inline__ #endif #include #include "fmpq.h" #include "flint.h" #ifdef __cplusplus extern "C" { #endif /* Memory management *******************************************************/ /* _fmpq_vec_init and _fmpq_vec_clear are declared in fmpq.h for backward compatibility */ /* Randomisation ***********************************************************/ FLINT_DLL void _fmpq_vec_randtest(fmpq * f, flint_rand_t state, slong len, flint_bitcnt_t bits); FLINT_DLL void _fmpq_vec_randtest_uniq_sorted(fmpq * vec, flint_rand_t state, slong len, flint_bitcnt_t bits); /* Sorting ******************************************************************/ FLINT_DLL void _fmpq_vec_sort(fmpq * vec, slong len); /* Conversions *************************************************************/ FLINT_DLL void _fmpq_vec_set_fmpz_vec(fmpq * res, const fmpz * vec, slong len); /* Dot product **************************************************/ FLINT_DLL void _fmpq_vec_dot(fmpq_t res, const fmpq * vec1, const fmpq * vec2, slong len); /* Input and output ********************************************************/ FLINT_DLL int _fmpq_vec_fprint(FILE * file, const fmpq * vec, slong len); FMPQ_VEC_INLINE int _fmpq_vec_print(const fmpq * vec, slong len) { return _fmpq_vec_fprint(stdout, vec, len); } #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpq_vec/000077500000000000000000000000001414523752600145345ustar00rootroot00000000000000flint2-2.8.4/fmpq_vec/dot.c000066400000000000000000000012271414523752600154700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fmpq_vec/fprint.c000066400000000000000000000014401414523752600162010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_vec.h" int _fmpq_vec_fprint(FILE * file, const fmpq * vec, slong len) { int r; slong i; r = flint_fprintf(file, "%li", 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; } flint2-2.8.4/fmpq_vec/init.c000066400000000000000000000013041414523752600156410ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpq_vec/randtest.c000066400000000000000000000020211414523752600165170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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); } } } flint2-2.8.4/fmpq_vec/randtest_uniq_sorted.c000066400000000000000000000022331414523752600211400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.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) { fprintf(stderr, "ERROR (_fmpq_vec_randtest_uniq_sorted): bits too small\n"); flint_abort(); } _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); } flint2-2.8.4/fmpq_vec/set_fmpz_vec.c000066400000000000000000000012501414523752600173620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpq_vec.h" void _fmpq_vec_set_fmpz_vec(fmpq * res, const fmpz * vec, slong len) { slong i; fmpz_t one; fmpz_init_set_ui(one, 1); for (i = 0; i < len; i++) fmpq_set_fmpz_frac(res + i, vec + i, one); fmpz_clear(one); } flint2-2.8.4/fmpq_vec/sort.c000066400000000000000000000010751414523752600156720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpq_vec/test/000077500000000000000000000000001414523752600155135ustar00rootroot00000000000000flint2-2.8.4/fmpq_vec/test/t-dot.c000066400000000000000000000026731414523752600167160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpq.h" #include "fmpq_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("dot...."); fflush(stdout); /* 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"); abort(); } _fmpq_vec_clear(a, len); _fmpq_vec_clear(b, len); fmpq_clear(res1); fmpq_clear(res2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpq_vec/test/t-randtest_uniq_sorted.c000066400000000000000000000037741414523752600223730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpq_vec.h" int main() { int iter; FLINT_TEST_INIT(state); printf("randtest_uniq_sorted...."); 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); 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"); abort(); } } _fmpq_vec_clear(vec, n); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpqxx.h000066400000000000000000000410601414523752600144310ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_FMPQXX_H #define CXX_FMPQXX_H #include #include "fmpq.h" #include "flintxx/expression.h" #include "flintxx/flint_classes.h" #include "flintxx/flint_exception.h" #include "flintxx/frandxx.h" #include "fmpzxx.h" // TODO exhibit this as a specialisation of a generic fraction // TODO summation namespace flint { // function "declarations" FLINT_DEFINE_BINOP(fmpqxx_reconstruct) FLINT_DEFINE_FOURARY_HERE(fmpqxx_reconstruct) // four argument version FLINT_DEFINE_UNOP(fmpqxx_next_minimal) FLINT_DEFINE_UNOP(fmpqxx_next_signed_minimal) FLINT_DEFINE_UNOP(fmpqxx_next_calkin_wilf) FLINT_DEFINE_UNOP(fmpqxx_next_signed_calkin_wilf) FLINT_DEFINE_UNOP(fmpqxx_num) FLINT_DEFINE_UNOP(fmpqxx_den) namespace detail { template struct fmpq_traits { typedef FLINT_UNOP_BUILD_RETTYPE(fmpqxx_num, fmpzxx, Fmpq) numreturn_t; typedef FLINT_UNOP_BUILD_RETTYPE(fmpqxx_den, fmpzxx, Fmpq) denreturn_t; typedef numreturn_t cnumreturn_t; typedef denreturn_t cdenreturn_t; static numreturn_t num(const Fmpq& f) {return fmpqxx_num(f);} static denreturn_t den(const Fmpq& f) {return fmpqxx_den(f);} }; } template class fmpqxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; FLINTXX_DEFINE_BASICS(fmpqxx_expression) FLINTXX_DEFINE_CTORS(fmpqxx_expression) FLINTXX_DEFINE_C_REF(fmpqxx_expression, fmpq, _fmpq) // static methods which only make sense with fmpqxx FLINTXX_DEFINE_RANDFUNC(fmpq, randbits) FLINTXX_DEFINE_RANDFUNC(fmpq, randtest) FLINTXX_DEFINE_RANDFUNC(fmpq, randtest_not_zero) template static fmpqxx_expression from_cfrac(const Vec& v, slong n) { fmpqxx_expression res; res.set_cfrac(v, n); return res; } // TODO does this make more sense as standalone function? template static FLINT_BINOP_ENABLE_RETTYPE(fmpqxx_reconstruct, Fmpz1, Fmpz2) reconstruct(const Fmpz1& a, const Fmpz2& m) { return fmpqxx_reconstruct(a, m); } template static FLINT_FOURARY_ENABLE_RETTYPE(fmpqxx_reconstruct, Fmpz1, Fmpz2, Fmpz3, Fmpz4) reconstruct(const Fmpz1& a, const Fmpz2& m, const Fmpz3& N, const Fmpz4& D) { return fmpqxx_reconstruct(a, m, N, D); } template void set_frac(const F1& f1, const F2& f2) { num() = f1; den() = f2; canonicalise(); } template static fmpqxx_expression frac(const F1& f1, const F2& f2) { fmpqxx_expression res; res.set_frac(f1, f2); return res; } template void set_integer(const T& t) { num() = t; den() = 1u; } template static fmpqxx_expression integer(const T& t) { fmpqxx_expression res; res.set_integer(t); return res; } static fmpqxx_expression zero(){return fmpqxx_expression();} static fmpqxx_expression one() { fmpqxx_expression res; res.set_one(); return res; } // These only make sense with immediates void canonicalise() {fmpq_canonicalise(_fmpq());} bool is_canonical() const {return fmpq_is_canonical(_fmpq());} void set_zero() {fmpq_zero(_fmpq());} void set_one() {fmpq_one(_fmpq());} template void set_cfrac(const Vec& v, slong n) { fmpq_set_cfrac(this->_fmpq(), v._array(), n); } // Numerator and denominator access typedef detail::fmpq_traits traits_t; typename traits_t::numreturn_t num() {return traits_t::num(*this);} typename traits_t::cnumreturn_t num() const {return traits_t::num(*this);} typename traits_t::denreturn_t den() {return traits_t::den(*this);} typename traits_t::cdenreturn_t den() const {return traits_t::den(*this);} // These cause evaluation bool is_zero() const {return fmpq_is_zero(this->evaluate()._fmpq());} bool is_one() const {return fmpq_is_one(this->evaluate()._fmpq());} // TODO make this only work on immediates? slong cfrac_bound() const {return fmpq_cfrac_bound(this->evaluate()._fmpq());} int sgn() const {return fmpq_sgn(this->evaluate()._fmpq());} flint_bitcnt_t height_bits() const {return fmpq_height_bits(this->evaluate()._fmpq());} FLINTXX_DEFINE_MEMBER_UNOP_(next_minimal, fmpqxx_next_minimal) FLINTXX_DEFINE_MEMBER_UNOP_(next_signed_minimal, fmpqxx_next_signed_minimal) FLINTXX_DEFINE_MEMBER_UNOP_(next_calkin_wilf, fmpqxx_next_calkin_wilf) FLINTXX_DEFINE_MEMBER_UNOP_(next_signed_calkin_wilf, fmpqxx_next_signed_calkin_wilf) // forwarded member functions FLINTXX_DEFINE_MEMBER_UNOP(abs) FLINTXX_DEFINE_MEMBER_UNOP(inv) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, height) FLINTXX_DEFINE_MEMBER_BINOP(pow) }; namespace detail { struct fmpq_data; } typedef fmpqxx_expression fmpqxx; typedef fmpqxx_expression > fmpqxx_ref; typedef fmpqxx_expression > fmpqxx_srcref; namespace detail { template<> struct fmpq_traits { typedef fmpzxx_srcref numreturn_t; typedef fmpzxx_srcref cnumreturn_t; typedef fmpzxx_srcref denreturn_t; typedef fmpzxx_srcref cdenreturn_t; template static cnumreturn_t num(T f) {return cnumreturn_t::make(fmpq_numref(f._fmpq()));} template static cnumreturn_t den(T f) {return cnumreturn_t::make(fmpq_denref(f._fmpq()));} }; template<> struct fmpq_traits { typedef fmpzxx_ref numreturn_t; typedef fmpzxx_ref denreturn_t; typedef fmpzxx_ref cnumreturn_t; typedef fmpzxx_ref cdenreturn_t; template static cnumreturn_t num(T f) {return cnumreturn_t::make(fmpq_numref(f._fmpq()));} template static cnumreturn_t den(T f) {return cnumreturn_t::make(fmpq_denref(f._fmpq()));} }; template<> struct fmpq_traits { typedef fmpzxx_ref numreturn_t; typedef fmpzxx_ref denreturn_t; typedef fmpzxx_srcref cnumreturn_t; typedef fmpzxx_srcref cdenreturn_t; template static cnumreturn_t num(const T& f) {return cnumreturn_t::make(fmpq_numref(f._fmpq()));} template static cnumreturn_t den(const T& f) {return cnumreturn_t::make(fmpq_denref(f._fmpq()));} template static numreturn_t num(T& f) {return numreturn_t::make(fmpq_numref(f._fmpq()));} template static numreturn_t den(T& f) {return numreturn_t::make(fmpq_denref(f._fmpq()));} }; struct fmpq_data { fmpq_t inner; typedef fmpq_t& data_ref_t; typedef const fmpq_t& data_srcref_t; fmpq_data() {fmpq_init(inner);} ~fmpq_data() {fmpq_clear(inner);} fmpq_data(const fmpq_data& o) { fmpq_init(inner); fmpq_set(inner, o.inner); } fmpq_data(fmpqxx_srcref r) { fmpq_init(inner); fmpq_set(inner, r._fmpq()); } fmpq_data(fmpzxx_srcref num, fmpzxx_srcref den) { fmpq_init(inner); fmpq_set_fmpz_frac(inner, num._fmpz(), den._fmpz()); } template fmpq_data(T num, U den, typename mp::enable_if >::type* = 0, typename mp::enable_if >::type* = 0) { fmpq_init(inner); fmpq_set_si(inner, num, den); } }; } // detail // TODO macroize? namespace traits { template struct is_fmpqxx : mp::or_< traits::is_T_expr, flint_classes::is_source > { }; } // traits namespace rules { #define FMPQXX_COND_S FLINTXX_COND_S(fmpqxx) #define FMPQXX_COND_T FLINTXX_COND_T(fmpqxx) FLINT_DEFINE_DOIT_COND2(assignment, FMPQXX_COND_T, FMPQXX_COND_S, fmpq_set(to._fmpq(), from._fmpq())) FLINT_DEFINE_DOIT_COND2(assignment, FMPQXX_COND_T, traits::fits_into_slong, fmpq_set_si(to._fmpq(), from, 1)) // TODO mpq, mpfr? FLINTXX_DEFINE_TO_STR(fmpqxx, fmpq_get_str(0, base, from._fmpq())) FLINTXX_DEFINE_CMP(fmpqxx, fmpq_cmp(e1._fmpq(), e2._fmpq())) template struct cmp, FMPZXX_COND_S > >::type> { static int get(const T& v, const U& t) { return fmpq_cmp_fmpz(v._fmpq(), t._fmpz()); } }; template struct cmp, traits::is_unsigned_integer > >::type> { static int get(const T& v, const U& t) { return fmpq_cmp_ui(v._fmpq(), t); } }; template struct cmp, traits::is_signed_integer > >::type> { static int get(const T& v, const U& t) { return fmpq_cmp_si(v._fmpq(), t); } }; FLINTXX_DEFINE_SWAP(fmpqxx, fmpq_swap(e1._fmpq(), e2._fmpq())) FLINT_DEFINE_PRINT_COND(FMPQXX_COND_S, (fmpq_fprint(to, from._fmpq()), 1)) FLINT_DEFINE_GET_COND(conversion, double, FMPQXX_COND_S, fmpq_get_d(from._fmpq())) FLINT_DEFINE_CBINARY_EXPR_COND2(plus, fmpqxx, FMPQXX_COND_S, FMPQXX_COND_S, fmpq_add(to._fmpq(), e1._fmpq(), e2._fmpq())) FLINT_DEFINE_CBINARY_EXPR_COND2(plus, fmpqxx, FMPQXX_COND_S, FMPZXX_COND_S, fmpq_add_fmpz(to._fmpq(), e1._fmpq(), e2._fmpz())) FLINT_DEFINE_CBINARY_EXPR_COND2(plus, fmpqxx, FMPQXX_COND_S, traits::is_unsigned_integer, fmpq_add_ui(to._fmpq(), e1._fmpq(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(plus, fmpqxx, FMPQXX_COND_S, traits::is_signed_integer, fmpq_add_si(to._fmpq(), e1._fmpq(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpqxx, FMPQXX_COND_S, FMPQXX_COND_S, fmpq_sub(to._fmpq(), e1._fmpq(), e2._fmpq())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpqxx, FMPQXX_COND_S, FMPZXX_COND_S, fmpq_sub_fmpz(to._fmpq(), e1._fmpq(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpqxx, FMPQXX_COND_S, traits::is_unsigned_integer, fmpq_sub_ui(to._fmpq(), e1._fmpq(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpqxx, FMPQXX_COND_S, traits::is_signed_integer, fmpq_sub_si(to._fmpq(), e1._fmpq(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpqxx, FMPQXX_COND_S, FMPQXX_COND_S, fmpq_mul(to._fmpq(), e1._fmpq(), e2._fmpq())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpqxx, FMPQXX_COND_S, FMPZXX_COND_S, fmpq_mul_fmpz(to._fmpq(), e1._fmpq(), e2._fmpz())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpqxx, FMPQXX_COND_S, traits::is_unsigned_integer, fmpq_mul_ui(to._fmpq(), e1._fmpq(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpqxx, FMPQXX_COND_S, traits::is_signed_integer, fmpq_mul_si(to._fmpq(), e1._fmpq(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpqxx, FMPQXX_COND_S, FMPQXX_COND_S, fmpq_div(to._fmpq(), e1._fmpq(), e2._fmpq())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpqxx, FMPQXX_COND_S, FMPZXX_COND_S, fmpq_div_fmpz(to._fmpq(), e1._fmpq(), e2._fmpz())) FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpqxx, FMPQXX_COND_S, fmpq_neg(to._fmpq(), from._fmpq())) FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpzxx, FMPQXX_COND_S, FMPZXX_COND_S, execution_check(fmpq_mod_fmpz(to._fmpz(), e1._fmpq(), e2._fmpz()), "modular inversion", "fmpq")) // TODO macroize? namespace rdetail { template void fmpqxx_shift(Fmpq1& to, const Fmpq2& from, T howmuch) { if(howmuch < 0) fmpq_div_2exp(to._fmpq(), from._fmpq(), -howmuch); else fmpq_mul_2exp(to._fmpq(), from._fmpq(), howmuch); } } // rdetail FLINT_DEFINE_BINARY_EXPR_COND2(shift, fmpqxx, FMPQXX_COND_S, traits::is_integer, rdetail::fmpqxx_shift(to, e1, e2)) } // rules FLINTXX_DEFINE_TERNARY(fmpqxx, fmpq_addmul(to._fmpq(), e1._fmpq(), e2._fmpq()), fmpq_submul(to._fmpq(), e1._fmpq(), e2._fmpq()), FLINTXX_UNADORNED_MAKETYPES) // immediate functions template inline typename mp::enable_if, flint_bitcnt_t>::type height_bits(const Fmpq& f) { return f.height_bits(); } // TODO maybe as a member function? template inline typename mp::enable_if, FMPQXX_COND_T >, int>::type get_cfrac(Vec& v, Fmpq1& rem, const Fmpq2& x) { return fmpq_get_cfrac(v._array(), rem._fmpq(), x.evaluate()._fmpq(), v.size()); } // TODO also set_cfrac? c/f fmpqxx::set_cfrac ... template inline typename mp::enable_if, int>::type sgn(const Fmpq& f) { return f.sgn(); } namespace rules { FLINT_DEFINE_UNARY_EXPR_COND(abs_op, fmpqxx, FMPQXX_COND_S, fmpq_abs(to._fmpq(), from._fmpq())) FLINT_DEFINE_UNARY_EXPR_COND(height_op, fmpzxx, FMPQXX_COND_S, fmpq_height(to._fmpz(), from._fmpq())) FLINT_DEFINE_UNARY_EXPR_COND(inv_op, fmpqxx, FMPQXX_COND_S, fmpq_inv(to._fmpq(), from._fmpq())) FLINT_DEFINE_UNARY_EXPR_COND(fmpqxx_next_minimal_op, fmpqxx, FMPQXX_COND_S, fmpq_next_minimal(to._fmpq(), from._fmpq())) FLINT_DEFINE_UNARY_EXPR_COND(fmpqxx_next_signed_minimal_op, fmpqxx, FMPQXX_COND_S, fmpq_next_signed_minimal(to._fmpq(), from._fmpq())) FLINT_DEFINE_UNARY_EXPR_COND(fmpqxx_next_calkin_wilf_op, fmpqxx, FMPQXX_COND_S, fmpq_next_calkin_wilf(to._fmpq(), from._fmpq())) FLINT_DEFINE_UNARY_EXPR_COND(fmpqxx_next_signed_calkin_wilf_op, fmpqxx, FMPQXX_COND_S, fmpq_next_signed_calkin_wilf(to._fmpq(), from._fmpq())) FLINT_DEFINE_UNARY_EXPR_COND(fmpqxx_num_op, fmpzxx, FMPQXX_COND_S, fmpz_set(to._fmpz(), fmpq_numref(from._fmpq()))) FLINT_DEFINE_UNARY_EXPR_COND(fmpqxx_den_op, fmpzxx, FMPQXX_COND_S, fmpz_set(to._fmpz(), fmpq_denref(from._fmpq()))) // TODO should this throw a different exception type? FLINT_DEFINE_BINARY_EXPR_COND2(fmpqxx_reconstruct_op, fmpqxx, FMPZXX_COND_S, FMPZXX_COND_S, execution_check(fmpq_reconstruct_fmpz( to._fmpq(), e1._fmpz(), e2._fmpz()), "rational reconstruction", "fmpq")) FLINT_DEFINE_FOURARY_EXPR_COND4(fmpqxx_reconstruct_op, fmpqxx, FMPZXX_COND_S, FMPZXX_COND_S, FMPZXX_COND_S, FMPZXX_COND_S, execution_check(fmpq_reconstruct_fmpz_2( to._fmpq(), e1._fmpz(), e2._fmpz(), e3._fmpz(), e4._fmpz()), "rational reconstruction (v2)", "fmpq")) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpqxx, FMPQXX_COND_S, traits::fits_into_slong, fmpq_pow_si(to._fmpq(), e1._fmpq(), e2)) } } // flint // fmpq_vecxx #include "flintxx/vector.h" namespace flint { namespace detail { struct fmpq_vector_data { slong size; fmpq* array; fmpq_vector_data(slong n) : size(n), array(_fmpq_vec_init(n)) {} ~fmpq_vector_data() {_fmpq_vec_clear(array, size);} fmpq_vector_data(const fmpq_vector_data& o) : size(o.size), array(_fmpq_vec_init(o.size)) { for(slong i = 0;i < size;++i) fmpq_set(array + i, o.array + i); } fmpqxx_ref at(slong i) {return fmpqxx_ref::make(array + i);} fmpqxx_srcref at(slong i) const {return fmpqxx_srcref::make(array + i);} }; } // detail typedef vector_expression< detail::wrapped_vector_traits, operations::immediate, detail::fmpq_vector_data> fmpq_vecxx; template<> struct enable_vector_rules : mp::false_ { }; namespace detail { inline bool fmpq_vec_equal(const fmpq* v1, const fmpq* v2, slong n) { for(slong i = 0;i < n;++i) if(!fmpq_equal(v1+i, v2+i)) return false; return true; } } namespace rules { // TODO hack to make code look like references are implemented template struct FMPQ_VECXX_COND_S : mp::equal_types { }; #define FMPQ_VECXX_COND_T FMPQ_VECXX_COND_S // TODO references FLINT_DEFINE_GET(equals, bool, fmpq_vecxx, e1.size() == e2.size() && detail::fmpq_vec_equal(e1._data().array, e2._data().array, e1.size())) } // rules } // flint #endif flint2-2.8.4/fmpz-conversions-gc.in000066400000000000000000000004771414523752600172050ustar00rootroot00000000000000#ifndef FMPZ_CONVERSIONS_H #define FMPZ_CONVERSIONS_H /* turn a pointer to an __mpz_struct into a fmpz_t */ #define PTR_TO_COEFF(x) (((ulong) (x) >> 2) | (WORD(1) << (FLINT_BITS - 2))) /* turns an fmpz into a pointer to an mpz */ #define COEFF_TO_PTR(x) ((__mpz_struct *) ((x) << 2)) #endif /* FMPZ_CONVERSIONS_H */ flint2-2.8.4/fmpz-conversions-reentrant.in000066400000000000000000000004771414523752600206160ustar00rootroot00000000000000#ifndef FMPZ_CONVERSIONS_H #define FMPZ_CONVERSIONS_H /* turn a pointer to an __mpz_struct into a fmpz_t */ #define PTR_TO_COEFF(x) (((ulong) (x) >> 2) | (WORD(1) << (FLINT_BITS - 2))) /* turns an fmpz into a pointer to an mpz */ #define COEFF_TO_PTR(x) ((__mpz_struct *) ((x) << 2)) #endif /* FMPZ_CONVERSIONS_H */ flint2-2.8.4/fmpz-conversions-single.in000066400000000000000000000004771414523752600200750ustar00rootroot00000000000000#ifndef FMPZ_CONVERSIONS_H #define FMPZ_CONVERSIONS_H /* turn a pointer to an __mpz_struct into a fmpz_t */ #define PTR_TO_COEFF(x) (((ulong) (x) >> 2) | (WORD(1) << (FLINT_BITS - 2))) /* turns an fmpz into a pointer to an mpz */ #define COEFF_TO_PTR(x) ((__mpz_struct *) ((x) << 2)) #endif /* FMPZ_CONVERSIONS_H */ flint2-2.8.4/fmpz.h000066400000000000000000000737001414523752600140700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_H #define FMPZ_H #ifdef FMPZ_INLINES_C #define FMPZ_INLINE FLINT_DLL #else #define FMPZ_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "fmpz-conversions.h" #if FLINT_USES_PTHREAD #include #endif #ifdef __cplusplus extern "C" { #endif typedef slong fmpz; typedef fmpz fmpz_t[1]; typedef gmp_randstate_t fmpz_randstate_t; extern __mpz_struct * fmpz_arr; extern gmp_randstate_t fmpz_randstate; typedef struct { mp_ptr dinv; slong n; flint_bitcnt_t norm; } fmpz_preinvn_struct; typedef fmpz_preinvn_struct fmpz_preinvn_t[1]; typedef struct { int count; #if FLINT_USES_PTHREAD pthread_t thread; #endif void * address; } fmpz_block_header_s; /* maximum positive value a small coefficient can have */ #define COEFF_MAX ((WORD(1) << (FLINT_BITS - 2)) - WORD(1)) /* minimum negative value a small coefficient can have */ #define COEFF_MIN (-((WORD(1) << (FLINT_BITS - 2)) - WORD(1))) #define COEFF_IS_MPZ(x) (((x) >> (FLINT_BITS - 2)) == WORD(1)) /* is x a pointer not an integer */ FLINT_DLL __mpz_struct * _fmpz_new_mpz(void); FLINT_DLL void _fmpz_clear_mpz(fmpz f); FLINT_DLL void _fmpz_cleanup_mpz_content(void); FLINT_DLL void _fmpz_cleanup(void); FLINT_DLL __mpz_struct * _fmpz_promote(fmpz_t f); FLINT_DLL __mpz_struct * _fmpz_promote_val(fmpz_t f); FMPZ_INLINE void _fmpz_demote(fmpz_t f) { /* warning, if fmpz_demote changes, fmpz_zero must also be changed to match */ if (COEFF_IS_MPZ(*f)) { _fmpz_clear_mpz(*f); (*f) = WORD(0); } } FLINT_DLL void _fmpz_demote_val(fmpz_t f); FLINT_DLL void _fmpz_init_readonly_mpz(fmpz_t f, const mpz_t z); FLINT_DLL void _fmpz_clear_readonly_mpz(mpz_t); FMPZ_INLINE void fmpz_init(fmpz_t f) { (*f) = WORD(0); } FLINT_DLL void fmpz_init2(fmpz_t f, ulong limbs); FMPZ_INLINE void fmpz_init_set(fmpz_t f, const fmpz_t g) { if (!COEFF_IS_MPZ(*g)) { *f = *g; } else { __mpz_struct *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 { __mpz_struct *ptr; ptr = _fmpz_new_mpz(); *f = PTR_TO_COEFF(ptr); flint_mpz_set_ui(ptr, g); } } FMPZ_INLINE void fmpz_init_set_si(fmpz_t f, slong g) { if (COEFF_MIN <= g && g <= COEFF_MAX) { *f = g; } else { __mpz_struct *ptr; ptr = _fmpz_new_mpz(); *f = PTR_TO_COEFF(ptr); flint_mpz_set_si(ptr, g); } } FMPZ_INLINE void fmpz_clear(fmpz_t f) { if (COEFF_IS_MPZ(*f)) _fmpz_clear_mpz(*f); } FLINT_DLL void fmpz_randbits(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void fmpz_randm(fmpz_t f, flint_rand_t state, const fmpz_t m); FLINT_DLL void fmpz_randtest(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void fmpz_randtest_unsigned(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void fmpz_randtest_not_zero(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void fmpz_randtest_mod(fmpz_t f, flint_rand_t state, const fmpz_t m); FLINT_DLL void fmpz_randtest_mod_signed(fmpz_t f, flint_rand_t state, const fmpz_t m); FLINT_DLL void fmpz_randprime(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits, int proved); FLINT_DLL slong fmpz_get_si(const fmpz_t f); FLINT_DLL ulong fmpz_get_ui(const fmpz_t f); FLINT_DLL mp_limb_t fmpz_get_nmod(const fmpz_t f, nmod_t mod); 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_si(fmpz_t f, slong val) { if (val < COEFF_MIN || val > COEFF_MAX) /* val is large */ { __mpz_struct *mpz_coeff = _fmpz_promote(f); flint_mpz_set_si(mpz_coeff, val); } else { _fmpz_demote(f); *f = val; /* val is small */ } } FMPZ_INLINE void fmpz_set_ui(fmpz_t f, ulong val) { if (val > COEFF_MAX) /* val is large */ { __mpz_struct *mpz_coeff = _fmpz_promote(f); flint_mpz_set_ui(mpz_coeff, val); } else { _fmpz_demote(f); *f = val; /* val is small */ } } FMPZ_INLINE void fmpz_neg_ui(fmpz_t f, ulong val) { if (val > COEFF_MAX) { __mpz_struct *mpz_coeff = _fmpz_promote(f); flint_mpz_set_ui(mpz_coeff, val); mpz_neg(mpz_coeff, mpz_coeff); } else { _fmpz_demote(f); *f = -(slong) val; } } 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; } } FLINT_DLL void fmpz_get_signed_uiui(ulong * hi, ulong * lo, const fmpz_t x); FLINT_DLL void fmpz_set_signed_uiui(fmpz_t r, ulong hi, ulong lo); FLINT_DLL void fmpz_set_signed_uiuiui(fmpz_t r, ulong hi, ulong mid, ulong lo); FLINT_DLL void fmpz_get_ui_array(ulong * out, slong n, const fmpz_t in); FLINT_DLL void fmpz_set_ui_array(fmpz_t out, const ulong * in, slong n); FLINT_DLL void fmpz_get_signed_ui_array(ulong * out, slong n, const fmpz_t in); FLINT_DLL void fmpz_set_signed_ui_array(fmpz_t out, const ulong * in, slong n); FLINT_DLL void fmpz_get_mpz(mpz_t x, const fmpz_t f); FLINT_DLL void fmpz_set_mpz(fmpz_t f, const mpz_t x); FLINT_DLL double fmpz_get_d(const fmpz_t f); FLINT_DLL void fmpz_set_d(fmpz_t f, double c); FLINT_DLL void fmpz_get_mpf(mpf_t x, const fmpz_t f); FLINT_DLL void fmpz_set_mpf(fmpz_t f, const mpf_t x); FLINT_DLL void fmpz_get_mpfr(mpfr_t x, const fmpz_t f, mpfr_rnd_t rnd); FLINT_DLL int fmpz_get_mpn(mp_ptr *n, fmpz_t n_in); FLINT_DLL int fmpz_set_str(fmpz_t f, const char * str, int b); FLINT_DLL void flint_mpz_init_set_readonly(mpz_t z, const fmpz_t f); FLINT_DLL void flint_mpz_clear_readonly(mpz_t z); FLINT_DLL void fmpz_init_set_readonly(fmpz_t f, const mpz_t z); FLINT_DLL void fmpz_clear_readonly(fmpz_t f); FLINT_DLL int fmpz_abs_fits_ui(const fmpz_t f); FLINT_DLL int fmpz_fits_si(const fmpz_t f); 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); } 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); } FLINT_DLL void fmpz_set(fmpz_t f, const fmpz_t g); FLINT_DLL int fmpz_equal(const fmpz_t f, const fmpz_t g); FLINT_DLL int fmpz_equal_si(const fmpz_t f, slong g); FLINT_DLL int fmpz_equal_ui(const fmpz_t f, ulong g); FLINT_DLL int fmpz_read(fmpz_t f); FLINT_DLL int fmpz_fread(FILE * file, fmpz_t f); FLINT_DLL size_t fmpz_inp_raw( fmpz_t x, FILE *fin ); FLINT_DLL int fmpz_print(const fmpz_t x); FLINT_DLL int fmpz_fprint(FILE * file, const fmpz_t x); FLINT_DLL size_t fmpz_out_raw( FILE *fout, const fmpz_t x ); FLINT_DLL size_t fmpz_sizeinbase(const fmpz_t f, int b); FLINT_DLL char * fmpz_get_str(char * str, int b, const fmpz_t f); FMPZ_INLINE void fmpz_swap(fmpz_t f, fmpz_t g) { if (f != g) /* swapping required */ { fmpz t = *f; *f = *g; *g = t; } } FLINT_DLL int fmpz_cmp(const fmpz_t f, const fmpz_t g); FLINT_DLL int fmpz_cmp_ui(const fmpz_t f, ulong g); FLINT_DLL int fmpz_cmp_si(const fmpz_t f, slong g); FLINT_DLL int fmpz_cmpabs(const fmpz_t f, const fmpz_t g); FLINT_DLL int fmpz_cmp2abs(const fmpz_t f, const fmpz_t g); 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)); } } FLINT_DLL mp_size_t fmpz_size(const fmpz_t f); FLINT_DLL int fmpz_sgn(const fmpz_t f); FLINT_DLL flint_bitcnt_t fmpz_bits(const fmpz_t f); FLINT_DLL flint_bitcnt_t fmpz_val2(const fmpz_t x); FMPZ_INLINE 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_DLL void fmpz_abs(fmpz_t f1, const fmpz_t f2); FLINT_DLL void fmpz_add(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_sub(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_mul_ui(fmpz_t f, const fmpz_t g, ulong x); FLINT_DLL void fmpz_mul_si(fmpz_t f, const fmpz_t g, slong x); FLINT_DLL void fmpz_mul(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_mul_2exp(fmpz_t f, const fmpz_t g, ulong exp); FLINT_DLL void fmpz_add_ui(fmpz_t f, const fmpz_t g, ulong x); FLINT_DLL 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); } FMPZ_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); } FMPZ_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); } FMPZ_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); } FLINT_DLL void fmpz_addmul_si(fmpz_t f, const fmpz_t g, slong x); FLINT_DLL void fmpz_submul_si(fmpz_t f, const fmpz_t g, slong x); FLINT_DLL void fmpz_addmul_ui(fmpz_t f, const fmpz_t g, ulong x); FLINT_DLL void fmpz_submul_ui(fmpz_t f, const fmpz_t g, ulong x); FLINT_DLL void fmpz_addmul(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_submul(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_fmma(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d); FLINT_DLL void fmpz_fmms(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_t d); FLINT_DLL void fmpz_pow_ui(fmpz_t f, const fmpz_t g, ulong exp); FLINT_DLL int fmpz_pow_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t e); FLINT_DLL void fmpz_powm_ui(fmpz_t f, const fmpz_t g, ulong exp, const fmpz_t m); FLINT_DLL void fmpz_powm(fmpz_t f, const fmpz_t g, const fmpz_t e, const fmpz_t m); FLINT_DLL void fmpz_setbit(fmpz_t f, ulong i); FLINT_DLL int fmpz_tstbit(const fmpz_t f, ulong i); FLINT_DLL void fmpz_clrbit(fmpz_t f, ulong i); FLINT_DLL void fmpz_complement(fmpz_t r, const fmpz_t f); FLINT_DLL void fmpz_combit(fmpz_t f, ulong i); FLINT_DLL void fmpz_and(fmpz_t r, const fmpz_t a, const fmpz_t b); FLINT_DLL void fmpz_or(fmpz_t r, const fmpz_t a, const fmpz_t b); FLINT_DLL void fmpz_xor(fmpz_t r, const fmpz_t a, const fmpz_t b); FLINT_DLL flint_bitcnt_t fmpz_popcnt(const fmpz_t c); FLINT_DLL double fmpz_dlog(const fmpz_t x); FLINT_DLL slong fmpz_flog(const fmpz_t x, const fmpz_t b); FLINT_DLL slong fmpz_flog_ui(const fmpz_t x, ulong b); FLINT_DLL slong fmpz_clog(const fmpz_t x, const fmpz_t b); FLINT_DLL slong fmpz_clog_ui(const fmpz_t x, ulong b); FLINT_DLL int fmpz_sqrtmod(fmpz_t b, const fmpz_t a, const fmpz_t p); FLINT_DLL void fmpz_sqrt(fmpz_t f, const fmpz_t g); FLINT_DLL int fmpz_is_square(const fmpz_t f); FLINT_DLL void fmpz_root(fmpz_t r, const fmpz_t f, slong n); FLINT_DLL int fmpz_is_perfect_power(fmpz_t root, const fmpz_t f); FLINT_DLL void fmpz_sqrtrem(fmpz_t f, fmpz_t r, const fmpz_t g); FLINT_DLL ulong fmpz_fdiv_ui(const fmpz_t g, ulong h); FLINT_DLL ulong fmpz_mod_ui(fmpz_t f, const fmpz_t g, ulong h); FLINT_DLL void fmpz_mod(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_smod(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL 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); } FLINT_DLL void fmpz_gcd(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_gcd3(fmpz_t f, const fmpz_t a, const fmpz_t b, const fmpz_t c); FLINT_DLL void fmpz_lcm(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_gcdinv(fmpz_t d, fmpz_t a, const fmpz_t f, const fmpz_t g); FLINT_DLL void fmpz_xgcd(fmpz_t d, fmpz_t a, fmpz_t b, const fmpz_t f, const fmpz_t g); FLINT_DLL void fmpz_xgcd_canonical_bezout(fmpz_t d, fmpz_t a, fmpz_t b, const fmpz_t f, const fmpz_t g); FLINT_DLL void fmpz_xgcd_partial(fmpz_t co2, fmpz_t co1, fmpz_t r2, fmpz_t r1, const fmpz_t L); FLINT_DLL int fmpz_invmod(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL int fmpz_jacobi(const fmpz_t a, const fmpz_t p); FLINT_DLL int fmpz_kronecker(const fmpz_t a, const fmpz_t n); FLINT_DLL 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); FLINT_DLL slong _fmpz_remove(fmpz_t x, const fmpz_t f, double finv); FLINT_DLL slong fmpz_remove(fmpz_t rop, const fmpz_t op, const fmpz_t f); FLINT_DLL void fmpz_divexact(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_divexact_si(fmpz_t f, const fmpz_t g, slong h); FLINT_DLL void fmpz_divexact_ui(fmpz_t f, const fmpz_t g, ulong h); FLINT_DLL int fmpz_divisible(const fmpz_t f, const fmpz_t g); FLINT_DLL int fmpz_divides(fmpz_t q, const fmpz_t g, const fmpz_t h); FLINT_DLL int fmpz_divisible_si(const fmpz_t f, slong g); FLINT_DLL void fmpz_cdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_cdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_cdiv_q_si(fmpz_t f, const fmpz_t g, slong h); FLINT_DLL void fmpz_cdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h); FLINT_DLL void fmpz_cdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp); FLINT_DLL void fmpz_cdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp); FLINT_DLL ulong fmpz_cdiv_ui(const fmpz_t g, ulong h); FLINT_DLL void fmpz_fdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_fdiv_qr_preinvn(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h, const fmpz_preinvn_t inv); FLINT_DLL void fmpz_fdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_fdiv_r(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_fdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h); FLINT_DLL void fmpz_fdiv_q_si(fmpz_t f, const fmpz_t g, slong h); FLINT_DLL void fmpz_fdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp); FLINT_DLL void fmpz_fdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp); FLINT_DLL void fmpz_tdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_tdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h); FLINT_DLL void fmpz_tdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h); FLINT_DLL void fmpz_tdiv_q_si(fmpz_t f, const fmpz_t g, slong h); FLINT_DLL void fmpz_tdiv_r_2exp(fmpz_t f, const fmpz_t g, ulong exp); FLINT_DLL ulong fmpz_tdiv_ui(const fmpz_t g, ulong h); FLINT_DLL void fmpz_tdiv_q_2exp(fmpz_t f, const fmpz_t g, ulong exp); FLINT_DLL void fmpz_ndiv_qr(fmpz_t q, fmpz_t r, const fmpz_t a, const fmpz_t b); FLINT_DLL void fmpz_preinvn_init(fmpz_preinvn_t inv, const fmpz_t f); FLINT_DLL void fmpz_preinvn_clear(fmpz_preinvn_t inv); FLINT_DLL double fmpz_get_d_2exp(slong * exp, const fmpz_t f); FLINT_DLL void fmpz_set_d_2exp(fmpz_t f, double m, slong exp); 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); } } 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); } } FLINT_DLL void fmpz_mul_tdiv_q_2exp(fmpz_t f, const fmpz_t g, const fmpz_t h, ulong exp); FLINT_DLL void fmpz_mul_si_tdiv_q_2exp(fmpz_t f, const fmpz_t g, slong x, ulong exp); FLINT_DLL void fmpz_fac_ui(fmpz_t f, ulong n); FLINT_DLL void fmpz_fib_ui(fmpz_t f, ulong n); FLINT_DLL void fmpz_bin_uiui(fmpz_t res, ulong n, ulong k); FLINT_DLL void _fmpz_rfac_ui(fmpz_t r, const fmpz_t x, ulong a, ulong b); FLINT_DLL void fmpz_rfac_ui(fmpz_t r, const fmpz_t x, ulong n); FLINT_DLL void fmpz_rfac_uiui(fmpz_t r, ulong x, ulong n); FLINT_DLL int fmpz_bit_pack(mp_ptr arr, flint_bitcnt_t shift, flint_bitcnt_t bits, const fmpz_t coeff, int negate, int borrow); FLINT_DLL int fmpz_bit_unpack(fmpz_t coeff, mp_srcptr arr, flint_bitcnt_t shift, flint_bitcnt_t bits, int negate, int borrow); FLINT_DLL void fmpz_bit_unpack_unsigned(fmpz_t coeff, mp_srcptr arr, flint_bitcnt_t shift, flint_bitcnt_t bits); /* crt ***********************************************************************/ FLINT_DLL 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); FLINT_DLL void fmpz_CRT_ui(fmpz_t out, const fmpz_t r1, const fmpz_t m1, ulong r2, ulong m2, int sign); FLINT_DLL void fmpz_CRT(fmpz_t out, const fmpz_t r1, const fmpz_t m1, fmpz_t r2, fmpz_t m2, int sign); 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); } /* 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]; FLINT_DLL void fmpz_multi_CRT_init(fmpz_multi_CRT_t CRT); FLINT_DLL int fmpz_multi_CRT_precompute(fmpz_multi_CRT_t CRT, const fmpz * moduli, slong len); FLINT_DLL void fmpz_multi_CRT_precomp(fmpz_t output, const fmpz_multi_CRT_t P, const fmpz * inputs, int sign); FLINT_DLL int fmpz_multi_CRT(fmpz_t output, const fmpz * moduli, const fmpz * values, slong len, int sign); FLINT_DLL void fmpz_multi_CRT_clear(fmpz_multi_CRT_t P); FLINT_DLL void _fmpz_multi_CRT_precomp(fmpz * outputs, const fmpz_multi_CRT_t P, const fmpz * inputs, int sign); /* deprecated versions that assume sign = 1 **********************************/ /* deprecated functions and types new functions and types 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 gone fmpz_multi_crt_precomp => fmpz_multi_CRT_precomp now with sign option fmpz_multi_crt_precomp_p gone fmpz_multi_crt => fmpz_multi_CRT now with sign option fmpz_multi_crt_clear => fmpz_multi_CRT_clear */ typedef fmpz_multi_CRT_struct fmpz_multi_crt_struct; typedef fmpz_multi_CRT_t fmpz_multi_crt_t; FLINT_DLL void fmpz_multi_crt_init(fmpz_multi_crt_t CRT); FLINT_DLL int fmpz_multi_crt_precompute(fmpz_multi_crt_t CRT, const fmpz * moduli, slong len); FLINT_DLL int fmpz_multi_crt_precompute_p(fmpz_multi_crt_t CRT, const fmpz * const * moduli, slong len); FLINT_DLL void fmpz_multi_crt_precomp(fmpz_t output, const fmpz_multi_crt_t P, const fmpz * inputs); FLINT_DLL void fmpz_multi_crt_precomp_p(fmpz_t output, const fmpz_multi_crt_t P, const fmpz * const * inputs); FLINT_DLL int fmpz_multi_crt(fmpz_t output, const fmpz * moduli, const fmpz * values, slong len); FLINT_DLL void fmpz_multi_crt_clear(fmpz_multi_crt_t P); FMPZ_INLINE slong _fmpz_multi_crt_local_size(const fmpz_multi_crt_t CRT) { return CRT->localsize; } FLINT_DLL void _fmpz_multi_crt_run(fmpz * outputs, const fmpz_multi_crt_t CRT, const fmpz * inputs); FLINT_DLL void _fmpz_multi_crt_run_p(fmpz * outputs, const fmpz_multi_crt_t CRT, const fmpz * const * inputs); /* 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]; FLINT_DLL void fmpz_multi_mod_init(fmpz_multi_mod_t P); FLINT_DLL void fmpz_multi_mod_clear(fmpz_multi_mod_t P); FLINT_DLL int fmpz_multi_mod_precompute(fmpz_multi_mod_t P, const fmpz * f, slong r); FLINT_DLL void fmpz_multi_mod_precomp(fmpz * outputs, const fmpz_multi_mod_t P, const fmpz_t input, int sign); FLINT_DLL void _fmpz_multi_mod_precomp(fmpz * outputs, const fmpz_multi_mod_t P, const fmpz_t input, int sign, fmpz * tmp); /* 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]; FLINT_DLL void fmpz_comb_temp_init(fmpz_comb_temp_t CT, const fmpz_comb_t C); FLINT_DLL void fmpz_comb_temp_clear(fmpz_comb_temp_t CT); FLINT_DLL void fmpz_comb_init(fmpz_comb_t C, mp_srcptr primes, slong num_primes); FLINT_DLL void fmpz_comb_clear(fmpz_comb_t C); FLINT_DLL void fmpz_multi_mod_ui(mp_limb_t * out, const fmpz_t in, const fmpz_comb_t C, fmpz_comb_temp_t CT); FLINT_DLL void fmpz_multi_CRT_ui(fmpz_t output, mp_srcptr residues, const fmpz_comb_t comb, fmpz_comb_temp_t temp, int sign); /*****************************************************************************/ FLINT_DLL mp_limb_t fmpz_abs_ubound_ui_2exp(slong * exp, const fmpz_t x, int bits); FLINT_DLL mp_limb_t fmpz_abs_lbound_ui_2exp(slong * exp, const fmpz_t x, int bits); FLINT_DLL void fmpz_lucas_chain(fmpz_t Vm, fmpz_t Vm1, const fmpz_t A, const fmpz_t m, const fmpz_t n); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int fmpz_is_probabprime_lucas(const fmpz_t n); FLINT_DLL int fmpz_is_probabprime_BPSW(const fmpz_t n); FLINT_DLL int fmpz_is_strong_probabprime(const fmpz_t n, const fmpz_t a); FLINT_DLL int fmpz_is_probabprime(const fmpz_t p); FLINT_DLL int fmpz_is_prime_pseudosquare(const fmpz_t n); FLINT_DLL void _fmpz_nm1_trial_factors(const fmpz_t n, mp_ptr pm1, slong * num_pm1, ulong limit); FLINT_DLL int fmpz_is_prime_pocklington(fmpz_t F, fmpz_t R, const fmpz_t n, mp_ptr pm1, slong num_pm1); FLINT_DLL void _fmpz_np1_trial_factors(const fmpz_t n, mp_ptr pp1, slong * num_pp1, ulong limit); FLINT_DLL int fmpz_is_prime_morrison(fmpz_t F, fmpz_t R, const fmpz_t n, mp_ptr pm1, slong num_pm1); FLINT_DLL int fmpz_is_prime(const fmpz_t p); FLINT_DLL int fmpz_divisor_in_residue_class_lenstra(fmpz_t fac, const fmpz_t n, const fmpz_t r, const fmpz_t s); FLINT_DLL void fmpz_nextprime(fmpz_t res, const fmpz_t n, int proved); /* Primorials */ FLINT_DLL void fmpz_primorial(fmpz_t res, ulong n); /* Multiplicative functions */ FLINT_DLL void fmpz_euler_phi(fmpz_t res, const fmpz_t n); FLINT_DLL int fmpz_moebius_mu(const fmpz_t n); FLINT_DLL void fmpz_divisor_sigma(fmpz_t res, const fmpz_t n, ulong k); /* Functions that should be in ulong extras */ FLINT_DLL ulong n_powmod2_fmpz_preinv(ulong a, const fmpz_t exp, ulong n, ulong ninv); FMPZ_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); } /* Inlines *******************************************************************/ FLINT_DLL fmpz * __new_fmpz(); FLINT_DLL void __free_fmpz(fmpz * f); FLINT_DLL void __fmpz_set_si(fmpz_t f, slong val); FLINT_DLL void __fmpz_set_ui(fmpz_t f, ulong val); FLINT_DLL void __fmpz_init(fmpz_t f); FLINT_DLL void __fmpz_init_set_ui(fmpz_t f, ulong g); FLINT_DLL void __fmpz_clear(fmpz_t f); FLINT_DLL int __fmpz_lt(fmpz_t f, fmpz_t g); FLINT_DLL int __fmpz_gt(fmpz_t f, fmpz_t g); FLINT_DLL int __fmpz_lte(fmpz_t f, fmpz_t g); FLINT_DLL int __fmpz_gte(fmpz_t f, fmpz_t g); FLINT_DLL int __fmpz_eq(fmpz_t f, fmpz_t g); FLINT_DLL int __fmpz_neq(fmpz_t f, fmpz_t g); FLINT_DLL void __fmpz_init_set(fmpz_t f, const fmpz_t g); FLINT_DLL void __fmpz_neg(fmpz_t f1, const fmpz_t f2); #ifdef __cplusplus } #endif #include "fmpz_factor.h" #endif flint2-2.8.4/fmpz/000077500000000000000000000000001414523752600137105ustar00rootroot00000000000000flint2-2.8.4/fmpz/CRT.c000066400000000000000000000037631414523752600145150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void _fmpz_CRT(fmpz_t out, const fmpz_t r1, const fmpz_t m1, fmpz_t r2, 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, fmpz_t r2, fmpz_t m2, int sign) { fmpz_t m1m2, c; fmpz_init(c); fmpz_mod(c, m1, m2); fmpz_invmod(c, c, m2); if (fmpz_is_zero(c)) { flint_printf("Exception (fmpz_CRT). m1 not invertible modulo m2.\n"); flint_abort(); } fmpz_init(m1m2); fmpz_mul(m1m2, m1, m2); _fmpz_CRT(out, r1, m1, r2, m2, m1m2, c, sign); fmpz_clear(m1m2); fmpz_clear(c); } flint2-2.8.4/fmpz/CRT_ui.c000066400000000000000000000032431414523752600152030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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; fmpz_init(tmp); if (fmpz_sgn(r1) < 0) fmpz_add(tmp, r1, m1); else fmpz_set(tmp, r1); r1mod = fmpz_fdiv_ui(tmp, m2); 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); if (c == 0) { flint_printf("Exception (fmpz_CRT_ui). m1 not invertible modulo m2.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz/abs.c000066400000000000000000000016261414523752600146260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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 *mpz_ptr = _fmpz_promote(f1); mpz_abs(mpz_ptr, COEFF_TO_PTR(*f2)); } } flint2-2.8.4/fmpz/abs_fits_ui.c000066400000000000000000000011321414523752600163400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz/abs_lbound_ui_2exp.c000066400000000000000000000032601414523752600176200ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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]; count_leading_zeros(shift, 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; } } count_leading_zeros(shift, m); e += FLINT_BITS - shift - bits; if (e >= 0) m >>= e; else m <<= (-e); *exp = e; return m; } flint2-2.8.4/fmpz/abs_ubound_ui_2exp.c000066400000000000000000000043251414523752600176340ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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]; count_leading_zeros(shift, 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 */ count_leading_zeros(shift, 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; } flint2-2.8.4/fmpz/add.c000066400000000000000000000035211414523752600146050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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 */ } } } flint2-2.8.4/fmpz/add_ui.c000066400000000000000000000023421414523752600153020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_add_ui(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 * mpz_ptr2 = _fmpz_promote(f); /* g is already large */ __mpz_struct * mpz_ptr = COEFF_TO_PTR(c); flint_mpz_add_ui(mpz_ptr2, mpz_ptr, x); _fmpz_demote_val(f); /* cancellation may have occurred */ } } flint2-2.8.4/fmpz/addmul.c000066400000000000000000000020561414523752600153250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_addmul(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1, c2; __mpz_struct * mpz_ptr; 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 */ mpz_ptr = _fmpz_promote_val(f); mpz_addmul(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* cancellation may have occurred */ } flint2-2.8.4/fmpz/addmul_si.c000066400000000000000000000024771414523752600160270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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); } } 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); } } flint2-2.8.4/fmpz/addmul_ui.c000066400000000000000000000051431414523752600160220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_addmul_ui(fmpz_t f, const fmpz_t g, ulong x) { fmpz c1, r; c1 = *g; if ((x == 0) || (c1 == 0)) /* product is zero */ return; r = *f; if (r == 0) { fmpz_mul_ui(f, g, x); /* we are adding product to 0 */ return; } if (x == UWORD(1)) /* special case, adding g*1 to f */ { fmpz_add(f, f, g); return; } if (c1 == UWORD(1)) /* special case, adding 1*x to f */ { fmpz_add_ui(f, f, x); return; } if (!COEFF_IS_MPZ(c1)) /* c1 is small */ { mp_limb_t prod[2]; ulong uc1 = FLINT_ABS(c1); umul_ppmm(prod[1], prod[0], uc1, x); /* compute product */ if (prod[1] == 0) /* product fits in one limb */ { if (c1 < WORD(0)) fmpz_sub_ui(f, f, prod[0]); else fmpz_add_ui(f, f, prod[0]); return; } else if ((prod[1] == 1) && (!COEFF_IS_MPZ(r)) && ((r ^ c1) < WORD(0))) { /* only chance at cancellation is if product is one bit past a limb and res is small and opposite sign to this product */ ulong ur = FLINT_ABS(r); if (ur > prod[0]) /* cancellation will occur */ { fmpz_set_ui(f, prod[0] - ur); if (r > WORD(0)) fmpz_neg(f, f); return; } } /* in all remaining cases res is either big already, or will be big in the end */ { __mpz_struct * mpz_ptr = _fmpz_promote_val(f); mpz_t temp; /* set up a temporary, cheap mpz_t to contain prod */ temp->_mp_d = prod; temp->_mp_size = (c1 < WORD(0) ? -2 : 2); mpz_add(mpz_ptr, mpz_ptr, temp); _fmpz_demote_val(f); /* cancellation may have occurred */ } } else /* c1 is large */ { __mpz_struct * mpz_ptr = _fmpz_promote_val(f); flint_mpz_addmul_ui(mpz_ptr, COEFF_TO_PTR(c1), x); _fmpz_demote_val(f); /* cancellation may have occurred */ } } flint2-2.8.4/fmpz/and.c000066400000000000000000000033301414523752600146150ustar00rootroot00000000000000/* Copyright (C) 2012 Thomas M. DuBuisson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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); } } } flint2-2.8.4/fmpz/bin_uiui.c000066400000000000000000000012671414523752600156650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.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); } flint2-2.8.4/fmpz/bit_pack.c000066400000000000000000000115411414523752600156320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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_n(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; } } flint2-2.8.4/fmpz/bit_unpack.c000066400000000000000000000131741414523752600162010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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 <= FLINT_BITS - 2) /* 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 * mpz_ptr; mp_limb_t * p; ulong l, b; mpz_ptr = _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(mpz_ptr, l); p = mpz_ptr->_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_n(p, p, l); if (!borrow) mpn_add_1(p, p, l, 1); /* normalise */ while (l && (p[l - 1] == (mp_limb_t) 0)) l--; mpz_ptr->_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--; mpz_ptr->_mp_size = l; sign = 0; } /* negate if required */ if (negate) mpz_neg(mpz_ptr, mpz_ptr); /* 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 <= FLINT_BITS - 2) /* 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 * mpz_ptr; mp_limb_t * p; ulong l, b; mpz_ptr = _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(mpz_ptr, l); p = mpz_ptr->_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--; mpz_ptr->_mp_size = l; /* coeff may fit in a small */ _fmpz_demote_val(coeff); } } flint2-2.8.4/fmpz/bits.c000066400000000000000000000012001414523752600150060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz/cdiv_q.c000066400000000000000000000041311414523752600153200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" 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_printf("Exception (fmpz_cdiv_q). Division by zero.\n"); flint_abort(); } 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 * mpz_ptr = _fmpz_promote(f); if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 > 0) /* h > 0 */ { flint_mpz_cdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); } else { flint_mpz_fdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), -c2); mpz_neg(mpz_ptr, mpz_ptr); } } else /* both are large */ { mpz_cdiv_q(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); } _fmpz_demote_val(f); /* division by h may result in small value */ } } flint2-2.8.4/fmpz/cdiv_q_2exp.c000066400000000000000000000016571414523752600162700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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, FLINT_BITS - 2))); } else /*g is large */ { __mpz_struct * mpz_ptr = _fmpz_promote(f); /* g is already large */ mpz_cdiv_q_2exp(mpz_ptr, COEFF_TO_PTR(d), exp); _fmpz_demote_val(f); /* division may make value small */ } } flint2-2.8.4/fmpz/cdiv_q_si.c000066400000000000000000000025701414523752600160200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" void fmpz_cdiv_q_si(fmpz_t f, const fmpz_t g, slong h) { fmpz c1 = *g; slong c2 = h; if (h == 0) { flint_printf("Exception (fmpz_cdiv_q_si). Division by zero.\n"); flint_abort(); } 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 *mpz_ptr = _fmpz_promote(f); if (c2 > 0) { flint_mpz_cdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); } else { flint_mpz_fdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), -(ulong) c2); mpz_neg(mpz_ptr, mpz_ptr); } _fmpz_demote_val(f); /* division by h may result in small value */ } } flint2-2.8.4/fmpz/cdiv_q_ui.c000066400000000000000000000024401414523752600160160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" void fmpz_cdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) { fmpz c1 = *g; ulong c2 = h; if (h == 0) { flint_printf("Exception: division by zero in fmpz_cdiv_q_ui\n"); flint_abort(); } 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 *mpz_ptr = _fmpz_promote(f); flint_mpz_cdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); _fmpz_demote_val(f); /* division by h may result in small value */ } } flint2-2.8.4/fmpz/cdiv_qr.c000066400000000000000000000054331414523752600155100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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_printf("Exception (fmpz_cdiv_q). Division by zero.\n"); flint_abort(); } 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 *mpz_ptr, *mpz_ptr2; _fmpz_promote(f); /* must not hang on to ptr whilst promoting s */ mpz_ptr2 = _fmpz_promote(s); mpz_ptr = COEFF_TO_PTR(*f); if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 > 0) /* h > 0 */ { flint_mpz_cdiv_qr_ui(mpz_ptr, mpz_ptr2, COEFF_TO_PTR(c1), c2); } else { flint_mpz_fdiv_qr_ui(mpz_ptr, mpz_ptr2, COEFF_TO_PTR(c1), -c2); mpz_neg(mpz_ptr, mpz_ptr); } } else /* both are large */ { mpz_cdiv_qr(mpz_ptr, mpz_ptr2, 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 */ } } flint2-2.8.4/fmpz/cdiv_r_2exp.c000066400000000000000000000026501414523752600162630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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 < (FLINT_BITS - 2) ? d & ((WORD(1) << exp) - 1) : d); } else { if (exp <= FLINT_BITS - 2) { fmpz_neg_ui(f, (-d) & ((WORD(1) << exp) - 1)); } else { __mpz_struct * mpz_ptr = _fmpz_promote(f); flint_mpz_set_ui(mpz_ptr, 1); mpz_mul_2exp(mpz_ptr, mpz_ptr, exp); flint_mpz_sub_ui(mpz_ptr, mpz_ptr, d); mpz_neg(mpz_ptr, mpz_ptr); } } } else /*g is large */ { __mpz_struct * mpz_ptr = _fmpz_promote(f); /* g is already large */ mpz_cdiv_r_2exp(mpz_ptr, COEFF_TO_PTR(d), exp); _fmpz_demote_val(f); /* division may make value small */ } } flint2-2.8.4/fmpz/cdiv_ui.c000066400000000000000000000017401414523752600155000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" ulong fmpz_cdiv_ui(const fmpz_t g, ulong h) { fmpz c1 = *g; ulong r; if (h == UWORD(0)) { flint_printf("Exception (fmpz_cdiv_ui). Division by 0.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpz/clear_readonly.c000066400000000000000000000012001414523752600170300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fmpz/clog.c000066400000000000000000000024171414523752600150040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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; } flint2-2.8.4/fmpz/clog_ui.c000066400000000000000000000027051414523752600155010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" 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; } flint2-2.8.4/fmpz/clrbit.c000066400000000000000000000013401414523752600153310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" void fmpz_clrbit(fmpz_t f, ulong i) { if (!COEFF_IS_MPZ(*f)) { if (i < FLINT_BITS - 2) { *f &= ~(WORD(1) << i); } /* i >= FLINT_BITS --> nop */ } else { __mpz_struct *ptr = COEFF_TO_PTR(*f); mpz_clrbit(ptr, i); _fmpz_demote_val(f); } } flint2-2.8.4/fmpz/cmp.c000066400000000000000000000022131414523752600146310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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)); } } flint2-2.8.4/fmpz/cmp2abs.c000066400000000000000000000041141414523752600154030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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)); } } } flint2-2.8.4/fmpz/cmp_si.c000066400000000000000000000013571414523752600153340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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); } flint2-2.8.4/fmpz/cmp_ui.c000066400000000000000000000014651414523752600153360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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); } flint2-2.8.4/fmpz/cmpabs.c000066400000000000000000000017351414523752600153270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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)); } } flint2-2.8.4/fmpz/comb_clear.c000066400000000000000000000016441414523752600161470ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz/comb_init.c000066400000000000000000000255471414523752600160340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "nmod_vec.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_fdiv_ui (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 8 #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_fdiv_ui(Mm->coeffs + i, C->crt_lu[i].mod.n); 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_fdiv_ui(M->coeffs + k - last, C->crt_lu[i].mod.n); 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"); } flint2-2.8.4/fmpz/combit.c000066400000000000000000000015461414523752600153370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" void fmpz_combit(fmpz_t f, ulong i) { if (!COEFF_IS_MPZ(*f)) { if (i < FLINT_BITS - 2) { *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); } } flint2-2.8.4/fmpz/complement.c000066400000000000000000000021561414523752600162230ustar00rootroot00000000000000/* Copyright (C) 2012 Thomas M. DuBuisson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" 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); } } } flint2-2.8.4/fmpz/deprecated.c000066400000000000000000000043531414523752600161610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" /* deprecated functions *****************************************************/ void fmpz_multi_crt_init(fmpz_multi_crt_t P) { fmpz_multi_CRT_init(P); } void fmpz_multi_crt_clear(fmpz_multi_crt_t P) { fmpz_multi_CRT_clear(P); } int fmpz_multi_crt_precompute( fmpz_multi_crt_t P, const fmpz * moduli, slong len) { return fmpz_multi_CRT_precompute(P, moduli, len); } int fmpz_multi_crt_precompute_p( fmpz_multi_crt_t P, const fmpz * const * moduli, slong len) { int success; slong i; fmpz * m = FLINT_ARRAY_ALLOC(len, fmpz); for (i = 0; i < len; i++) m[i] = *moduli[i]; success = fmpz_multi_CRT_precompute(P, m, len); flint_free(m); return success; } void fmpz_multi_crt_precomp( fmpz_t output, const fmpz_multi_crt_t P, const fmpz * inputs) { fmpz_multi_CRT_precomp(output, P, inputs, 1); } void fmpz_multi_crt_precomp_p( fmpz_t output, const fmpz_multi_crt_t P, const fmpz * const * inputs) { slong i; fmpz * ins = FLINT_ARRAY_ALLOC(P->moduli_count, fmpz); for (i = 0; i < P->moduli_count; i++) ins[i] = *inputs[i]; fmpz_multi_CRT_precomp(output, P, ins, 1); flint_free(ins); } int fmpz_multi_crt( fmpz_t output, const fmpz * moduli, const fmpz * values, slong len) { return fmpz_multi_CRT(output, moduli, values, len, 1); } void _fmpz_multi_crt_run( fmpz * outputs, const fmpz_multi_crt_t P, const fmpz * inputs) { _fmpz_multi_CRT_precomp(outputs, P, inputs, 1); } void _fmpz_multi_crt_run_p( fmpz * outputs, const fmpz_multi_crt_t P, const fmpz * const * inputs) { slong i; fmpz * ins = FLINT_ARRAY_ALLOC(P->moduli_count, fmpz); for (i = 0; i < P->moduli_count; i++) ins[i] = *inputs[i]; _fmpz_multi_CRT_precomp(outputs, P, ins, 1); flint_free(ins); } flint2-2.8.4/fmpz/divexact.c000066400000000000000000000032231414523752600156630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.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_printf("Exception (fmpz_divexact). Division by zero.\n"); flint_abort(); } 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 * mpz_ptr = _fmpz_promote(f); if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 > 0) /* h > 0 */ { flint_mpz_divexact_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); _fmpz_demote_val(f); /* division by h may result in small value */ } else { flint_mpz_divexact_ui(mpz_ptr, COEFF_TO_PTR(c1), -c2); _fmpz_demote_val(f); /* division by h may result in small value */ fmpz_neg(f, f); } } else /* both are large */ { mpz_divexact(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* division by h may result in small value */ } } } flint2-2.8.4/fmpz/divexact_si.c000066400000000000000000000024501414523752600163570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_divexact_si(fmpz_t f, const fmpz_t g, slong h) { fmpz c1 = *g; if (h == 0) { flint_printf("Exception (fmpz_divexact_si). Division by zero.\n"); flint_abort(); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { fmpz_set_si(f, c1 / h); } else /* g is large */ { __mpz_struct * mpz_ptr = _fmpz_promote(f); if (h > 0) { flint_mpz_divexact_ui(mpz_ptr, COEFF_TO_PTR(c1), h); _fmpz_demote_val(f); /* division by h may result in small value */ } else { flint_mpz_divexact_ui(mpz_ptr, COEFF_TO_PTR(c1), -h); _fmpz_demote_val(f); /* division by h may result in small value */ fmpz_neg(f, f); } } } flint2-2.8.4/fmpz/divexact_ui.c000066400000000000000000000020621414523752600163600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_divexact_ui(fmpz_t f, const fmpz_t g, ulong h) { fmpz c1 = *g; if (h == 0) { flint_printf("Exception (fmpz_divexact_ui). Division by zero.\n"); flint_abort(); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { fmpz_set_si(f, c1 / (slong) h); } else /* g is large */ { __mpz_struct * mpz_ptr = _fmpz_promote(f); flint_mpz_divexact_ui(mpz_ptr, COEFF_TO_PTR(c1), h); _fmpz_demote_val(f); /* division by h may result in small value */ } } flint2-2.8.4/fmpz/divides.c000066400000000000000000000042071414523752600155060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.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 *mpz_ptr = _fmpz_promote(q); if (!COEFF_IS_MPZ(c2)) /* h is small */ { mp_limb_t r; if (c2 < 0) { c2 = -c2; negate ^= 1; } r = flint_mpz_tdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); res = (r == 0); } else /* both are large */ { mpz_t r; mpz_ptr = _fmpz_promote(q); mpz_init(r); mpz_tdiv_qr(mpz_ptr, r, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); res = mpz_sgn(r) == 0; mpz_clear(r); } if (!res) mpz_set_ui(mpz_ptr, 0); _fmpz_demote_val(q); if (negate) fmpz_neg(q, q); return res; } } flint2-2.8.4/fmpz/divides_mod_list.c000066400000000000000000000027261414523752600174040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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); } flint2-2.8.4/fmpz/divisible.c000066400000000000000000000020761414523752600160330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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)); } } } flint2-2.8.4/fmpz/divisible_si.c000066400000000000000000000013371414523752600165250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int fmpz_divisible_si(const fmpz_t x, slong p) { fmpz y = *x; if (y == WORD(0)) { return 1; } if (!COEFF_IS_MPZ(y)) { return !(y % p); } else { return flint_mpz_divisible_ui_p(COEFF_TO_PTR(y), p); } } flint2-2.8.4/fmpz/divisor_in_residue_class_lenstra.c000066400000000000000000000126741414523752600226700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #define ulong mp_limb_t #include #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; } flint2-2.8.4/fmpz/divisor_sigma.c000066400000000000000000000027301414523752600167150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" void fmpz_factor_divisor_sigma(fmpz_t res, const fmpz_factor_t fac, ulong k) { 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, const fmpz_t n, ulong k) { 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, fac, k); fmpz_factor_clear(fac); } flint2-2.8.4/fmpz/dlog.c000066400000000000000000000016701414523752600150050ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" double fmpz_dlog(const fmpz_t x) { if (!COEFF_IS_MPZ(*x)) { return log(*x); } else { double s; #if defined(__MPIR_RELEASE) && __MPIR_RELEASE > 30000 slong e = mpz_get_2exp_d(&s, COEFF_TO_PTR(*x)); #else #if defined(__MPIR_VERSION) && __MPIR_VERSION<=2 slong e; #else long e; #endif s = mpz_get_d_2exp(&e, COEFF_TO_PTR(*x)); #endif return log(s) + e * 0.69314718055994530942; } } flint2-2.8.4/fmpz/equal.c000066400000000000000000000014361414523752600151670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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); } flint2-2.8.4/fmpz/equal_si.c000066400000000000000000000011571414523752600156620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "ulong_extras.h" 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); } flint2-2.8.4/fmpz/equal_ui.c000066400000000000000000000012331414523752600156570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "ulong_extras.h" 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); } flint2-2.8.4/fmpz/euler_phi.c000066400000000000000000000022661414523752600160360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.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); } flint2-2.8.4/fmpz/fac_ui.c000066400000000000000000000023071414523752600153040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.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); } flint2-2.8.4/fmpz/fdiv_q.c000066400000000000000000000041321414523752600153240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" 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_printf("Exception (fmpz_fdiv_q). Division by zero.\n"); flint_abort(); } 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 *mpz_ptr = _fmpz_promote(f); if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 > 0) /* h > 0 */ { flint_mpz_fdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); } else { flint_mpz_cdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), -c2); mpz_neg(mpz_ptr, mpz_ptr); } } else /* both are large */ { mpz_fdiv_q(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); } _fmpz_demote_val(f); /* division by h may result in small value */ } } flint2-2.8.4/fmpz/fdiv_q_2exp.c000066400000000000000000000015761414523752600162730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_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, FLINT_BITS - 2)); } else /*g is large */ { __mpz_struct * mpz_ptr = _fmpz_promote(f); /* g is already large */ mpz_fdiv_q_2exp(mpz_ptr, COEFF_TO_PTR(d), exp); _fmpz_demote_val(f); /* division may make value small */ } } flint2-2.8.4/fmpz/fdiv_q_si.c000066400000000000000000000026141414523752600160220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_fdiv_q_si(fmpz_t f, const fmpz_t g, slong h) { fmpz c1 = *g; slong c2 = h; if (h == 0) { flint_printf("Exception (fmpq_fdiv_q_si). Division by zero.\n"); flint_abort(); } 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 *mpz_ptr = _fmpz_promote(f); if (c2 > 0) { flint_mpz_fdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); } else { flint_mpz_cdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), -(ulong) c2); mpz_neg(mpz_ptr, mpz_ptr); } _fmpz_demote_val(f); /* division by h may result in small value */ } } flint2-2.8.4/fmpz/fdiv_q_ui.c000066400000000000000000000024611414523752600160240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" void fmpz_fdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) { fmpz c1 = *g; ulong c2 = h; if (h == 0) { flint_printf("Exception (fmpz_fdiv_q_ui). Division by zero.\n"); flint_abort(); } 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 *mpz_ptr = _fmpz_promote(f); flint_mpz_fdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); _fmpz_demote_val(f); /* division by h may result in small value */ } } flint2-2.8.4/fmpz/fdiv_qr.c000066400000000000000000000055141414523752600155130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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_printf("Exception (fmpz_fdiv_q). Division by zero.\n"); flint_abort(); } 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 *mpz_ptr, *mpz_ptr2; _fmpz_promote(f); /* must not hang on to ptr whilst promoting s */ mpz_ptr2 = _fmpz_promote(s); mpz_ptr = COEFF_TO_PTR(*f); if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 > 0) /* h > 0 */ { flint_mpz_fdiv_qr_ui(mpz_ptr, mpz_ptr2, COEFF_TO_PTR(c1), c2); } else { flint_mpz_cdiv_qr_ui(mpz_ptr, mpz_ptr2, COEFF_TO_PTR(c1), -c2); mpz_neg(mpz_ptr, mpz_ptr); } } else /* both are large */ { mpz_fdiv_qr(mpz_ptr, mpz_ptr2, 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 */ } } flint2-2.8.4/fmpz/fdiv_qr_preinvn.c000066400000000000000000000121361414523752600172520ustar00rootroot00000000000000/* Copyright 1991, 1993-1996, 2000, 2001, 2005 Free Software Foundation, Inc. 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "longlong.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" /* 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_printf("Exception (fmpz_fdiv_q). Division by zero.\n"); flint_abort(); } 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 *mpz_ptr, *mpz_ptr2; 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 */ mpz_ptr2 = _fmpz_promote(s); mpz_ptr = COEFF_TO_PTR(*f); _mpz_fdiv_qr_preinvn(mpz_ptr, mpz_ptr2, 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 */ } } } flint2-2.8.4/fmpz/fdiv_r.c000066400000000000000000000043441414523752600153320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" 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_printf("Exception (fmpz_fdiv_r). Division by zero.\n"); flint_abort(); } 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 * mpz_ptr = _fmpz_promote(f); if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 > 0) /* h > 0 */ { flint_mpz_fdiv_r_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); } else { flint_mpz_cdiv_r_ui(mpz_ptr, COEFF_TO_PTR(c1), -c2); } } else /* both are large */ { mpz_fdiv_r(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); } _fmpz_demote_val(f); /* division by h may result in small value */ } } flint2-2.8.4/fmpz/fdiv_r_2exp.c000066400000000000000000000026171414523752600162710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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 < (FLINT_BITS - 2) ? d & ((WORD(1) << exp) - 1) : d); } else { if (exp <= FLINT_BITS - 2) { fmpz_set_ui(f, d & ((WORD(1) << exp) - 1)); } else { __mpz_struct * mpz_ptr = _fmpz_promote(f); flint_mpz_set_ui(mpz_ptr, 1); mpz_mul_2exp(mpz_ptr, mpz_ptr, exp); flint_mpz_sub_ui(mpz_ptr, mpz_ptr, -d); } } } else /*g is large */ { __mpz_struct * mpz_ptr = _fmpz_promote(f); /* g is already large */ mpz_fdiv_r_2exp(mpz_ptr, COEFF_TO_PTR(d), exp); _fmpz_demote_val(f); /* division may make value small */ } } flint2-2.8.4/fmpz/fdiv_ui.c000066400000000000000000000021301414523752600154750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" ulong fmpz_fdiv_ui(const fmpz_t g, ulong h) { fmpz c1 = *g; ulong r; if (h == UWORD(0)) { flint_printf("Exception (fmpz_fdiv_ui). Division by 0.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpz/fib_ui.c000066400000000000000000000044061414523752600153150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #if FLINT64 #define NUM_SMALL_FIB 94 #else #define NUM_SMALL_FIB 48 #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 flint_mpz_fib_ui(_fmpz_promote(f), n); } flint2-2.8.4/fmpz/fits_si.c000066400000000000000000000043371414523752600155230ustar00rootroot00000000000000/* 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 #include "flint.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 2.1 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 } } flint2-2.8.4/fmpz/flog.c000066400000000000000000000024271414523752600150100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.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; } flint2-2.8.4/fmpz/flog_ui.c000066400000000000000000000026231414523752600155030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" 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; } flint2-2.8.4/fmpz/fmma.c000066400000000000000000000027351414523752600150030ustar00rootroot00000000000000/* 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 2.1 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 (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); } } flint2-2.8.4/fmpz/fmms.c000066400000000000000000000030211414523752600150120ustar00rootroot00000000000000/* 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 2.1 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 (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 (!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 (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); } } flint2-2.8.4/fmpz/fprint.c000066400000000000000000000011701414523752600153550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz.h" int fmpz_fprint(FILE * file, const fmpz_t x) { if (!COEFF_IS_MPZ(*x)) return flint_fprintf(file, "%wd", *x); else return (int) mpz_out_str(file, 10, COEFF_TO_PTR(*x)); } flint2-2.8.4/fmpz/fread.c000066400000000000000000000012621414523752600151360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" 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; } flint2-2.8.4/fmpz/gcd.c000066400000000000000000000032521414523752600146130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" ulong z_gcd(slong a, slong b) { ulong ua = FLINT_ABS(a); ulong ub = FLINT_ABS(b); return n_gcd(ua, ub); } void fmpz_gcd(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(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(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(c2, c1d)); } else /* g and h are both large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); /* aliasing fine as g, h already large */ mpz_gcd(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* gcd may be small */ } } } flint2-2.8.4/fmpz/gcd3.c000066400000000000000000000065711414523752600147050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.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); } 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)) { c = n_gcd(FLINT_ABS(*a), c); if (c != 1) c = _fmpz_gcd_small(b, c); } else { c = _fmpz_gcd_small(b, c); if (c != 1) c = _fmpz_gcd_big_small(a, c); } fmpz_set_ui(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); } } flint2-2.8.4/fmpz/gcdinv.c000066400000000000000000000033671414523752600153370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fmpz/get_d.c000066400000000000000000000021321414523752600151340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #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)); } flint2-2.8.4/fmpz/get_d_2exp.c000066400000000000000000000025601414523752600160770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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 { #if defined(__MPIR_VERSION) && __MPIR_VERSION <= 2 return mpz_get_d_2exp(exp, COEFF_TO_PTR(d)); #elif defined(__MPIR_RELEASE) && __MPIR_RELEASE > 30000 double m; *exp = mpz_get_2exp_d(&m, COEFF_TO_PTR(d)); return m; #else long exp2; double m = mpz_get_d_2exp(&exp2, COEFF_TO_PTR(d)); *exp = exp2; return m; #endif } } flint2-2.8.4/fmpz/get_mpf.c000066400000000000000000000013101414523752600154700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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 */ } flint2-2.8.4/fmpz/get_mpfr.c000066400000000000000000000022011414523752600156520ustar00rootroot00000000000000/* 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 2.1 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 #if defined( _WIN64) && defined( _MSC_MPIR_VERSION ) && __MPIR_RELEASE >= 20700 # if defined( _MSC_VER ) && _MSC_VER >= 1600 # include # include # define mpfr_set_si mpfr_set_sj # endif #endif #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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 */ } flint2-2.8.4/fmpz/get_mpn.c000066400000000000000000000015501414523752600155060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" 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; } } flint2-2.8.4/fmpz/get_mpz.c000066400000000000000000000012441414523752600155220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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 */ } flint2-2.8.4/fmpz/get_nmod.c000066400000000000000000000022751414523752600156560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" 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); } flint2-2.8.4/fmpz/get_si.c000066400000000000000000000010761414523752600153320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" slong fmpz_get_si(const fmpz_t f) { return (!COEFF_IS_MPZ(*f) ? *f : flint_mpz_get_si(COEFF_TO_PTR(*f))); } flint2-2.8.4/fmpz/get_signed_ui_array.c000066400000000000000000000016431414523752600200630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" 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); } flint2-2.8.4/fmpz/get_signed_uiui.c000066400000000000000000000016161414523752600172230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" 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; } flint2-2.8.4/fmpz/get_str.c000066400000000000000000000017111414523752600155230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" char * fmpz_get_str(char * str, int b, const fmpz_t f) { if (!COEFF_IS_MPZ(*f)) { mpz_t z; flint_mpz_init_set_si(z, *f); if (!str) { str = flint_malloc(mpz_sizeinbase (z, b) + 2); } str = mpz_get_str(str, b, z); mpz_clear(z); } else { if (!str) { str = flint_malloc(mpz_sizeinbase (COEFF_TO_PTR(*f), b) + 2); } str = mpz_get_str(str, b, COEFF_TO_PTR(*f)); } return str; } flint2-2.8.4/fmpz/get_ui.c000066400000000000000000000012711414523752600153310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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)); } flint2-2.8.4/fmpz/get_ui_array.c000066400000000000000000000020471414523752600165310ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" /* 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); } flint2-2.8.4/fmpz/init2.c000066400000000000000000000012731414523752600151040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_init2(fmpz_t f, ulong limbs) { if (limbs) { __mpz_struct *mpz_ptr = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mpz_ptr); _mpz_realloc(mpz_ptr, limbs); } else { (*f) = WORD(0); } } flint2-2.8.4/fmpz/init_set_readonly.c000066400000000000000000000014541414523752600175730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fmpz/inlines.c000066400000000000000000000054241414523752600155220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" fmpz * __new_fmpz() { return flint_calloc(sizeof(fmpz), 1); } void __free_fmpz(fmpz * f) { _fmpz_demote(f); flint_free(f); } void __fmpz_set_si(fmpz_t f, slong val) { if (val < COEFF_MIN || val > COEFF_MAX) /* val is large */ { __mpz_struct *mpz_coeff = _fmpz_promote(f); flint_mpz_set_si(mpz_coeff, val); } else { _fmpz_demote(f); *f = val; /* val is small */ } } void __fmpz_set_ui(fmpz_t f, ulong val) { if (val > COEFF_MAX) /* val is large */ { __mpz_struct *mpz_coeff = _fmpz_promote(f); flint_mpz_set_ui(mpz_coeff, val); } else { _fmpz_demote(f); *f = val; /* val is small */ } } void __fmpz_init(fmpz_t f) { (*f) = WORD(0); } void __fmpz_init_set_ui(fmpz_t f, ulong g) { if (g <= COEFF_MAX) { *f = g; } else { __mpz_struct *ptr; ptr = _fmpz_new_mpz(); *f = PTR_TO_COEFF(ptr); flint_mpz_set_ui(ptr, g); } } void __fmpz_clear(fmpz_t f) { _fmpz_demote(f); } int __fmpz_lt(fmpz_t f, fmpz_t g) { return fmpz_cmp(f, g) < 0; } int __fmpz_gt(fmpz_t f, fmpz_t g) { return fmpz_cmp(f, g) > 0; } int __fmpz_lte(fmpz_t f, fmpz_t g) { return fmpz_cmp(f, g) <= 0; } int __fmpz_gte(fmpz_t f, fmpz_t g) { return fmpz_cmp(f, g) >= 0; } int __fmpz_eq(fmpz_t f, fmpz_t g) { return fmpz_cmp(f, g) == 0; } int __fmpz_neq(fmpz_t f, fmpz_t g) { return fmpz_cmp(f, g) != 0; } void __fmpz_init_set(fmpz_t f, const fmpz_t g) { if (!COEFF_IS_MPZ(*g)) { *f = *g; } else { __mpz_struct *ptr; ptr = _fmpz_new_mpz(); *f = PTR_TO_COEFF(ptr); mpz_set(ptr, COEFF_TO_PTR(*g)); } } 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_ptr = _fmpz_promote(f1); mpz_neg(mpz_ptr, COEFF_TO_PTR(*f2)); } } flint2-2.8.4/fmpz/inp_raw.c000066400000000000000000000011241414523752600155110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" 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; } flint2-2.8.4/fmpz/invmod.c000066400000000000000000000061021414523752600153470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.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_printf("Exception (fmpz_invmod). Division by zero.\n"); flint_abort(); } 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 *mpz_ptr; 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; } mpz_ptr = _fmpz_promote(f); val = mpz_invert(mpz_ptr, &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 *mpz_ptr = _fmpz_promote(f); val = mpz_invert(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* reduction mod h may result in small value */ return val; } } } flint2-2.8.4/fmpz/is_perfect_power.c000066400000000000000000000164151414523752600174220ustar00rootroot00000000000000/* 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 #define ulong ulongxx /* interferes with system includes */ #include /* for NULL */ #undef ulong #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 higest 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 { unsigned long int 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; } } flint2-2.8.4/fmpz/is_prime.c000066400000000000000000000223121414523752600156630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #include #undef ulong #define ulong mp_limb_t #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "aprcl.h" #include "mpn_extras.h" int fmpz_is_prime(const fmpz_t n) { 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 (fmpz_cmp_ui(n, 1) <= 0) return 0; if (fmpz_abs_fits_ui(n)) return n_is_prime(fmpz_get_ui(n)); if (fmpz_is_even(n)) return 0; if (flint_mpn_factor_trial(COEFF_TO_PTR(*n)->_mp_d, COEFF_TO_PTR(*n)->_mp_size, 1, fmpz_bits(n))) return 0; /* todo: use fmpz_is_perfect_power? */ if (fmpz_is_square(n)) return 0; /* 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_printf("Exception in fmpz_is_prime: failed to prove "); fmpz_print(n); flint_printf(" prime or composite\n"); flint_abort(); } fmpz_clear(F1); fmpz_clear(R); fmpz_clear(Fsqr); fmpz_clear(Fcub); return res; } flint2-2.8.4/fmpz/is_prime_morrison.c000066400000000000000000000122331414523752600176140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #include #undef ulong #define ulong mp_limb_t #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.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; } flint2-2.8.4/fmpz/is_prime_pocklington.c000066400000000000000000000105421414523752600202740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #include #undef ulong #define ulong mp_limb_t #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.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; } flint2-2.8.4/fmpz/is_prime_pseudosquare.c000066400000000000000000000212121414523752600204610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #define ulong mp_limb_t #include #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_printf("Exception (fmpz_set_pseudosquare). Index too large.\n"); flint_abort(); } } 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; ret = -1; /* silence compiler warning (not set when aborting) */ 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_printf("Whoah, "); fmpz_print(n); flint_printf("is a probable prime, but not prime, please report!!\n"); flint_abort(); } 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_printf("Whoah, "); fmpz_print(n); flint_printf("is a probable prime, but not prime, please report!!\n"); flint_abort(); } } flint_printf("Whoah, "); fmpz_print(n); flint_printf("is a probable prime, but not prime, please report!!\n"); flint_abort(); } cleanup: fmpz_clear(NB); fmpz_clear(f); fmpz_clear(exp); fmpz_clear(mod); fmpz_clear(nm1); return ret; } flint2-2.8.4/fmpz/is_probabprime.c000066400000000000000000000024661414523752600170610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "mpn_extras.h" int fmpz_is_probabprime(const fmpz_t n) { if (!COEFF_IS_MPZ(*n)) { slong v = *n; if (v <= 1) return 0; return n_is_probabprime(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_probabprime(d[0]); 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; if (fmpz_is_square(n)) return 0; return fmpz_is_probabprime_BPSW(n); } } flint2-2.8.4/fmpz/is_probabprime_BPSW.c000066400000000000000000000015741414523752600177130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #include #include #undef ulong #define ulong mp_limb_t #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; } flint2-2.8.4/fmpz/is_probabprime_lucas.c000066400000000000000000000042241414523752600202420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #include #include #undef ulong #define ulong mp_limb_t #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; } flint2-2.8.4/fmpz/is_square.c000066400000000000000000000013011414523752600160420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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)); } flint2-2.8.4/fmpz/is_strong_probabprime.c000066400000000000000000000030341414523752600204450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #include #include #undef ulong #define ulong mp_limb_t #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; } flint2-2.8.4/fmpz/jacobi.c000066400000000000000000000017641414523752600153130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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; } flint2-2.8.4/fmpz/kronecker.c000066400000000000000000000017101414523752600160360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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; } flint2-2.8.4/fmpz/lcm.c000066400000000000000000000015771414523752600146410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz/link/000077500000000000000000000000001414523752600146455ustar00rootroot00000000000000flint2-2.8.4/fmpz/link/fmpz_gc.c000066400000000000000000000105151414523752600164400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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 * mpz_ptr = _fmpz_new_mpz(); (*f) = PTR_TO_COEFF(mpz_ptr); return mpz_ptr; } 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 * mpz_ptr = _fmpz_new_mpz(); (*f) = PTR_TO_COEFF(mpz_ptr); flint_mpz_set_si(mpz_ptr, c); return mpz_ptr; } else /* f is large already, just return the pointer */ return COEFF_TO_PTR(c); } void _fmpz_demote_val(fmpz_t f) { __mpz_struct * mpz_ptr = COEFF_TO_PTR(*f); int size = mpz_ptr->_mp_size; if (size == 1 || size == -1) { ulong uval = mpz_ptr->_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); } } flint2-2.8.4/fmpz/link/fmpz_reentrant.c000066400000000000000000000045541414523752600200570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" __mpz_struct * _fmpz_new_mpz(void) { __mpz_struct * mpz_ptr = (__mpz_struct *) flint_malloc(sizeof(__mpz_struct)); mpz_init2(mpz_ptr, 2*FLINT_BITS); return mpz_ptr; } 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 * mpz_ptr = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mpz_ptr); return mpz_ptr; } 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 * mpz_ptr = _fmpz_new_mpz(); *f = PTR_TO_COEFF(mpz_ptr); flint_mpz_set_si(mpz_ptr, c); return mpz_ptr; } else /* f is large already, just return the pointer */ return COEFF_TO_PTR(*f); } void _fmpz_demote_val(fmpz_t f) { __mpz_struct * mpz_ptr = COEFF_TO_PTR(*f); int size = mpz_ptr->_mp_size; if (!(((unsigned int) size + 1U) & ~2U)) /* size +-1 */ { ulong uval = mpz_ptr->_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 * mpz_ptr = (__mpz_struct *) flint_malloc(sizeof(__mpz_struct)); *f = PTR_TO_COEFF(mpz_ptr); *mpz_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); } } flint2-2.8.4/fmpz/link/fmpz_single.c000066400000000000000000000164611414523752600173360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef __unix__ #include /* sysconf */ #endif #if defined(_WIN32) || defined(WIN32) #include /* GetSytemInfo */ #endif #if defined(_MSC_VER) && FLINT_USES_PTHREAD #include #endif #include #include #include "flint.h" #include "fmpz.h" /* 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() { #if defined(__unix__) return sysconf(_SC_PAGESIZE); #elif defined(_WIN32) || defined(WIN32) SYSTEM_INFO si; GetSystemInfo(&si); return si.dwPageSize; #else return 4096; #endif } 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 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) && FLINT_USES_PTHREAD new_count = __atomic_add_fetch(&(header_ptr->count), 1, __ATOMIC_SEQ_CST); #elif defined(_MSC_VER) && FLINT_USES_PTHREAD new_count = atomic_add_fetch(&(header_ptr->count), 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 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) && FLINT_USES_PTHREAD new_count = __atomic_add_fetch(&(ptr->count), 1, __ATOMIC_SEQ_CST); #elif defined(_MSC_VER) && FLINT_USES_PTHREAD new_count = atomic_add_fetch(&(ptr->count), 1); #else /* may be a very small leak with pthreads */ 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 * mpz_ptr = _fmpz_new_mpz(); (*f) = PTR_TO_COEFF(mpz_ptr); return mpz_ptr; } 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 * mpz_ptr = _fmpz_new_mpz(); (*f) = PTR_TO_COEFF(mpz_ptr); flint_mpz_set_si(mpz_ptr, c); return mpz_ptr; } else /* f is large already, just return the pointer */ return COEFF_TO_PTR(c); } void _fmpz_demote_val(fmpz_t f) { __mpz_struct * mpz_ptr = COEFF_TO_PTR(*f); int size = mpz_ptr->_mp_size; if (size == 1 || size == -1) { ulong uval = mpz_ptr->_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); } } flint2-2.8.4/fmpz/lucas_chain.c000066400000000000000000000125471414523752600163360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #include #undef ulong #define ulong mp_limb_t #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); } flint2-2.8.4/fmpz/mod.c000066400000000000000000000035751414523752600146450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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 */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); mpz_mod(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* reduction mod h may result in small value */ } } } flint2-2.8.4/fmpz/mod_ui.c000066400000000000000000000011561414523752600153330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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; } flint2-2.8.4/fmpz/moebius_mu.c000066400000000000000000000015651414523752600162270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.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; } flint2-2.8.4/fmpz/mpz_clear_readonly.c000066400000000000000000000010061414523752600177220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" void flint_mpz_clear_readonly(mpz_t z) { _fmpz_clear_readonly_mpz(z); } flint2-2.8.4/fmpz/mpz_init_set_readonly.c000066400000000000000000000011711414523752600204550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" 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); } } flint2-2.8.4/fmpz/mul.c000066400000000000000000000022431414523752600146520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_mul(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1, c2; __mpz_struct *mpz_ptr; 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; } mpz_ptr = _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(mpz_ptr, COEFF_TO_PTR(c1), c2); else /* c1 and c2 are large */ mpz_mul(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); } flint2-2.8.4/fmpz/mul_2exp.c000066400000000000000000000024471414523752600156160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_mul_2exp(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 <= FLINT_BITS - 2) /* result will fit in small */ { fmpz_set_si(f, d << exp); } else /* result is large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); /* g is saved */ flint_mpz_set_si(mpz_ptr, d); mpz_mul_2exp(mpz_ptr, mpz_ptr, exp); } } else /* g is large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); /* g is already large */ mpz_mul_2exp(mpz_ptr, COEFF_TO_PTR(d), exp); } } flint2-2.8.4/fmpz/mul_si.c000066400000000000000000000023361414523752600153500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_mul_si(fmpz_t f, const fmpz_t g, slong x) { 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 = FLINT_ABS(c2); mp_limb_t ux = FLINT_ABS(x); /* unsigned limb by limb multiply (assembly for most CPU's) */ umul_ppmm(prod[1], prod[0], uc2, ux); if ((c2 ^ x) < WORD(0)) fmpz_neg_uiui(f, prod[1], prod[0]); else fmpz_set_uiui(f, prod[1], prod[0]); } else /* c2 is large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); /* ok without val as if aliased both are large */ flint_mpz_mul_si(mpz_ptr, COEFF_TO_PTR(c2), x); } } flint2-2.8.4/fmpz/mul_si_tdiv_q_2exp.c000066400000000000000000000041301414523752600176460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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 *mpz_ptr = _fmpz_promote(f); /* two limbs, least significant first, native endian, no nails, stored in prod */ mpz_import(mpz_ptr, 2, -1, sizeof(mp_limb_t), 0, 0, prod); if ((c2 ^ x) < WORD(0)) mpz_neg(mpz_ptr, mpz_ptr); } } else /* c2 is large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); /* ok without val as if aliased both are large */ flint_mpz_mul_si(mpz_ptr, COEFF_TO_PTR(c2), x); mpz_tdiv_q_2exp(mpz_ptr, mpz_ptr, exp); _fmpz_demote_val(f); /* value may be small */ } } flint2-2.8.4/fmpz/mul_tdiv_q_2exp.c000066400000000000000000000025371414523752600171640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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 *mpz_ptr; 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; } mpz_ptr = _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(mpz_ptr, COEFF_TO_PTR(c1), c2); else /* c1 and c2 are large */ mpz_mul(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); mpz_tdiv_q_2exp(mpz_ptr, mpz_ptr, exp); _fmpz_demote_val(f); /* division may make value small */ } flint2-2.8.4/fmpz/mul_ui.c000066400000000000000000000022751414523752600153540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_mul_ui(fmpz_t f, const fmpz_t g, ulong x) { 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 = FLINT_ABS(c2); /* unsigned limb by limb multiply (assembly for most CPU's) */ umul_ppmm(prod[1], prod[0], uc2, x); if (c2 < WORD(0)) fmpz_neg_uiui(f, prod[1], prod[0]); else fmpz_set_uiui(f, prod[1], prod[0]); } else /* c2 is large */ { /* Promote without val as if aliased both are large */ __mpz_struct *mpz_ptr = _fmpz_promote(f); flint_mpz_mul_ui(mpz_ptr, COEFF_TO_PTR(c2), x); } } flint2-2.8.4/fmpz/multi_CRT.c000066400000000000000000000021201414523752600157110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" 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; } flint2-2.8.4/fmpz/multi_CRT_clear.c000066400000000000000000000014261414523752600170670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" 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); } flint2-2.8.4/fmpz/multi_CRT_init.c000066400000000000000000000013111414523752600167350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz/multi_CRT_precomp.c000066400000000000000000000045461414523752600174540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" 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; } flint2-2.8.4/fmpz/multi_CRT_precompute.c000066400000000000000000000141641414523752600201670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" 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); SLONG_SWAP(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); SLONG_SWAP(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); SLONG_SWAP(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; } flint2-2.8.4/fmpz/multi_CRT_ui.c000066400000000000000000000076701414523752600164250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" #include "nmod_vec.h" #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); } flint2-2.8.4/fmpz/multi_mod_clear.c000066400000000000000000000012301414523752600172070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz/multi_mod_init.c000066400000000000000000000011451414523752600170710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz/multi_mod_precomp.c000066400000000000000000000046161414523752600176010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" 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 propogate 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; } flint2-2.8.4/fmpz/multi_mod_precompute.c000066400000000000000000000111111414523752600203030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" 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); SLONG_SWAP(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); SLONG_SWAP(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); SLONG_SWAP(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; } flint2-2.8.4/fmpz/multi_mod_ui.c000066400000000000000000000041741414523752600165500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "nmod_vec.h" 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; } flint2-2.8.4/fmpz/ndiv_qr.c000066400000000000000000000047501414523752600155240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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_printf("Exception: division by zero in fmpz_ndiv_qr\n"); flint_abort(); } 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^(FLINT_BITS - 2) */ 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); } } } flint2-2.8.4/fmpz/nextprime.c000066400000000000000000000034001414523752600160640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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) < FLINT_BITS - 2) { /* 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); } } } flint2-2.8.4/fmpz/or.c000066400000000000000000000032151414523752600144750ustar00rootroot00000000000000/* Copyright (C) 2012 Thomas M. DuBuisson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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); 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); } } } flint2-2.8.4/fmpz/out_raw.c000066400000000000000000000011351414523752600155340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" 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; } flint2-2.8.4/fmpz/popcnt.c000066400000000000000000000025121414523752600153570ustar00rootroot00000000000000/* Copyright (C) 2012 Thomas M. DuBuisson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #ifdef FLINT_USES_POPCNT static __inline__ flint_bitcnt_t shortCount(slong val) { #if defined(_WIN64) || defined(__mips64) return __builtin_popcountll(val); #else return __builtin_popcountl(val); #endif } #else /* A naive implementation if neither your processor nor your compiler want to * do the work. */ static __inline__ flint_bitcnt_t shortCount(slong val) { flint_bitcnt_t cnt; for(cnt=0; val; val >>= 1) { cnt += val & 1; } return cnt; } #endif flint_bitcnt_t fmpz_popcnt(const fmpz_t c) { fmpz c1; c1 = *c; if(!COEFF_IS_MPZ(c1)) { if(*c < 0) return 0; else return shortCount(*c); } else { __mpz_struct *t = COEFF_TO_PTR(c1); if(flint_mpz_cmp_si(t,0) < 0) return 0; else return mpz_popcount(t); } } flint2-2.8.4/fmpz/pow_fmpz.c000066400000000000000000000017001414523752600157130ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" 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; } flint2-2.8.4/fmpz/pow_ui.c000066400000000000000000000027551414523752600153670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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 <= FLINT_BITS - 2) { fmpz_set_ui(f, n_pow(u1, exp)); } else { __mpz_struct *mpz_ptr = _fmpz_promote_val(f); flint_mpz_set_ui(mpz_ptr, u1); flint_mpz_pow_ui(mpz_ptr, mpz_ptr, 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 *mpz_ptr = _fmpz_promote_val(f); flint_mpz_pow_ui(mpz_ptr, COEFF_TO_PTR(c1), exp); /* no need to demote as it can't get smaller */ } } flint2-2.8.4/fmpz/powm.c000066400000000000000000000050001414523752600150310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" 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 */ { if (!COEFF_IS_MPZ(*m)) /* m is small */ { ulong g1 = fmpz_fdiv_ui(g, *m); mpz_t g2, m2; __mpz_struct *mpz_ptr; flint_mpz_init_set_ui(g2, g1); flint_mpz_init_set_ui(m2, *m); mpz_ptr = _fmpz_promote(f); mpz_powm(mpz_ptr, g2, COEFF_TO_PTR(*e), m2); mpz_clear(g2); mpz_clear(m2); _fmpz_demote_val(f); } else /* m is large */ { if (!COEFF_IS_MPZ(*g)) /* g is small */ { mpz_t g2; __mpz_struct *mpz_ptr; flint_mpz_init_set_si(g2, *g); mpz_ptr = _fmpz_promote(f); mpz_powm(mpz_ptr, g2, COEFF_TO_PTR(*e), COEFF_TO_PTR(*m)); mpz_clear(g2); _fmpz_demote_val(f); } else /* g is large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); mpz_powm(mpz_ptr, COEFF_TO_PTR(*g), COEFF_TO_PTR(*e), COEFF_TO_PTR(*m)); _fmpz_demote_val(f); } } } } flint2-2.8.4/fmpz/powm_ui.c000066400000000000000000000050141414523752600155330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" void fmpz_powm_ui(fmpz_t f, const fmpz_t g, ulong e, const fmpz_t m) { if (fmpz_sgn(m) <= 0) { flint_printf("Exception (fmpz_powm_ui). Modulus is less than 1.\n"); flint_abort(); } 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 */ { __mpz_struct *ptr = _fmpz_promote(f); mpz_t m3; flint_mpz_init_set_ui(m3, m2); flint_mpz_powm_ui(ptr, COEFF_TO_PTR(g2), e, m3); mpz_clear(m3); _fmpz_demote_val(f); } } else /* m is large */ { if (!COEFF_IS_MPZ(g2)) /* g is small */ { __mpz_struct *ptr = _fmpz_promote(f); mpz_t g3; flint_mpz_init_set_si(g3, g2); flint_mpz_powm_ui(ptr, g3, e, COEFF_TO_PTR(m2)); mpz_clear(g3); _fmpz_demote_val(f); } else /* g is large */ { __mpz_struct *ptr = _fmpz_promote(f); flint_mpz_powm_ui(ptr, COEFF_TO_PTR(g2), e, COEFF_TO_PTR(m2)); _fmpz_demote_val(f); } } } } flint2-2.8.4/fmpz/powmod2_fmpz_preinv.c000066400000000000000000000024241414523752600200640ustar00rootroot00000000000000/* Copyright (C) 2018, Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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; count_leading_zeros(norm, 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; } flint2-2.8.4/fmpz/preinvn_clear.c000066400000000000000000000010271414523752600167030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_preinvn_clear(fmpz_preinvn_t inv) { flint_free(inv->dinv); } flint2-2.8.4/fmpz/preinvn_init.c000066400000000000000000000030741414523752600165640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #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_printf("Exception (fmpz_preinvn_init). Division by zero.\n"); flint_abort(); norm = 0; /* not reached, but silence compiler warning */ } else if (!COEFF_IS_MPZ(c)) /* c is small */ { inv->dinv = flint_malloc(sizeof(mp_limb_t)); if (c < 0) c = -c; count_leading_zeros(norm, c); if (norm) c <<= norm; flint_mpn_preinvn(inv->dinv, (mp_ptr) &c, 1); inv->n = 1; } else /* c is big */ { __mpz_struct * mpz_ptr = COEFF_TO_PTR(c); slong size = FLINT_ABS(mpz_ptr->_mp_size); inv->dinv = flint_malloc(size*sizeof(mp_limb_t)); count_leading_zeros(norm, mpz_ptr->_mp_d[size - 1]); if (norm) { t = flint_malloc(size*sizeof(mp_limb_t)); mpn_lshift(t, mpz_ptr->_mp_d, size, norm); } else t = mpz_ptr->_mp_d; flint_mpn_preinvn(inv->dinv, t, size); inv->n = size; if (norm) flint_free(t); } inv->norm = norm; } flint2-2.8.4/fmpz/primorial.c000066400000000000000000000073311414523752600160560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "arith.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); mpz_ptr->_mp_size = len; } flint2-2.8.4/fmpz/print.c000066400000000000000000000011461414523752600152120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz.h" int fmpz_print(const fmpz_t x) { if (!COEFF_IS_MPZ(*x)) return flint_printf("%wd", *x); else return (int) mpz_out_str(stdout, 10, COEFF_TO_PTR(*x)); } flint2-2.8.4/fmpz/profile/000077500000000000000000000000001414523752600153505ustar00rootroot00000000000000flint2-2.8.4/fmpz/profile/p-div_qr.c000066400000000000000000000135151414523752600172420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint/flint.h" #include "flint/fmpz.h" #include "flint/fmpz_vec.h" #include "flint/profiler.h" void sample_ndiv_qr(void * arg, ulong count) { FLINT_TEST_INIT(state); fmpz_t q, r, a, b; fmpz_t nmax; 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 (int 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) { FLINT_TEST_INIT(state); fmpz_t q, r, a, b; fmpz_t nmax; 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 (int 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) { FLINT_TEST_INIT(state); fmpz_t q, r, a, b; fmpz_t nmax; 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 (int 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) { FLINT_TEST_INIT(state); fmpz_t q, r, a, b; fmpz_t nmax; 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 (int 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; } flint2-2.8.4/fmpz/profile/p-fdiv_qr_preinvn.c000066400000000000000000000046111414523752600211460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; FLINT_TEST_INIT(state); fmpz_t a, b, c, r; fmpz_preinvn_t inv; 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; } flint2-2.8.4/fmpz/profile/p-xgcd.c000066400000000000000000000143361414523752600167050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint/flint.h" #include "flint/fmpz.h" #include "flint/profiler.h" void sample_xgcd_small(void * arg, ulong count) { FLINT_TEST_INIT(state); fmpz_t d, x, y, a, b; fmpz_t nmax; 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 - 2); prof_start(); for (int 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) { FLINT_TEST_INIT(state); fmpz_t d, x, y, a, b; fmpz_t nmax; 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 (int 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) { FLINT_TEST_INIT(state); fmpz_t d, x, y, a, b; fmpz_t nmax; 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 (int 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) { FLINT_TEST_INIT(state); fmpz_t d, x, y, a, b; fmpz_t nmax; 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 - 2); prof_start(); for (int 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) { FLINT_TEST_INIT(state); fmpz_t d, x, y, a, b; fmpz_t nmax; 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 (int 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) { FLINT_TEST_INIT(state); fmpz_t d, x, y, a, b; fmpz_t nmax; 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 (int 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; } flint2-2.8.4/fmpz/randbits.c000066400000000000000000000020731414523752600156640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_randbits(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits) { if (bits <= FLINT_BITS - 2) { _fmpz_demote(f); *f = n_randbits(state, bits); if (n_randint(state, 2)) *f = -*f; } else { __mpz_struct *mpz_ptr = _fmpz_promote(f); _flint_rand_init_gmp(state); mpz_urandomb(mpz_ptr, state->gmp_state, bits); mpz_setbit(mpz_ptr, bits - 1); if (n_randint(state, 2)) mpz_neg(mpz_ptr, mpz_ptr); _fmpz_demote_val(f); } } flint2-2.8.4/fmpz/randm.c000066400000000000000000000021051414523752600151530ustar00rootroot00000000000000/* Copyright (C) 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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 <= FLINT_BITS - 2) { _fmpz_demote(f); *f = (sgn >= 0) ? n_randint(state, *m) : - n_randint(state, -(*m)); } else { __mpz_struct *mpz_ptr = _fmpz_promote(f); _flint_rand_init_gmp(state); mpz_urandomm(mpz_ptr, state->gmp_state, COEFF_TO_PTR(*m)); if (sgn < 0) mpz_neg(mpz_ptr, mpz_ptr); _fmpz_demote_val(f); } } flint2-2.8.4/fmpz/randprime.c000066400000000000000000000023051414523752600160350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" void fmpz_randprime(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits, int proved) { if (bits <= FLINT_BITS - 2) { _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 *mpz_ptr = _fmpz_promote(f); _flint_rand_init_gmp(state); do { mpz_urandomb(mpz_ptr, state->gmp_state, bits - 1); mpz_setbit(mpz_ptr, bits - 1); fmpz_nextprime(f, f, proved); } while (fmpz_bits(f) != bits); } } flint2-2.8.4/fmpz/randtest.c000066400000000000000000000033351414523752600157040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" 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 <= FLINT_BITS - 2) { _fmpz_demote(f); if (m & UWORD(3)) *f = n_randtest_bits(state, bits); else { m >>= 2; if (bits == 0) *f = 0; else if (bits < FLINT_BITS - 2) *f = m & UWORD(1); else *f = COEFF_MAX; } } else { __mpz_struct *mpz_ptr = _fmpz_promote(f); _flint_rand_init_gmp(state); mpz_rrandomb(mpz_ptr, 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_printf("Exception (fmpz_randtest_not_zero). bits == 0.\n"); flint_abort(); } fmpz_randtest(f, state, bits); if (fmpz_is_zero(f)) fmpz_one(f); } flint2-2.8.4/fmpz/randtest_mod.c000066400000000000000000000025471414523752600165470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" 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); } } flint2-2.8.4/fmpz/read.c000066400000000000000000000012441414523752600147700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" int fmpz_read(fmpz_t f) { mpz_t t; size_t r; mpz_init(t); r = mpz_inp_str(t, stdin, 10); fmpz_set_mpz(f, t); mpz_clear(t); return (r > 0) ? 1 : 0; } flint2-2.8.4/fmpz/remove.c000066400000000000000000000056751414523752600153660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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_printf("Exception (fmpz_remove). factor f <= 1.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz/rfac_ui.c000066400000000000000000000047721414523752600154760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #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); } } flint2-2.8.4/fmpz/rfac_uiui.c000066400000000000000000000016541414523752600160300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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); } } flint2-2.8.4/fmpz/root.c000066400000000000000000000037371414523752600150510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #define ulong mp_limb_t #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_root(fmpz_t r, const fmpz_t f, slong n) { fmpz c = *f; if (n == 0) { flint_printf("Exception (fmpz_root). Unable to take 0-th root.\n"); flint_abort(); } if (n == 1) { fmpz_set(r, f); return; } if (!COEFF_IS_MPZ(c)) /* f is small */ { if (n == 2) { if (c < WORD(0)) { flint_printf("Exception (fmpz_root). Unable to take square root of negative value.\n"); flint_abort(); } fmpz_set_ui(r, n_sqrt(c)); } else /* n > 2 */ { __mpz_struct mpz2; __mpz_struct * mpz1; mp_limb_t cval; if (c == 0) { fmpz_set_ui(r, 0); return; } mpz1 = _fmpz_promote(r); cval = FLINT_ABS(c); mpz2._mp_d = &cval; /* mock up an mpz */ mpz2._mp_size = 1; if (c < WORD(0)) mpz2._mp_size = -1; mpz2._mp_alloc = 1; mpz_root(mpz1, &mpz2, n); _fmpz_demote_val(r); /* root may be small */ } } else /* f is large */ { __mpz_struct * mpz2 = COEFF_TO_PTR(c); __mpz_struct * mpz1 = _fmpz_promote(r); mpz_root(mpz1, mpz2, n); _fmpz_demote_val(r); /* root may be small */ } } flint2-2.8.4/fmpz/set.c000066400000000000000000000015011414523752600146440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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 *mpz_ptr = _fmpz_promote(f); mpz_set(mpz_ptr, COEFF_TO_PTR(*g)); } } flint2-2.8.4/fmpz/set_d.c000066400000000000000000000017011414523752600151510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #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); } } flint2-2.8.4/fmpz/set_d_2exp.c000066400000000000000000000014211414523752600161060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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, ldexp(m, 53)); fmpz_mul_2exp(f, f, exp - 53); } else if (exp < 0) fmpz_set_ui(f, 0); else fmpz_set_d(f, ldexp(m, exp)); } flint2-2.8.4/fmpz/set_mpf.c000066400000000000000000000015331414523752600155130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_set_mpf(fmpz_t f, const mpf_t x) { int check; #if defined(__MPIR_VERSION) check = mpf_fits_si_p(x); #else check = flint_mpf_fits_slong_p(x); #endif 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); } } flint2-2.8.4/fmpz/set_mpz.c000066400000000000000000000025141414523752600155370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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 *mpz_ptr = _fmpz_promote(f); flint_mpz_set_ui(mpz_ptr, uval); mpz_neg(mpz_ptr, mpz_ptr); } } else /* x is more than one limb */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); mpz_set(mpz_ptr, x); } } flint2-2.8.4/fmpz/set_signed_ui_array.c000066400000000000000000000031101414523752600200660ustar00rootroot00000000000000/* Copyright (C) 2016 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" /* 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); } } } } flint2-2.8.4/fmpz/set_signed_uiui.c000066400000000000000000000012761414523752600172410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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); } } flint2-2.8.4/fmpz/set_signed_uiuiui.c000066400000000000000000000021311414523752600175660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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; } } flint2-2.8.4/fmpz/set_str.c000066400000000000000000000012631414523752600155410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int fmpz_set_str(fmpz_t f, const char * str, int b) { int ans; mpz_t copy; ans = mpz_init_set_str(copy, (char *) str, b); if (ans == 0) fmpz_set_mpz(f, copy); mpz_clear(copy); return ans; } flint2-2.8.4/fmpz/set_ui_array.c000066400000000000000000000020541414523752600165430ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" /* 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); } } flint2-2.8.4/fmpz/setbit.c000066400000000000000000000015551414523752600153540ustar00rootroot00000000000000/* 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 2.1 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 < FLINT_BITS - 2) { *f |= (WORD(1) << i); } else /* i >= FLINT_BITS - 2 */ { __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); } } flint2-2.8.4/fmpz/sgn.c000066400000000000000000000012551414523752600146460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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)); } flint2-2.8.4/fmpz/size.c000066400000000000000000000012101414523752600150200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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)); } flint2-2.8.4/fmpz/sizeinbase.c000066400000000000000000000012321414523752600162060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz/smod.c000066400000000000000000000043561414523752600150260ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/fmpz/sqrt.c000066400000000000000000000015721414523752600150520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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_printf("Exception (fmpz_sqrt). g is negative.\n"); flint_abort(); } if (!COEFF_IS_MPZ(*g)) fmpz_set_ui(f, n_sqrt(*g)); else { __mpz_struct * mpz_ptr = _fmpz_promote(f); mpz_sqrt(mpz_ptr, COEFF_TO_PTR(*g)); _fmpz_demote_val(f); } } flint2-2.8.4/fmpz/sqrtmod.c000066400000000000000000000101541414523752600155460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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; 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; } } flint2-2.8.4/fmpz/sqrtrem.c000066400000000000000000000022461414523752600155550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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_printf("Exception (fmpz_sqrtrem). g is negative.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpz/sub.c000066400000000000000000000037721414523752600146560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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 */ } } } flint2-2.8.4/fmpz/sub_ui.c000066400000000000000000000025731414523752600153510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_sub_ui(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 *mpz_ptr, *mpz_ptr2; mpz_ptr2 = _fmpz_promote(f); /* g is already large */ mpz_ptr = COEFF_TO_PTR(c); flint_mpz_sub_ui(mpz_ptr2, mpz_ptr, x); _fmpz_demote_val(f); /* cancellation may have occurred */ } } flint2-2.8.4/fmpz/submul.c000066400000000000000000000023341414523752600153650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_submul(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (c1 < WORD(0)) fmpz_addmul_ui(f, h, -c1); else fmpz_submul_ui(f, h, c1); } else { fmpz c2 = *h; if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 < WORD(0)) fmpz_addmul_ui(f, g, -c2); else fmpz_submul_ui(f, g, c2); } else /* both g and h are large */ { __mpz_struct *mpz_ptr = _fmpz_promote_val(f); mpz_submul(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* cancellation may have occurred */ } } } flint2-2.8.4/fmpz/submul_si.c000066400000000000000000000026231414523752600160610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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); } } 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); } } flint2-2.8.4/fmpz/submul_ui.c000066400000000000000000000046361414523752600160710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_submul_ui(fmpz_t f, const fmpz_t g, ulong x) { fmpz c1 = *g, r; if ((x == 0) || (c1 == 0)) return; /* product is zero */ r = *f; if (r == 0) { fmpz_mul_ui(f, g, x); /* we are subtracting product from 0 */ fmpz_neg(f, f); return; } if (!COEFF_IS_MPZ(c1)) /* c1 is small */ { mp_limb_t prod[2]; ulong uc1 = FLINT_ABS(c1); __mpz_struct * mpz_ptr; mpz_t temp; umul_ppmm(prod[1], prod[0], uc1, x); /* compute product */ if (prod[1] == 0) /* product fits in one limb */ { if (c1 < WORD(0)) fmpz_add_ui(f, f, prod[0]); else fmpz_sub_ui(f, f, prod[0]); return; } else if ((prod[1] == 1) && (!COEFF_IS_MPZ(r)) && ((r ^ c1) >= WORD(0))) { /* only chance at cancellation is if product is one bit past a limb and f is small and same sign as this product */ ulong ur = FLINT_ABS(r); if (ur > prod[0]) /* cancellation will occur */ { fmpz_set_ui(f, prod[0] - ur); if (r > WORD(0)) fmpz_neg(f, f); return; } } /* in all remaining cases res is either big already, or will be big in the end */ mpz_ptr = _fmpz_promote_val(f); /* set up a temporary, cheap mpz_t to contain prod */ temp->_mp_d = prod; temp->_mp_size = (c1 < WORD(0) ? -2 : 2); mpz_sub(mpz_ptr, mpz_ptr, temp); _fmpz_demote_val(f); /* cancellation may have occurred */ } else /* c1 is large */ { __mpz_struct *mpz_ptr = _fmpz_promote_val(f); flint_mpz_submul_ui(mpz_ptr, COEFF_TO_PTR(c1), x); _fmpz_demote_val(f); /* cancellation may have occurred */ } } flint2-2.8.4/fmpz/tdiv_q.c000066400000000000000000000031441414523752600153440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" 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_printf("Exception (fmpz_tdiv_q). Division by zero.\n"); flint_abort(); } 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 *mpz_ptr = _fmpz_promote(f); if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 > 0) /* h > 0 */ { flint_mpz_tdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); } else { flint_mpz_tdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), -c2); mpz_neg(mpz_ptr, mpz_ptr); } } else /* both are large */ { mpz_tdiv_q(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); } _fmpz_demote_val(f); /* division by h may result in small value */ } } flint2-2.8.4/fmpz/tdiv_q_2exp.c000066400000000000000000000020311414523752600162740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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, FLINT_BITS - 2); else d = -((-d) >> FLINT_MIN(exp, FLINT_BITS - 2)); fmpz_set_si(f, d); } else /*g is large */ { __mpz_struct * mpz_ptr = _fmpz_promote(f); /* g is already large */ mpz_tdiv_q_2exp(mpz_ptr, COEFF_TO_PTR(d), exp); _fmpz_demote_val(f); /* division may make value small */ } } flint2-2.8.4/fmpz/tdiv_q_si.c000066400000000000000000000023541414523752600160410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_tdiv_q_si(fmpz_t f, const fmpz_t g, slong h) { fmpz c1 = *g; slong c2 = h; if (h == 0) { flint_printf("Exception (fmpz_tdiv_q_si). Division by zero.\n"); flint_abort(); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { fmpz_set_si(f, c1 / c2); } else /* g is large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); if (c2 > 0) { flint_mpz_tdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); } else { flint_mpz_tdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), -(ulong) c2); mpz_neg(mpz_ptr, mpz_ptr); } _fmpz_demote_val(f); /* division by h may result in small value */ } } flint2-2.8.4/fmpz/tdiv_q_ui.c000066400000000000000000000023641414523752600160440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" void fmpz_tdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) { fmpz c1 = *g; ulong c2 = h; if (h == 0) { flint_printf("Exception (fmpz_tdiv_q_ui). Division by zero.\n"); flint_abort(); } 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 *mpz_ptr = _fmpz_promote(f); flint_mpz_tdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); _fmpz_demote_val(f); /* division by h may result in small value */ } } flint2-2.8.4/fmpz/tdiv_qr.c000066400000000000000000000041661414523752600155330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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_printf("Exception: division by zero in fmpz_tdiv_qr\n"); flint_abort(); } 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 *mpz_ptr, *mpz_ptr2; _fmpz_promote(f); /* must not hang on to ptr whilst promoting s */ mpz_ptr2 = _fmpz_promote(s); mpz_ptr = COEFF_TO_PTR(*f); if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 > 0) /* h > 0 */ { flint_mpz_tdiv_qr_ui(mpz_ptr, mpz_ptr2, COEFF_TO_PTR(c1), c2); } else { flint_mpz_tdiv_qr_ui(mpz_ptr, mpz_ptr2, COEFF_TO_PTR(c1), -c2); mpz_neg(mpz_ptr, mpz_ptr); } } else /* both are large */ { mpz_tdiv_qr(mpz_ptr, mpz_ptr2, 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 */ } } flint2-2.8.4/fmpz/tdiv_r_2exp.c000066400000000000000000000021151414523752600163000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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 < (FLINT_BITS - 2) ? d & ((WORD(1) << exp) - 1) : d); } else { d = -d; fmpz_neg_ui(f, exp < (FLINT_BITS - 2) ? d & ((WORD(1) << exp) - 1) : d); } } else /*g is large */ { __mpz_struct * mpz_ptr = _fmpz_promote(f); /* g is already large */ mpz_tdiv_r_2exp(mpz_ptr, COEFF_TO_PTR(d), exp); _fmpz_demote_val(f); /* division may make value small */ } } flint2-2.8.4/fmpz/tdiv_ui.c000066400000000000000000000017621414523752600155250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" ulong fmpz_tdiv_ui(const fmpz_t g, ulong h) { fmpz c1 = *g; if (h == UWORD(0)) { flint_printf("Exception (fmpz_tdiv_ui). Division by 0.\n"); flint_abort(); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { /* We need the absolut 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); } } flint2-2.8.4/fmpz/test/000077500000000000000000000000001414523752600146675ustar00rootroot00000000000000flint2-2.8.4/fmpz/test/t-abs.c000066400000000000000000000036121414523752600160430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("abs...."); fflush(stdout); 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); fmpz_abs(b, a); mpz_abs(c, c); fmpz_get_mpz(d, b); result = (mpz_cmp(c, d) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } /* Check aliasing */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t c, d; fmpz_init(a); mpz_init(c); mpz_init(d); fmpz_randtest(a, state, 200); fmpz_get_mpz(c, a); fmpz_abs(a, a); mpz_abs(c, c); fmpz_get_mpz(d, a); result = (mpz_cmp(c, d) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); abort(); } fmpz_clear(a); mpz_clear(c); mpz_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-abs_fits_ui.c000066400000000000000000000030161414523752600175630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" static void check(fmpz_t x, int expected) { if (fmpz_abs_fits_ui(x) != expected) { flint_printf("FAIL:\n\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); abort(); } } int main(void) { slong i; fmpz_t x; FLINT_TEST_INIT(state); flint_printf("abs_fits_ui...."); fflush(stdout); fmpz_init(x); fmpz_set_si(x, COEFF_MIN); check(x, 1); fmpz_set_si(x, COEFF_MAX); check(x, 1); fmpz_set_ui(x, UWORD_MAX); check(x, 1); fmpz_set_ui(x, UWORD_MAX); fmpz_neg(x, x); check(x, 1); fmpz_set_ui(x, UWORD_MAX); fmpz_add_ui(x, x, UWORD(1)); check(x, 0); fmpz_neg(x, x); check(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, i < FLINT_BITS); fmpz_neg(x, x); check(x, i < FLINT_BITS); } fmpz_clear(x); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-abs_lbound_ui_2exp.c000066400000000000000000000037731414523752600210510ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.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; } int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("abs_lbound_ui_2exp...."); fflush(stdout); 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); abort(); } fmpz_clear(x); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-abs_ubound_ui_2exp.c000066400000000000000000000063751414523752600210630ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { slong iter; int result; FLINT_TEST_INIT(state); flint_printf("abs_ubound_ui_2exp...."); fflush(stdout); 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); 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); abort(); } fmpz_clear(x); fmpz_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-add.c000066400000000000000000000076371414523752600160410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_add(c, a, b); mpz_add(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); fmpz_add(c, a, a); mpz_add(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_add(a, a, b); mpz_add(f, d, e); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_add(b, a, b); mpz_add(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-add_ui.c000066400000000000000000000042561414523752600165300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add_ui...."); fflush(stdout); 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); fmpz_add_ui(b, a, x); flint_mpz_add_ui(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); 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, f; ulong x; fmpz_init(a); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randtest(state); fmpz_add_ui(a, a, x); flint_mpz_add_ui(e, d, x); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-addmul.c000066400000000000000000000077121414523752600165510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("addmul...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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_get_mpz(d, a); fmpz_get_mpz(e, b); fmpz_get_mpz(f, c); fmpz_addmul(c, a, b); mpz_addmul(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(c, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(f, c); fmpz_addmul(c, a, a); mpz_addmul(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; 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); fmpz_addmul(a, a, b); mpz_addmul(d, d, e); fmpz_get_mpz(f, a); result = (mpz_cmp(d, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd\n", d, e, f); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; 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); fmpz_addmul(b, a, b); mpz_addmul(e, d, e); fmpz_get_mpz(f, b); result = (mpz_cmp(f, e) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd\n", d, e, f); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-addmul_si.c000066400000000000000000000044771414523752600172510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "long_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("addmul_si...."); fflush(stdout); 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); fmpz_addmul_si(b, a, x); flint_mpz_init_set_si(xx, x); mpz_addmul(e, d, xx); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, xx = %Zd\n", d, e, f, xx); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(xx); 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, xx; slong 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_si(a, a, x); flint_mpz_init_set_si(xx, x); mpz_addmul(d, d, xx); fmpz_get_mpz(e, a); result = (mpz_cmp(d, e) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, xx = %Zd\n", d, e, xx); flint_abort(); } fmpz_clear(a); mpz_clear(xx); mpz_clear(d); mpz_clear(e); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-addmul_ui.c000066400000000000000000000043051414523752600172410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("addmul_ui...."); fflush(stdout); 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); fmpz_addmul_ui(b, a, x); flint_mpz_addmul_ui(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); 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); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-and.c000066400000000000000000000077211414523752600160450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("and...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_and(c, a, b); mpz_and(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (no aliasing):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); fmpz_and(c, a, a); mpz_and(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (a/b alias):\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_and(a, a, b); mpz_and(f, d, e); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (a/c alias):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_and(b, a, b); mpz_and(f, d, e); fmpz_get_mpz(g, b); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (b/c alias):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-bin_uiui.c000066400000000000000000000023511414523752600171000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main(void) { slong i; ulong n, k; fmpz_t x, y; mpz_t z; FLINT_TEST_INIT(state); flint_printf("bin_uiui...."); fflush(stdout); 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)) { flint_printf("FAIL: n,k = %wu,%wu\n", n, k); abort(); } fmpz_clear(x); fmpz_clear(y); mpz_clear(z); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-bit_pack.c000066400000000000000000000050721414523752600170540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("bit_pack/bit_unpack...."); fflush(stdout); 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 accomodate 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"); 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 accomodate 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); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n"); fmpz_print(b), flint_printf("\n"); abort(); } flint_free(arr); fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-bits.c000066400000000000000000000023511414523752600162360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("bits...."); fflush(stdout); 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); abort(); } fmpz_clear(a); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-cdiv_q.c000066400000000000000000000077321414523752600165520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cdiv_q...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_cdiv_q(c, a, b); mpz_cdiv_q(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest_not_zero(a, state, 200); fmpz_get_mpz(d, a); fmpz_cdiv_q(c, a, a); mpz_cdiv_q(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_cdiv_q(a, a, b); mpz_cdiv_q(f, d, e); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_cdiv_q(b, a, b); mpz_cdiv_q(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-cdiv_q_2exp.c000066400000000000000000000043051414523752600175010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cdiv_q_2exp...."); fflush(stdout); 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); fmpz_cdiv_q_2exp(b, a, x); mpz_cdiv_q_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); 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, f; ulong x; fmpz_init(a); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); fmpz_cdiv_q_2exp(a, a, x); mpz_cdiv_q_2exp(e, d, x); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-cdiv_q_si.c000066400000000000000000000045431414523752600172420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cdiv_q_si...."); fflush(stdout); 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); fmpz_cdiv_q_si(c, a, b); mpz_cdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (1):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { slong b; fmpz_t a; mpz_t d, e, f, g; fmpz_init(a); 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); fmpz_cdiv_q_si(a, a, b); mpz_cdiv_q(f, d, e); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (2):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-cdiv_q_ui.c000066400000000000000000000045441414523752600172450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cdiv_q_ui...."); fflush(stdout); 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); fmpz_cdiv_q_ui(c, a, b); mpz_cdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (1):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong b; fmpz_t a; mpz_t d, e, f, g; fmpz_init(a); 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); fmpz_cdiv_q_ui(a, a, b); mpz_cdiv_q(f, d, e); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (2):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-cdiv_qr.c000066400000000000000000000147371414523752600167370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cdiv_qr...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; slong j; 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_randbits(a, state, 1000); do { fmpz_randbits(b, state, 500); } while(fmpz_is_zero(b)); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); for (j = 1; j < 100; j++) fmpz_cdiv_qr(c, r, a, b); 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); if (!result) { flint_printf("FAIL 1:\n"); gmp_printf ("d = %Zd, e = %Zd, f = %Zd, g = %Zd, h = %Zd, s = %Zd\n", d, e, f, g, h, s); 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); } /* Check aliasing of c and a */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_cdiv_qr(a, r, a, b); mpz_cdiv_qr(f, s, d, e); fmpz_get_mpz(g, a); fmpz_get_mpz(h, r); result = (mpz_cmp(f, g) == 0 && mpz_cmp(h, s) == 0); if (!result) { flint_printf("FAIL 2:\n"); gmp_printf ("d = %Zd, e = %Zd, f = %Zd, g = %Zd, h = %Zd, s = %Zd\n", d, e, f, g, h, s); 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); } /* Check aliasing of c and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_cdiv_qr(b, r, a, b); mpz_cdiv_qr(f, s, d, e); fmpz_get_mpz(g, b); fmpz_get_mpz(h, r); result = (mpz_cmp(f, g) == 0 && mpz_cmp(h, s) == 0); if (!result) { flint_printf("FAIL 3:\n"); gmp_printf ("d = %Zd, e = %Zd, f = %Zd, g = %Zd, h = %Zd, s = %Zd\n", d, e, f, g, h, s); 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); } /* Check aliasing of r and a */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_cdiv_qr(c, a, a, b); mpz_cdiv_qr(f, s, d, e); fmpz_get_mpz(g, c); fmpz_get_mpz(h, a); result = (mpz_cmp(f, g) == 0 && mpz_cmp(h, s) == 0); if (!result) { flint_printf("FAIL 4:\n"); gmp_printf ("d = %Zd, e = %Zd, f = %Zd, g = %Zd, h = %Zd, s = %Zd\n", d, e, f, g, h, s); 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); } /* Check aliasing of r and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_cdiv_qr(c, b, a, b); mpz_cdiv_qr(f, s, d, e); fmpz_get_mpz(g, c); fmpz_get_mpz(h, b); result = (mpz_cmp(f, g) == 0 && mpz_cmp(h, s) == 0); if (!result) { flint_printf("FAIL 5:\n"); gmp_printf ("d = %Zd, e = %Zd, f = %Zd, g = %Zd, h = %Zd, s = %Zd\n", d, e, f, g, h, s); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-cdiv_r_2exp.c000066400000000000000000000043311414523752600175010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cdiv_r_2exp...."); fflush(stdout); 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); fmpz_cdiv_r_2exp(b, a, x); mpz_cdiv_r_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL 1:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); 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, f; ulong x; fmpz_init(a); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); fmpz_cdiv_r_2exp(a, a, x); mpz_cdiv_r_2exp(e, d, x); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL 2:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); flint_abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-cdiv_ui.c000066400000000000000000000024521414523752600167210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cdiv_ui...."); fflush(stdout); 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); if (!result) { flint_printf("FAIL:\n"); gmp_printf ("b = %Zd, x = %ld, r1 = %ld, r2 = %ld\n", b, x, r1, r2); abort(); } fmpz_clear(a); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-clog.c000066400000000000000000000061361414523752600162260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("clog...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-clog_ui.c000066400000000000000000000051431414523752600167200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("clog_ui...."); fflush(stdout); /* 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); 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); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-cmp.c000066400000000000000000000037011414523752600160540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cmp...."); fflush(stdout); 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"); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-cmp2abs.c000066400000000000000000000026231414523752600166260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int sign(int a) { return a > 0 ? 1 : a < 0 ? -1 : 0; } int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("cmp2abs...."); fflush(stdout); 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"); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(b2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-cmp_si.c000066400000000000000000000032071414523752600165500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "long_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cmp_si...."); fflush(stdout); /* 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)); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-cmp_ui.c000066400000000000000000000031371414523752600165540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cmp_ui...."); fflush(stdout); /* 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)); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-cmpabs.c000066400000000000000000000037141414523752600165460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cmpabs...."); fflush(stdout); 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"); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-comb_init_clear.c000066400000000000000000000025461414523752600204140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main() { slong i, j; mp_limb_t n; slong num_primes; mp_limb_t * primes; mp_limb_t p; fmpz_comb_t comb; FLINT_TEST_INIT(state); flint_printf("comb_init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-combit.c000066400000000000000000000027361414523752600165610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("combit...."); fflush(stdout); 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); 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); abort(); } fmpz_clear(a); mpz_clear(c); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-complement.c000066400000000000000000000036701414523752600174450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("complement...."); fflush(stdout); 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); fmpz_complement(b, a); mpz_com(c, c); fmpz_get_mpz(d, b); result = (mpz_cmp(c, d) == 0); if (!result) { flint_printf("FAIL (no alias):\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } /* Check aliasing */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t c, d; fmpz_init(a); mpz_init(c); mpz_init(d); fmpz_randtest(a, state, 200); fmpz_get_mpz(c, a); fmpz_complement(a, a); mpz_com(c, c); fmpz_get_mpz(d, a); result = (mpz_cmp(c, d) == 0); if (!result) { flint_printf("FAIL (aliased):\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); abort(); } fmpz_clear(a); mpz_clear(c); mpz_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-crt.c000066400000000000000000000051771414523752600160760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main() { slong i, j; int sign; fmpz_t input; fmpz_t result; fmpz_t r1; fmpz_t m1; fmpz_t mprod; fmpz_t r2, m2; FLINT_TEST_INIT(state); flint_printf("CRT...."); fflush(stdout); 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); fmpz_CRT(result, r1, m1, r2, m2, sign); if (!fmpz_equal(result, input)) { 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"); abort(); } } fmpz_clear(input); fmpz_clear(result); fmpz_clear(r1); fmpz_clear(m1); fmpz_clear(r2); fmpz_clear(m2); fmpz_clear(mprod); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-crt_ui.c000066400000000000000000000047031414523752600165650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main() { slong i, j; int sign; fmpz_t input; fmpz_t result; fmpz_t r1; fmpz_t m1; fmpz_t mprod; ulong r2, m2; FLINT_TEST_INIT(state); flint_printf("CRT_ui...."); fflush(stdout); 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)) { 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"); abort(); } } fmpz_clear(input); fmpz_clear(result); fmpz_clear(r1); fmpz_clear(m1); fmpz_clear(mprod); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-divexact.c000066400000000000000000000102351414523752600171040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divexact...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_divexact(a, c, b); mpz_divexact(f, e, d); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest_not_zero(a, state, 200); fmpz_get_mpz(d, a); fmpz_divexact(c, a, a); mpz_divexact(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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, c); fmpz_get_mpz(e, b); fmpz_divexact(c, c, b); mpz_divexact(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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, c); fmpz_get_mpz(e, b); fmpz_divexact(b, c, b); mpz_divexact(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-divexact2_uiui.c000066400000000000000000000052751414523752600202310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divexact2_uiui...."); fflush(stdout); 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); fmpz_divexact2_uiui(a, c, 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); if (!result) { flint_printf("FAIL:\n"); gmp_printf("n = %Mu, m = %Mu, e = %Zd, f = %Zd, g = %Zd\n", n, m, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; ulong n, m; fmpz_init(a); fmpz_init(c); mpz_init(d); 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(d, c); fmpz_divexact2_uiui(c, c, n, m); flint_mpz_divexact_ui(f, d, n); flint_mpz_divexact_ui(f, f, m); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, n = %Mu, m = %Mu, f = %Zd, g = %Zd\n", d, n, m, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-divexact_si.c000066400000000000000000000047321414523752600176040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divexact_si...."); fflush(stdout); 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); fmpz_divexact_si(a, c, 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); if (!result) { flint_printf("FAIL:\n"); gmp_printf("n = %Md, e = %Zd, f = %Zd, g = %Zd\n", n, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; slong n; fmpz_init(a); fmpz_init(c); mpz_init(d); 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(d, c); fmpz_divexact_si(c, c, n); flint_mpz_divexact_ui(f, d, FLINT_ABS(n)); if (n < 0) mpz_neg(f, f); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL;\n"); gmp_printf("d = %Zd, n = %Md, f = %Zd, g = %Zd\n", d, n, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-divexact_ui.c000066400000000000000000000045501414523752600176040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divexact_ui...."); fflush(stdout); 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); fmpz_divexact_ui(a, c, n); flint_mpz_divexact_ui(f, e, n); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL1\n"); gmp_printf("n = %Mu, e = %Zd, f = %Zd, g = %Zd\n", n, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; ulong n; fmpz_init(a); fmpz_init(c); mpz_init(d); 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(d, c); fmpz_divexact_ui(c, c, n); flint_mpz_divexact_ui(f, d, n); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, n = %Mu, f = %Zd, g = %Zd\n", d, n, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-divides.c000066400000000000000000000105551414523752600167310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divides...."); fflush(stdout); /* Random values */ 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); divides = fmpz_divides(q, b, a); fmpz_mul(p, a, q); result = ((divides && fmpz_equal(p, b)) || (!divides && fmpz_is_zero(q) && !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"); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(p); fmpz_clear(q); } /* Check aliasing of q and a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, q; int divides1, divides2; fmpz_init(a); fmpz_init(b); fmpz_init(q); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); divides1 = fmpz_divides(q, b, a); divides2 = fmpz_divides(a, b, a); result = (divides1 == divides2 && fmpz_equal(q, a)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides1 = %d, divides2 = %d\n", divides1, divides2); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(q); } /* Check aliasing of q and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, b, q; int divides1, divides2; fmpz_init(a); fmpz_init(b); fmpz_init(q); fmpz_randtest(a, state, 200); fmpz_randtest(b, state, 200); divides1 = fmpz_divides(q, b, a); divides2 = fmpz_divides(b, b, a); result = (divides1 == divides2 && fmpz_equal(q, b)); if (!result) { flint_printf("FAIL:\n"); flint_printf("divides1 = %d, divides2 = %d\n", divides1, divides2); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-divides_mod_list.c000066400000000000000000000110421414523752600206130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { slong i, j; int result1, result2; FLINT_TEST_INIT(state); flint_printf("divides_mod_list...."); fflush(stdout); 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"); flint_abort(); } if (fmpz_cmp(xstart, xstride) >= 0) { flint_printf("FAIL:\ncheck xstart < xstride\n"); 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); 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); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-divisible.c000066400000000000000000000051261414523752600172520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divisible...."); fflush(stdout); /* Compare with MPIR: 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } /* Compare with MPIR: 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); 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); abort(); } fmpz_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-divisible_si.c000066400000000000000000000043601414523752600177440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divisible_si...."); fflush(stdout); /* Compare with MPIR: 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(state); if (a == WORD_MIN) a = 1; a = FLINT_ABS(a) + 1; fmpz_randtest(b, state, 200); fmpz_get_mpz(d, b); e = fmpz_divisible_si(b, a); f = flint_mpz_divisible_ui_p(d, a); result = (e == f); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = %wd, b = ", a), fmpz_print(b), flint_printf("\n"); abort(); } fmpz_clear(b); mpz_clear(d); } /* Compare with MPIR: 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(state); if (a == WORD_MIN) a = 1; a = FLINT_ABS(a) + 1; fmpz_randtest(b, state, 200); fmpz_mul_ui(b, b, a); fmpz_get_mpz(d, b); e = fmpz_divisible_si(b, a); f = flint_mpz_divisible_ui_p(d, a); result = (e == f && e == 1); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = %wd, b = ", a), fmpz_print(b), flint_printf("\n"); abort(); } fmpz_clear(b); mpz_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-divisor_in_residue_class_lenstra.c000066400000000000000000000067441414523752600241110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divisors_in_residue_class...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(p); fmpz_clear(r); fmpz_clear(s); fmpz_clear(g); fmpz_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-divisor_sigma.c000066400000000000000000000032361414523752600201370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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 n, ulong k) { 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); } int main(void) { fmpz_t m, a, b; slong n, k; FLINT_TEST_INIT(state); flint_printf("divisor_sigma...."); fflush(stdout); 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, m, k); fmpz_sigma_naive(b, n, k); if (!fmpz_equal(a, b)) { flint_printf("FAIL:\n"); flint_printf("wrong value for n=%wd, k=%wd\n", n, k); abort(); } } } fmpz_clear(a); fmpz_clear(b); fmpz_clear(m); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-dlog.c000066400000000000000000000030711414523752600162220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("dlog...."); fflush(stdout); 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); abort(); } fmpz_clear(x); mpz_clear(z); mpfr_clear(r); } mpfr_free_cache(); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-equal.c000066400000000000000000000035101414523752600164020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("equal...."); fflush(stdout); 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"); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-equal_si.c000066400000000000000000000047621414523752600171070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "long_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("equal_si...."); fflush(stdout); /* 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)); 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)); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-equal_ui.c000066400000000000000000000047121414523752600171040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("equal_ui...."); fflush(stdout); /* 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)); 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)); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-euler_phi.c000066400000000000000000000047501414523752600172560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" #include "profiler.h" int main(void) { slong i; ulong n; fmpz_t x, y, z; FLINT_TEST_INIT(state); flint_printf("euler_phi...."); fflush(stdout); 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); 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"); 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)) { 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)) { flint_printf("FAIL: special test value\n"); abort(); } fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fac_ui.c000066400000000000000000000025111414523752600165210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { slong i, n; fmpz_t x; fmpz_t y; FLINT_TEST_INIT(state); flint_printf("fac_ui...."); fflush(stdout); 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)) { flint_printf("FAIL: %wd\n", i); fmpz_print(x); flint_printf("\n"); fmpz_print(y); flint_printf("\n"); abort(); } } } fmpz_clear(x); fmpz_clear(y); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fdiv_q.c000066400000000000000000000077321414523752600165550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("fdiv_q...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_fdiv_q(c, a, b); mpz_fdiv_q(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest_not_zero(a, state, 200); fmpz_get_mpz(d, a); fmpz_fdiv_q(c, a, a); mpz_fdiv_q(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_fdiv_q(a, a, b); mpz_fdiv_q(f, d, e); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_fdiv_q(b, a, b); mpz_fdiv_q(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fdiv_q_2exp.c000066400000000000000000000043051414523752600175040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("fdiv_q_2exp...."); fflush(stdout); 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); fmpz_fdiv_q_2exp(b, a, x); mpz_fdiv_q_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); 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, f; ulong x; fmpz_init(a); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); fmpz_fdiv_q_2exp(a, a, x); mpz_fdiv_q_2exp(e, d, x); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fdiv_q_si.c000066400000000000000000000045431414523752600172450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("fdiv_q_si...."); fflush(stdout); 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); fmpz_fdiv_q_si(c, a, b); mpz_fdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (1):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { slong b; fmpz_t a; mpz_t d, e, f, g; fmpz_init(a); 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); fmpz_fdiv_q_si(a, a, b); mpz_fdiv_q(f, d, e); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (2):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fdiv_q_ui.c000066400000000000000000000045441414523752600172500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("fdiv_q_ui...."); fflush(stdout); 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); fmpz_fdiv_q_ui(c, a, b); mpz_fdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (1):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong b; fmpz_t a; mpz_t d, e, f, g; fmpz_init(a); 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); fmpz_fdiv_q_ui(a, a, b); mpz_fdiv_q(f, d, e); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (2):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fdiv_qr.c000066400000000000000000000147361414523752600167410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("fdiv_qr...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; slong j; 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_randbits(a, state, 1000); do { fmpz_randbits(b, state, 500); } while(fmpz_is_zero(b)); fmpz_get_mpz(d, a); fmpz_get_mpz(e, b); for (j = 1; j < 100; j++) fmpz_fdiv_qr(c, r, a, b); 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); 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); } /* Check aliasing of c and a */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_fdiv_qr(a, r, a, b); mpz_fdiv_qr(f, s, d, e); fmpz_get_mpz(g, a); 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); 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); } /* Check aliasing of c and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_fdiv_qr(b, r, a, b); mpz_fdiv_qr(f, s, d, e); fmpz_get_mpz(g, b); 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); 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); } /* Check aliasing of r and a */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_fdiv_qr(c, a, a, b); mpz_fdiv_qr(f, s, d, e); fmpz_get_mpz(g, c); fmpz_get_mpz(h, a); 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); 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); } /* Check aliasing of r and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_fdiv_qr(c, b, a, b); mpz_fdiv_qr(f, s, d, e); fmpz_get_mpz(g, c); fmpz_get_mpz(h, b); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fdiv_qr_preinvn.c000066400000000000000000000156451414523752600205020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("fdiv_qr_preinvn...."); fflush(stdout); 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; 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); fmpz_fdiv_qr_preinvn(c, r, a, b, 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); 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); } /* Check aliasing of c and a */ 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; 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); fmpz_preinvn_init(inv, b); fmpz_fdiv_qr_preinvn(a, r, a, b, inv); mpz_fdiv_qr(f, s, d, e); fmpz_get_mpz(g, a); 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); 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); } /* Check aliasing of c and b */ 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; 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); fmpz_preinvn_init(inv, b); fmpz_fdiv_qr_preinvn(b, r, a, b, inv); mpz_fdiv_qr(f, s, d, e); fmpz_get_mpz(g, b); 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); 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); } /* Check aliasing of r and a */ 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; 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); fmpz_preinvn_init(inv, b); fmpz_fdiv_qr_preinvn(c, a, a, b, inv); mpz_fdiv_qr(f, s, d, e); fmpz_get_mpz(g, c); fmpz_get_mpz(h, a); 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); 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); } /* Check aliasing of r and b */ 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; 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); fmpz_preinvn_init(inv, b); fmpz_fdiv_qr_preinvn(c, b, a, b, inv); mpz_fdiv_qr(f, s, d, e); fmpz_get_mpz(g, c); fmpz_get_mpz(h, b); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fdiv_r.c000066400000000000000000000077321414523752600165560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("fdiv_r...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_fdiv_r(c, a, b); mpz_fdiv_r(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest_not_zero(a, state, 200); fmpz_get_mpz(d, a); fmpz_fdiv_r(c, a, a); mpz_fdiv_r(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_fdiv_r(a, a, b); mpz_fdiv_r(f, d, e); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_fdiv_r(b, a, b); mpz_fdiv_r(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fdiv_r_2exp.c000066400000000000000000000043731414523752600175120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("fdiv_r_2exp...."); fflush(stdout); 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); fmpz_fdiv_r_2exp(b, a, x); mpz_fdiv_r_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); 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, f; ulong x; fmpz_init(a); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); fmpz_fdiv_r_2exp(a, a, x); mpz_fdiv_r_2exp(e, d, x); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-fdiv_ui.c000066400000000000000000000024641414523752600167270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("fdiv_ui...."); fflush(stdout); 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); if (!result) { flint_printf("FAIL:\n"); gmp_printf ("b = %Zd, x = %wu, r1 = %wu, r2 = %wu\n", b, x, r1, r2); abort(); } fmpz_clear(a); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fib_ui.c000066400000000000000000000027401414523752600165340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { slong i, n; fmpz_t x, y, z, w; FLINT_TEST_INIT(state); flint_printf("fib_ui...."); fflush(stdout); 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)) { flint_printf("FAIL: %wd\n", i); fmpz_print(x); flint_printf("\n"); fmpz_print(y); flint_printf("\n"); fmpz_print(z); flint_printf("\n"); abort(); } } } fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); fmpz_clear(w); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fits_si.c000066400000000000000000000034451414523752600167420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" static void check(fmpz_t x, int expected) { if (fmpz_fits_si(x) != expected) { flint_printf("FAIL:\n\n"); flint_printf("x = "), fmpz_print(x), flint_printf("\n"); flint_printf("fmpz_fits_si(x) = %d\n", fmpz_fits_si(x)); flint_printf("WORD_MIN = %wd\n", WORD_MIN); abort(); } } int main(void) { slong i; fmpz_t x; FLINT_TEST_INIT(state); flint_printf("fits_si...."); fflush(stdout); fmpz_init(x); fmpz_set_si(x, COEFF_MIN); check(x, 1); fmpz_set_si(x, COEFF_MAX); check(x, 1); fmpz_set_si(x, WORD_MAX); check(x, 1); fmpz_set_si(x, WORD_MIN); check(x, 1); fmpz_set_ui(x, UWORD_MAX); check(x, 0); fmpz_set_ui(x, UWORD_MAX); fmpz_neg(x, x); check(x, 0); fmpz_set_si(x, WORD_MAX); fmpz_add_ui(x, x, 1); check(x, 0); fmpz_set_si(x, WORD_MIN); fmpz_sub_ui(x, x, 1); check(x, 0); for (i = 0; i < 1000; i++) { fmpz_set_ui(x, 1); fmpz_mul_2exp(x, x, i); check(x, i < FLINT_BITS - 1); fmpz_neg(x, x); check(x, i < FLINT_BITS); /* WORD_MIN fits */ } fmpz_clear(x); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-flog.c000066400000000000000000000060071414523752600162260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("flog...."); fflush(stdout); /* 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); 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); 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); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-flog_ui.c000066400000000000000000000050451414523752600167240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("flog_ui...."); fflush(stdout); /* 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); 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); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-fmma.c000066400000000000000000000041721414523752600162200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("fmma...."); fflush(stdout); 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)) { 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"); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(f); fmpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fmms.c000066400000000000000000000041721414523752600162420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("fmms...."); fflush(stdout); 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)) { 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"); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(f); fmpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fmpz.c000066400000000000000000000020621414523752600162500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("fmpz...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; *a = WORD(0); fmpz_randtest(a, state, FLINT_BITS - 2); *b = *a; _fmpz_promote_val(a); _fmpz_demote_val(a); result = (*b == *a); if (!result) { flint_printf("FAIL\n"); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fmpz_cleanup.c000066400000000000000000000027641414523752600177700ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "flint.h" #include "ulong_extras.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("fmpz_cleanup...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-fmpz_stress.c000066400000000000000000000111001414523752600176440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" #include "thread_support.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); } } int main(void) { slong i, j, k; slong max_num_threads = 5; thread_pool_handle * handles; slong num_handles; worker_arg_struct * wargs; FLINT_TEST_INIT(state); flint_printf("fmpz_stress...."); fflush(stdout); 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)) { flint_printf("FAIL:\n"); flint_printf("total: "); fmpz_print(total); flint_printf("\n"); flint_printf("check: "); fmpz_print(check); flint_printf("\n"); flint_abort(); } } _fmpz_vec_clear(v, n); fmpz_clear(total); fmpz_clear(check); } flint_free(wargs); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-gcd.c000066400000000000000000000104171414523752600160340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_gcd(c, a, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); fmpz_gcd(c, a, a); mpz_gcd(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_gcd(a, a, b); mpz_gcd(f, d, e); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_gcd(b, a, b); mpz_gcd(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-gcd3.c000066400000000000000000000042211414523752600161130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("gcd3...."); fflush(stdout); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(e); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-gcdinv.c000066400000000000000000000124201414523752600165450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcdinv...."); fflush(stdout); /* Test aliasing of d and f, a and g */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t d, a, f, g, F, G; fmpz_init(d); fmpz_init(a); fmpz_init(f); fmpz_init(g); fmpz_init(F); fmpz_init(G); fmpz_randtest_unsigned(G, state, 200); fmpz_add_ui(G, G, 1); fmpz_randm(F, state, G); fmpz_set(f, F); fmpz_set(g, G); fmpz_gcdinv(d, a, f, g); fmpz_gcdinv(f, g, f, g); result = (fmpz_equal(d, f) && (fmpz_equal(a, g) || fmpz_is_zero(F))); 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("F = "), fmpz_print(F), flint_printf("\n"); flint_printf("G = "), fmpz_print(G), flint_printf("\n"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(f); fmpz_clear(g); fmpz_clear(F); fmpz_clear(G); } /* Test aliasing of a and f, d and g */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t d, a, f, g, F, G; fmpz_init(d); fmpz_init(a); fmpz_init(f); fmpz_init(g); fmpz_init(F); fmpz_init(G); fmpz_randtest_unsigned(G, state, 200); fmpz_add_ui(G, G, 1); fmpz_randm(F, state, G); fmpz_set(f, F); fmpz_set(g, G); fmpz_gcdinv(d, a, f, g); fmpz_gcdinv(g, f, f, g); result = (fmpz_equal(d, g) && (fmpz_equal(a, f) || fmpz_is_zero(F))); 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("F = "), fmpz_print(F), flint_printf("\n"); flint_printf("G = "), fmpz_print(G), flint_printf("\n"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(f); fmpz_clear(g); fmpz_clear(F); fmpz_clear(G); } /* Test a f == d mod g (generically d == 1) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t d, a, f, g, t; fmpz_init(d); fmpz_init(a); fmpz_init(f); fmpz_init(g); fmpz_init(t); fmpz_randtest_unsigned(g, state, 200); fmpz_add_ui(g, g, 1); fmpz_randm(f, state, g); fmpz_gcdinv(d, a, f, g); 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); 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"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(f); fmpz_clear(g); fmpz_clear(t); } /* 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; 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); fmpz_gcdinv(d, a, f, g); 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); 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"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(f); fmpz_clear(g); fmpz_clear(t); fmpz_clear(x); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-get_d.c000066400000000000000000000035041414523752600163600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get_d...."); fflush(stdout); 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); 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); abort(); } fmpz_clear(x); fmpz_clear(y); mpz_clear(z); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-get_d_2exp.c000066400000000000000000000024751414523752600173240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; double output; slong exp; FLINT_TEST_INIT(state); flint_printf("get_d_2exp...."); fflush(stdout); 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)); abort(); } fmpz_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-get_mpf.c000066400000000000000000000042511414523752600167170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get/set_mpf...."); fflush(stdout); 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"); 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"); abort(); } fmpz_clear(x); fmpz_clear(y); mpz_clear(z); mpf_clears(a, b, tmp, NULL); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-get_mpfr.c000066400000000000000000000031771414523752600171070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get_mpfr...."); fflush(stdout); 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"); abort(); } fmpz_clear(x); fmpz_clear(y); mpz_clear(z); mpfr_clears(a, b, NULL); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-get_mpn.c000066400000000000000000000053111414523752600167250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "mpn_extras.h" #include "fmpz.h" int main() { fmpz_t a, b, mmin; int i, j, k; mp_ptr mpna; FLINT_TEST_INIT(state); flint_printf("get_mpn...."); fflush(stdout); 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"); 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"); abort(); } flint_free(mpna); #endif } fmpz_clear(a); fmpz_clear(b); fmpz_clear(mmin); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-get_mpz.c000066400000000000000000000026151414523752600167450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get/set_mpz...."); fflush(stdout); 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); if (!result) { flint_printf("FAIL:\n"); gmp_printf("b = %Zd, c = %Zd\n", b, c); abort(); } fmpz_clear(a); mpz_clear(b); mpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-get_nmod.c000066400000000000000000000025751414523752600171010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get_nmod...."); fflush(stdout); 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); flint_abort(); } fmpz_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-get_set_ui_array.c000066400000000000000000000037611414523752600206300ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i; slong max_limbs = 100; ulong * limbs; FLINT_TEST_INIT(state); flint_printf("get_set_ui_array...."); fflush(stdout); 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)) { flint_printf("FAIL:\n"); flint_printf("Check get and set are inverse\n"); abort(); } if (!fmpz_equal(a, c)) { flint_printf("FAIL:\n"); flint_printf("Check limbs are accurate\n"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } flint_free(limbs); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-get_si.c000066400000000000000000000034571414523752600165570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "long_extras.h" int main(void) { fmpz_t x; int i, result; FLINT_TEST_INIT(state); flint_printf("get/set_si...."); fflush(stdout); 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"); abort(); } fmpz_set_si(x, COEFF_MAX); if (COEFF_IS_MPZ(*x) || fmpz_get_si(x) != COEFF_MAX) { flint_printf("FAIL: COEFF_MIN"); abort(); } fmpz_set_si(x, WORD_MIN); if (!COEFF_IS_MPZ(*x) || fmpz_get_si(x) != WORD_MIN) { flint_printf("FAIL: WORD_MIN"); abort(); } fmpz_set_si(x, WORD_MIN); if (!COEFF_IS_MPZ(*x) || fmpz_get_si(x) != WORD_MIN) { flint_printf("FAIL: WORD_MAX"); 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); if (!result) { flint_printf("FAIL:\n"); flint_printf("b = %wd, c = %wd\n", b, c); abort(); } fmpz_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-get_str.c000066400000000000000000000033111414523752600167410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get_str...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t b; int base, j; 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); result = strlen(str1) == strlen(str2); if (result) { for (j = 0; result && j < strlen(str1); j++) if (str1[j] != str2[j]) result = 0; } if (!result) { 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); abort(); } flint_free(str1); flint_free(str2); fmpz_clear(a); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-get_ui.c000066400000000000000000000021551414523752600165530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get/set_ui...."); fflush(stdout); 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); if (!result) { flint_printf("FAIL:\n"); flint_printf("b = %wd, c = %wd\n", b, c); abort(); } fmpz_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-init2.c000066400000000000000000000021361414523752600163230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/init2/clear...."); fflush(stdout); 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, FLINT_BITS - 2); _fmpz_promote_val(a); _fmpz_demote_val(a); fmpz_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-init_set.c000066400000000000000000000034101414523752600171100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("init_set...."); fflush(stdout); /* Small integers */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; fmpz_init(a); fmpz_randtest(a, state, FLINT_BITS - 2); fmpz_init_set(b, a); result = fmpz_equal(a, 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"); 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); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-init_set_readonly.c000066400000000000000000000044311414523752600210110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "long_extras.h" #include "fmpz.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init_set_readonly...."); fflush(stdout); /* 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)) { 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-init_set_ui.c000066400000000000000000000024221414523752600176070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("init_set_ui...."); fflush(stdout); 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); 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); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-invmod.c000066400000000000000000000111651414523752600165740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" /* Use the definiton 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); } int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("invmod...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; int r1, r2; 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); r1 = fmpz_invmod(c, a, b); 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); 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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; int r1, r2; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest_not_zero(a, state, 200); fmpz_get_mpz(d, a); r1 = fmpz_invmod(c, a, a); r2 = mpz_invert2(f, d, d); fmpz_get_mpz(g, c); result = (r1 != 0 && r2 != 0 && (mpz_cmp(f, g) == 0)) || (r1 == 0 && r2 == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd, r1 = %d, r2 = %d\n", d, f, g, r1, r2); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; int r1, r2; fmpz_init(a); fmpz_init(b); 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); r1 = fmpz_invmod(a, a, b); r2 = mpz_invert2(f, d, e); fmpz_get_mpz(g, a); result = (r1 != 0 && r2 != 0 && (mpz_cmp(f, g) == 0)) || (r1 == 0 && r2 == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; int r1, r2; fmpz_init(a); fmpz_init(b); 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); r1 = fmpz_invmod(b, a, b); r2 = mpz_invert2(f, d, e); fmpz_get_mpz(g, b); result = (r1 != 0 && r2 != 0 && (mpz_cmp(f, g) == 0)) || (r1 == 0 && r2 == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-is_even.c000066400000000000000000000033431414523752600167270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_even/odd...."); fflush(stdout); 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); 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); abort(); } fmpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-is_perfect_power.c000066400000000000000000000067021414523752600206400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; ulong bits, exp; fmpz_t root, d, n, n2, pow; FLINT_TEST_INIT(state); flint_printf("is_perfect_power...."); fflush(stdout); 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"); 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); 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"); 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"); 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); 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"); abort(); } mpz_clear(d_m); } fmpz_clear(n); fmpz_clear(n2); fmpz_clear(d); fmpz_clear(pow); fmpz_clear(root); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-is_prime.c000066400000000000000000000071661414523752600171150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.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[] = { "2047", "1373653", "25326001", "3215031751", "2152302898747", "3474749660383", "341550071728321", "230245660726188031", "3825123056546413051", "7395010240794120709381", "164280218643672633986221", "318665857834031151167461", "360681321802296925566181", "552727880697763694556181", "667636712015520329618581", "2995741773170734841812261", "3317044064679887385961981", "3404730287403079539471001", NULL, }; int main(void) { int i, result, r1; FLINT_TEST_INIT(state); flint_printf("is_prime...."); fflush(stdout); /* test table of composites */ for (i = 0; composites[i] != NULL; i++) { fmpz_t n; fmpz_init(n); fmpz_set_str(n, composites[i], 10); r1 = fmpz_is_prime(n); if (r1 != 0) { flint_printf("FAIL:\n"); fmpz_print(n); printf("\n"); 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"); 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"); 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"); 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"); abort(); } fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-is_prime_morrison.c000066400000000000000000000031541414523752600210360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_prime_morrison...."); fflush(stdout); 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"); abort(); } _nmod_vec_clear(pp1); fmpz_clear(p); fmpz_clear(F); fmpz_clear(R); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-is_prime_pocklington.c000066400000000000000000000031621414523752600215140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_prime_pocklington...."); fflush(stdout); 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"); abort(); } _nmod_vec_clear(pm1); fmpz_clear(p); fmpz_clear(F); fmpz_clear(R); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-is_prime_pseudosquare.c000066400000000000000000000023271414523752600217070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_prime_pseudosquare...."); fflush(stdout); 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); abort(); } fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-is_probabprime_BPSW.c000066400000000000000000000037351414523752600211340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_probabprime_BPSW...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(p); fmpz_clear(a); fmpz_clear(F); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-is_probabprime_lucas.c000066400000000000000000000040451414523752600214630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result, count = 0; FLINT_TEST_INIT(state); flint_printf("is_probabprime_lucas...."); fflush(stdout); /* 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"); 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); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-is_square.c000066400000000000000000000024261414523752600172730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_square...."); fflush(stdout); 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); abort(); } fmpz_clear(a); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-is_strong_probabprime.c000066400000000000000000000077751414523752600217050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" /* Composite strong pseudoprimes from https://oeis.org/A014233 */ static const char * composites[] = { "2047", "1373653", "25326001", "3215031751", "2152302898747", "3474749660383", "341550071728321", "341550071728321", "3825123056546413051", "3825123056546413051", "3825123056546413051", "318665857834031151167461", "3317044064679887385961981", NULL, }; int main(void) { int i, result, count = 0; FLINT_TEST_INIT(state); flint_printf("is_strong_probabprime...."); fflush(stdout); /* test table */ { for (i = 0; composites[i] != NULL; i++) { int j; fmpz_t n, a; fmpz_init(n); fmpz_init(a); fmpz_set_str(n, composites[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"); 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"); 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"); 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); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-jacobi.c000066400000000000000000000026541414523752600165320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("jacobi...."); fflush(stdout); 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); flint_abort(); } } fmpz_clear(a); fmpz_clear(n); mpz_clear(aa); mpz_clear(nn); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-kronecker.c000066400000000000000000000026111414523752600172570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("kronecker...."); fflush(stdout); 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(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); flint_abort(); } } fmpz_clear(a); fmpz_clear(n); mpz_clear(aa); mpz_clear(nn); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-lcm.c000066400000000000000000000104701414523752600160510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("lcm...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_lcm(c, a, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); fmpz_lcm(c, a, a); mpz_lcm(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_lcm(a, a, b); mpz_lcm(f, d, e); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_lcm(b, a, b); mpz_lcm(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-mod.c000066400000000000000000000077001414523752600160570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mod...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_mod(c, a, b); mpz_mod(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest_not_zero(a, state, 200); fmpz_get_mpz(d, a); fmpz_mod(c, a, a); mpz_mod(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_mod(a, a, b); mpz_mod(f, d, e); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_mod(b, a, b); mpz_mod(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-mod_ui.c000066400000000000000000000046041414523752600165540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mod_ui...."); fflush(stdout); 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); r1 = fmpz_mod_ui(b, a, x); r2 = flint_mpz_fdiv_r_ui(e, d, x); fmpz_get_mpz(f, b); result = ((mpz_cmp(e, f) == 0) && (r1 == r2)); 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); 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, f; ulong x, r1, r2; fmpz_init(a); 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); r1 = fmpz_mod_ui(a, a, x); r2 = flint_mpz_fdiv_r_ui(e, d, x); fmpz_get_mpz(f, a); result = ((mpz_cmp(e, f) == 0) && (r1 == r2)); 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); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-moebius_mu.c000066400000000000000000000033071414523752600174430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" #include "profiler.h" void check(fmpz_t n, int expected) { int mu; mu = fmpz_moebius_mu(n); if (mu != expected) { flint_printf("FAIL:"); fmpz_print(n); flint_printf("\n"); } } int main(void) { fmpz_t x; ulong p; slong i, j, k, l; FLINT_TEST_INIT(state); flint_printf("moebius_mu...."); fflush(stdout); fmpz_init(x); for (i = -1000; i < 1000; i++) { fmpz_set_si(x, i); check(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, (k % 2 ? -1 : 1)); fmpz_neg(x, x); check(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, 0); } fmpz_clear(x); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-mpz_init_set_readonly.c000066400000000000000000000037751414523752600217110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "long_extras.h" #include "fmpz.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("mpz_init_set_readonly...."); fflush(stdout); /* 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-mul.c000066400000000000000000000076331414523752600161020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_mul(c, a, b); mpz_mul(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); fmpz_mul(c, a, a); mpz_mul(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_mul(a, a, b); mpz_mul(f, d, e); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_mul(b, a, b); mpz_mul(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-mul2_uiui.c000066400000000000000000000046461414523752600172200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul2_uiui...."); fflush(stdout); 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); fmpz_mul2_uiui(b, a, 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); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu, y = %Mu\n", d, e, f, x, y); 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, f; ulong x, y; fmpz_init(a); 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); fmpz_mul2_uiui(a, a, x, y); flint_mpz_mul_ui(e, d, x); flint_mpz_mul_ui(e, e, y); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu, y = %Mu\n", d, e, f, x, y); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-mul_2exp.c000066400000000000000000000042671414523752600170400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_2exp...."); fflush(stdout); 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); fmpz_mul_2exp(b, a, x); mpz_mul_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); 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, f; ulong x; fmpz_init(a); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); fmpz_mul_2exp(a, a, x); mpz_mul_2exp(e, d, x); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-mul_si.c000066400000000000000000000042531414523752600165700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_si...."); fflush(stdout); 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); fmpz_mul_si(b, a, x); flint_mpz_mul_si(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Md\n", d, e, f, x); 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, f; slong x; fmpz_init(a); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = z_randtest(state); fmpz_mul_si(a, a, x); flint_mpz_mul_si(e, d, x); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Md\n", d, e, f, x); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-mul_si_tdiv_q_2exp.c000066400000000000000000000047721414523752600211020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_si_tdiv_q_2exp...."); fflush(stdout); 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); fmpz_mul_si_tdiv_q_2exp(b, a, 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); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Md, exp = %Mu\n", d, e, f, x, exp); 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, f; slong x; ulong exp; fmpz_init(a); 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); fmpz_mul_si_tdiv_q_2exp(a, a, x, exp); flint_mpz_mul_si(e, d, x); mpz_tdiv_q_2exp(e, e, exp); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Md, exp = %Mu\n", d, e, f, x, exp); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-mul_tdiv_q_2exp.c000066400000000000000000000107611414523752600204020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_tdiv_q_2exp...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; ulong exp; 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); fmpz_mul_tdiv_q_2exp(c, a, b, exp); mpz_mul(f, d, e); mpz_tdiv_q_2exp(f, f, exp); 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, exp = %Mu\n", d, e, f, g, exp); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; ulong exp; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); exp = n_randint(state, 200); fmpz_get_mpz(d, a); fmpz_mul_tdiv_q_2exp(c, a, a, exp); mpz_mul(f, d, d); mpz_tdiv_q_2exp(f, f, exp); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd, exp = %Mu\n", d, f, g, exp); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; ulong exp; fmpz_init(a); fmpz_init(b); 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); fmpz_mul_tdiv_q_2exp(a, a, b, exp); mpz_mul(f, d, e); mpz_tdiv_q_2exp(f, f, exp); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd, exp = %Mu\n", d, e, f, g, exp); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; ulong exp; fmpz_init(a); fmpz_init(b); 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); fmpz_mul_tdiv_q_2exp(b, a, b, exp); mpz_mul(f, d, e); mpz_tdiv_q_2exp(f, f, exp); fmpz_get_mpz(g, b); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd, exp = %Mu\n", d, e, f, g, exp); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-mul_ui.c000066400000000000000000000042541414523752600165730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_ui...."); fflush(stdout); 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); fmpz_mul_ui(b, a, x); flint_mpz_mul_ui(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); 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, f; ulong x; fmpz_init(a); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randtest(state); fmpz_mul_ui(a, a, x); flint_mpz_mul_ui(e, d, x); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-multi_CRT_multi_mod.c000066400000000000000000000234451414523752600212170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_vec.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("multi_CRT/multi_mod...."); fflush(stdout); /* 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"); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz/test/t-multi_CRT_ui.c000066400000000000000000000066131414523752600176410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" int main() { 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; FLINT_TEST_INIT(state); flint_printf("multi_CRT_ui...."); fflush(stdout); 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) ULONG_SWAP(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); 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); 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); flint_abort(); } } fmpz_clear(temp); fmpz_clear(input); fmpz_clear(prod); flint_free(output); flint_free(primes); _fmpz_vec_clear(primes2, num_primes); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-multi_crt.c000066400000000000000000000301521414523752600172770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("crt...."); fflush(stdout); /* test internal interface */ { fmpz_multi_crt_t P; fmpz ** moduli, ** inputs, * outputs; slong moduli_count = 1000; moduli = (fmpz **) flint_malloc(moduli_count*sizeof(fmpz *)); inputs = (fmpz **) flint_malloc(moduli_count*sizeof(fmpz *)); outputs = (fmpz *) flint_malloc(moduli_count*sizeof(fmpz)); for (k = 0; k < moduli_count; k++) { moduli[k] = (fmpz *) flint_malloc(sizeof(fmpz)); inputs[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(moduli[k]); fmpz_init(inputs[k]); fmpz_init(outputs + 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(P, (const fmpz * const *) moduli, moduli_count)) { printf("FAIL\n"); flint_printf("Check simple example\n"); flint_abort(); } FLINT_ASSERT(_fmpz_multi_crt_local_size(P) <= moduli_count); for (k = 0; k < 1; k++) { _fmpz_multi_crt_run_p(outputs, P, (const fmpz * const *) inputs); } for (k = 0; k < moduli_count; k++) { fmpz_clear(moduli[k]); fmpz_clear(inputs[k]); fmpz_clear(outputs + k); flint_free(moduli[k]); flint_free(inputs[k]); } flint_free(moduli); flint_free(inputs); flint_free(outputs); fmpz_multi_crt_clear(P); } /* test pointer interface */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_multi_crt_t P; 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); fmpz_multi_crt_init(P); 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++) { moduli[k] = (fmpz *) flint_malloc(sizeof(fmpz)); inputs[k] = (fmpz *) flint_malloc(sizeof(fmpz)); 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_precompute_p(P, (const fmpz * const *) moduli, moduli_count)) { fmpz_multi_crt_precomp_p(output, P, (const fmpz * const *) inputs); 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 " "i = %wd, j = %wd, k = %wd\n", i, j, k); flint_abort(); } } fmpz_add(output, output, output); if (fmpz_cmpabs(output, p) > 0) { printf("FAIL\n"); flint_printf("Check output size " "i = %wd, j = %wd, k = %wd\n", i, j, k); 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 crt failure i = %wd, j = %wd\n", i, j); flint_abort(); } } for (k = 0; k < moduli_count; k++) { fmpz_clear(moduli[k]); fmpz_clear(inputs[k]); flint_free(moduli[k]); flint_free(inputs[k]); } flint_free(moduli); flint_free(inputs); } fmpz_clear(t); fmpz_clear(p); fmpz_clear(output); fmpz_multi_crt_clear(P); } /* test flat interface */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { fmpz_multi_crt_t P; 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); fmpz_multi_crt_init(P); 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_precompute(P, moduli, moduli_count)) { fmpz_multi_crt_precomp(output, P, inputs); 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 flat " "i = %wd, j = %wd, k = %wd\n", i, j, k); flint_abort(); } } fmpz_add(output, output, output); if (fmpz_cmpabs(output, p) > 0) { printf("FAIL\n"); flint_printf("Check output size flat " "i = %wd, j = %wd, k = %wd\n", i, j, k); 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 flat crt failure i = %wd, j = %wd\n", i, j); 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); fmpz_multi_crt_clear(P); } /* 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)) { 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); 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz/test/t-ndiv_qr.c000066400000000000000000000113111414523752600167330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { slong i; int result; FLINT_TEST_INIT(state); flint_printf("ndiv_qr...."); fflush(stdout); /* 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"); 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"); 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); 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"); 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); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-neg.c000066400000000000000000000036161414523752600160530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg...."); fflush(stdout); 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); fmpz_neg(b, a); mpz_neg(c, c); fmpz_get_mpz(d, b); result = (mpz_cmp(c, d) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } /* Check aliasing */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a; mpz_t c, d; fmpz_init(a); mpz_init(c); mpz_init(d); fmpz_randtest(a, state, 200); fmpz_get_mpz(c, a); fmpz_neg(a, a); mpz_neg(c, c); fmpz_get_mpz(d, a); result = (mpz_cmp(c, d) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); abort(); } fmpz_clear(a); mpz_clear(c); mpz_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-neg_ui.c000066400000000000000000000024641414523752600165500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg_ui...."); fflush(stdout); 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); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-neg_uiui.c000066400000000000000000000027321414523752600171040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg_uiui...."); fflush(stdout); 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); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-nextprime.c000066400000000000000000000050251414523752600173110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" const char * const manual_tests[] = { /* anyting <= 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" }; int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("nextprime...."); fflush(stdout); 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)) { flint_printf("FAIL:\n"); fmpz_print(start); flint_printf("\n"); 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)) { flint_printf("FAIL:\n"); fmpz_print(start); flint_printf("\n"); abort(); } fmpz_clear(start); fmpz_clear(res); fmpz_clear(iter); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-or.c000066400000000000000000000076321414523752600157240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("or...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_or(c, a, b); mpz_ior(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); fmpz_or(c, a, a); mpz_ior(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_or(a, a, b); mpz_ior(f, d, e); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_or(b, a, b); mpz_ior(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-out_inp_raw.c000066400000000000000000000073651414523752600176350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ #undef __STRICT_ANSI__ #endif #undef ulong #define ulong ulongxx /* interferes with standard libraries */ #include #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) #include #endif #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) int main(void) { int i, j, n = 10000, result; FILE *in, *out; int fd[2]; pid_t childpid; FLINT_TEST_INIT(state); printf("out_raw/inp_raw...."); fflush(stdout); /* 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"); abort(); } if((childpid = fork()) == -1) { printf("FAIL:\n"); printf("Failed to fork the process.\n"); 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"); abort(); } for (j = 0; j < n; j++) { r = fmpz_out_raw(out, a + j); if (r <= 0) { printf("FAIL:\n"); printf("Write error.\n"); 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"); abort(); } fmpz_init(t); i = 0; while ( (r = fmpz_inp_raw(t, in)) != 0 ) { result = fmpz_equal(t, a + i); if (!result) { printf("FAIL:\n"); printf("a[i] = "), fmpz_print(a + i), printf("\n"); printf("t = "), fmpz_print(t), printf("\n"); abort(); } ++i; } fmpz_clear(t); fclose(in); } if (i != n) { printf("FAIL:\n"); printf("Only %d out of %d objects were processed.\n", i, n); 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 */ FLINT_TEST_CLEANUP(state); printf("PASS\n"); return EXIT_SUCCESS; } #else int main(void) { printf("out_raw/ inp_raw...."); fflush(stdout); printf("SKIPPED\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fmpz/test/t-popcnt.c000066400000000000000000000026231414523752600166020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; flint_bitcnt_t r1, r2; FLINT_TEST_INIT(state); flint_printf("popcnt...."); fflush(stdout); 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); abort(); } fmpz_clear(a); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-pow_ui.c000066400000000000000000000042621414523752600166020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow_ui...."); fflush(stdout); 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); fmpz_pow_ui(b, a, x); flint_mpz_pow_ui(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); 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, f; ulong x; fmpz_init(a); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 20); fmpz_pow_ui(a, a, x); flint_mpz_pow_ui(e, d, x); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-powm.c000066400000000000000000000111451414523752600162600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powm...."); fflush(stdout); /* Compare with MPIR */ 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; 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); fmpz_powm(b, a, x, c); mpz_powm(e, d, y, m); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL (cmp f with MPIR e := d^y mod m):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, y = %Zd, m = %Zd\n", d, e, f, y, m); 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); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; fmpz_t n; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(n); fmpz_randtest(b, state, 200); fmpz_randtest_not_zero(c, state, 200); fmpz_abs(c, c); fmpz_randtest_unsigned(n, state, 20); fmpz_powm(a, b, n, c); fmpz_powm(b, b, n, c); result = (fmpz_equal(a, b)); if (!result) { flint_printf("FAIL (alias a and b):\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("n = "), fmpz_print(n), flint_printf("\n"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(n); } /* Check aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; fmpz_t n; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(n); fmpz_randtest(b, state, 200); fmpz_randtest_not_zero(c, state, 200); fmpz_abs(c, c); fmpz_randtest_unsigned(n, state, 20); fmpz_powm(a, b, n, c); fmpz_powm(c, b, n, c); result = (fmpz_equal(a, c)); if (!result) { flint_printf("FAIL (alias a and c):\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("n = "), fmpz_print(n), flint_printf("\n"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(n); } /* Check aliasing of a and {b, c} */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; fmpz_t n; fmpz_init(a); fmpz_init(c); fmpz_init(n); fmpz_randtest_not_zero(c, state, 200); fmpz_abs(c, c); fmpz_randtest_unsigned(n, state, 20); fmpz_powm(a, c, n, c); fmpz_powm(c, c, n, c); result = (fmpz_equal(a, c)); if (!result) { flint_printf("FAIL (alias a and b,c):\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); flint_printf("n = "), fmpz_print(n), flint_printf("\n"); abort(); } fmpz_clear(a); fmpz_clear(c); fmpz_clear(n); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-powm_ui.c000066400000000000000000000102251414523752600167530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powm_ui...."); fflush(stdout); /* Compare with MPIR */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, m; ulong x; 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); fmpz_powm_ui(b, a, x, c); flint_mpz_powm_ui(e, d, x, m); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu, m = %Zd\n", d, e, f, x, m); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(m); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; ulong n; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_randtest(b, state, 200); fmpz_randtest_not_zero(c, state, 200); fmpz_abs(c, c); n = n_randtest(state); fmpz_powm_ui(a, b, n, c); fmpz_powm_ui(b, b, n, c); 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"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); flint_printf("n = %wu\n", n); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; ulong n; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_randtest(b, state, 200); fmpz_randtest_not_zero(c, state, 200); fmpz_abs(c, c); n = n_randtest(state); fmpz_powm_ui(a, b, n, c); fmpz_powm_ui(c, b, n, c); result = (fmpz_equal(a, c)); 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"); flint_printf("n = %wu\n", n); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } /* Check aliasing of a and {b, c} */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; ulong n; fmpz_init(a); fmpz_init(c); fmpz_randtest_not_zero(c, state, 200); fmpz_abs(c, c); n = n_randtest(state); fmpz_powm_ui(a, c, n, c); fmpz_powm_ui(c, c, n, c); result = (fmpz_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), fmpz_print(a), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); flint_printf("n = %wu\n", n); abort(); } fmpz_clear(a); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-primorial.c000066400000000000000000000022301414523752600172670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main(void) { ulong k; fmpz_t x; fmpz_t y; FLINT_TEST_INIT(state); flint_printf("primorial...."); fflush(stdout); fmpz_init(x); fmpz_init(y); fmpz_set_ui(y, 1); for (k = 0; k < 10000; k++) { fmpz_primorial(x, k); if (n_is_prime(k)) fmpz_mul_ui(y, y, k); if (!fmpz_equal(x, y)) { flint_printf("FAIL:\n"); flint_printf("primorial of %wu disagrees with direct product\n", k); fmpz_print(x); flint_printf("\n"); abort(); } } fmpz_clear(x); fmpz_clear(y); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-print_read.c000066400000000000000000000137041414523752600174300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ #undef __STRICT_ANSI__ #endif #include #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) #include #endif #include #include #include #include "flint.h" #include "fmpz.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) int main(void) { int i, j, n = 10000, result; FILE *in, *out; int fd[2]; pid_t childpid; FLINT_TEST_INIT(state); flint_printf("print/ read...."); fflush(stdout); /* 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"); abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); 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"); 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"); 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"); 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"); abort(); } result = fmpz_equal(t, a + i); 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"); abort(); } ++i; } fmpz_clear(t); fclose(in); } if (i != n) { flint_printf("FAIL:\n"); flint_printf("Only %d out of %d objects were processed.\n", i, n); 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"); abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); 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"); abort(); } r = flint_fprintf(out, "blah"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); 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"); abort(); } fmpz_init(t); i = 0; while (!feof(in)) { r = fmpz_fread(in, t); if (r > 0) { flint_printf("FAIL:\n"); flint_printf("r = %d\n", r); abort(); } ++i; } fmpz_clear(t); fclose(in); } /* 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); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #else int main(void) { flint_printf("print/ read...."); fflush(stdout); flint_printf("SKIPPED\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fmpz/test/t-randprime.c000066400000000000000000000051141414523752600172560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" int main(void) { int i; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("randprime...."); fflush(stdout); 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) { flint_printf("FAIL: not %wu bits\n", bits); fmpz_print(p); flint_printf("\n"); abort(); } if (fmpz_is_prime(p) != 1) { flint_printf("FAIL: not prime, %wu bits\n", bits); fmpz_print(p); flint_printf("\n"); 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) { flint_printf("FAIL: not %wu bits\n", bits); fmpz_print(p+j); flint_printf("\n"); abort(); } if (fmpz_is_prime(p+j) == 0) { flint_printf("FAIL: not prime, %wu bits\n", bits); fmpz_print(p+j); flint_printf("\n"); 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"); abort(); } fmpz_clear(p+0); fmpz_clear(p+1); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-remove.c000066400000000000000000000123071414523752600165740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("remove...."); fflush(stdout); /* Compare with MPIR, 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; 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); x = fmpz_remove(c, a, b); y = mpz_remove(f, d, e); fmpz_get_mpz(g, c); result = ((x == y) && (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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Compare with MPIR, 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); 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); } /* Check aliasing of a and b */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, c; slong x; fmpz_init(a); fmpz_init(c); do { fmpz_randtest_not_zero(a, state, 200); fmpz_abs(a, a); } while (fmpz_is_one(a)); x = fmpz_remove(c, a, a); result = ((x == 1) && (fmpz_cmp_ui(c, 1) == 0)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n"); fmpz_print(c), flint_printf("\n"); abort(); } fmpz_clear(a); fmpz_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b, c; slong x, y; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_randtest_not_zero(a, state, 200); do { fmpz_randtest_not_zero(b, state, 200); fmpz_abs(b, b); } while (fmpz_is_one(b)); x = fmpz_remove(c, a, b); y = fmpz_remove(a, a, b); result = ((x == y) && fmpz_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n"); fmpz_print(b), flint_printf("\n"); fmpz_print(c), flint_printf("\n"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } /* Check aliasing of b and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_t a, b, c; slong x, y; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_randtest_not_zero(a, state, 200); do { fmpz_randtest_not_zero(b, state, 200); fmpz_abs(b, b); } while (fmpz_is_one(b)); x = fmpz_remove(c, a, b); y = fmpz_remove(b, a, b); result = ((x == y) && fmpz_equal(b, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n"); fmpz_print(b), flint_printf("\n"); fmpz_print(c), flint_printf("\n"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-rfac_ui.c000066400000000000000000000052121414523752600167040ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("rfac_ui... "); fflush(stdout); /* Check aliasing */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t x, r; ulong a; fmpz_init(x); fmpz_init(r); fmpz_randtest(x, state, 1 + n_randint(state, 200)); a = n_randint(state, 100); fmpz_rfac_ui(r, x, a); fmpz_rfac_ui(x, x, a); result = fmpz_equal(r, x); if (!result) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("x: "); fmpz_print(x); flint_printf("\n\n"); flint_printf("a = %wu\n\n", a); flint_printf("r: "); fmpz_print(r); flint_printf("\n\n"); abort(); } fmpz_clear(x); fmpz_clear(r); } /* 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); fmpz_rfac_ui(r1, x, a); fmpz_rfac_ui(r2, xa, b); fmpz_rfac_ui(r3, x, a+b); fmpz_mul(r1r2, r1, r2); result = fmpz_equal(r1r2, 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"); abort(); } fmpz_clear(x); fmpz_clear(xa); fmpz_clear(r1); fmpz_clear(r2); fmpz_clear(r1r2); fmpz_clear(r3); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-rfac_uiui.c000066400000000000000000000036411414523752600172460ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("rfac_uiui... "); fflush(stdout); /* 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); 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"); abort(); } fmpz_clear(xa); fmpz_clear(r1); fmpz_clear(r2); fmpz_clear(r1r2); fmpz_clear(r3); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-root.c000066400000000000000000000045671414523752600162730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("root...."); fflush(stdout); /* 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); fmpz_root(f, g, n); mpz_root(mf, mg, n); fmpz_get_mpz(mf2, f); result = (mpz_cmp(mf2, mf) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("mf = %Zd, mf2 = %Zd, mg = %Zd, root = %Md\n", mf, mf2, mg, n); abort(); } fmpz_clear(f); fmpz_clear(g); mpz_clear(mf); mpz_clear(mf2); mpz_clear(mg); } /* Check aliasing of f and g */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f; mpz_t mf, mf2; slong n; fmpz_init(f); mpz_init(mf); mpz_init(mf2); n = n_randint(state, 20) + 1; fmpz_randtest(f, state, 200); if ((n & 1) == 0) fmpz_abs(f, f); fmpz_get_mpz(mf, f); fmpz_root(f, f, n); mpz_root(mf, mf, n); fmpz_get_mpz(mf2, f); result = (mpz_cmp(mf, mf2) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("mf = %Zd, mf2 = %Zd, root = %Md\n", mf, mf2, n); abort(); } fmpz_clear(f); mpz_clear(mf); mpz_clear(mf2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-set.c000066400000000000000000000027151414523752600160740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set...."); fflush(stdout); 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); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-set_d_2exp.c000066400000000000000000000026411414523752600173330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; double d, d2; slong exp, exp2; FLINT_TEST_INIT(state); flint_printf("set_d_2exp...."); fflush(stdout); 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); 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)); abort(); } fmpz_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-set_signed_ui_array.c000066400000000000000000000037371414523752600213250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i; slong max_limbs = 20; ulong * limbs; fmpz_t a, b, c; FLINT_TEST_INIT(state); flint_printf("set_signed_ui_array...."); fflush(stdout); 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)) { flint_printf("FAIL: check answer mod 2^(n*FLINT_BITS)\n"); 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"); flint_abort(); } fmpz_neg(c, c); if (fmpz_cmp(b, c) < 0) { flint_printf("FAIL: check answer >= -2^(n*FLINT_BITS - 1)\n"); flint_abort(); } } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); flint_free(limbs); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-set_signed_uiui.c000066400000000000000000000032401414523752600204520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_signed_uiui...."); fflush(stdout); 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); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-set_signed_uiuiui.c000066400000000000000000000035061414523752600210150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_signed_uiuiui...."); fflush(stdout); 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); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-set_ui_smod.c000066400000000000000000000027251414523752600176140ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("set_ui_smod...."); fflush(stdout); 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)) { 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(mz); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-set_uiui.c000066400000000000000000000027021414523752600171230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_uiui...."); fflush(stdout); 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); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-setbit.c000066400000000000000000000032611414523752600165700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("setbit...."); fflush(stdout); for (i = 0; i < 100000 * 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)); 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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(z); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-sgn.c000066400000000000000000000022761414523752600160720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sgn...."); fflush(stdout); 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); abort(); } fmpz_clear(a); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-size.c000066400000000000000000000023011414523752600162420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("size...."); fflush(stdout); 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); abort(); } fmpz_clear(a); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-sizeinbase.c000066400000000000000000000027451414523752600174400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sizeinbase...."); fflush(stdout); 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); abort(); } fmpz_clear(a); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-smod.c000066400000000000000000000130031414523752600162330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("smod...."); fflush(stdout); for (i = 0; i < 200000 * flint_test_multiplier(); i++) { 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, 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); } fmpz_smod(c, a, b); fmpz_sub(d, a, c); fmpz_mod(d, d, b); if (!fmpz_is_zero(d)) { 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"); 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"); 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"); flint_abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(e); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, d; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_randtest_not_zero(a, state, 200); fmpz_set(b, a); fmpz_smod(c, a, a); fmpz_smod(d, a, b); result = (fmpz_cmp(c, d) == 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("c = "); fmpz_print(c); flint_printf("\n"); flint_printf("d = "); fmpz_print(d); flint_printf("\n"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, d; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); fmpz_set(c, a); fmpz_smod(a, a, b); fmpz_smod(d, c, b); result = (fmpz_cmp(a, d) == 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("c = "); fmpz_print(c); flint_printf("\n"); flint_printf("d = "); fmpz_print(d); flint_printf("\n"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, d; fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(d); fmpz_randtest(a, state, 200); fmpz_randtest_not_zero(b, state, 200); fmpz_set(c, b); fmpz_smod(b, a, b); fmpz_smod(d, a, c); result = (fmpz_cmp(b, d) == 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("c = "); fmpz_print(c); flint_printf("\n"); flint_printf("d = "); fmpz_print(d); flint_printf("\n"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-sqrt.c000066400000000000000000000042131414523752600162650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrt...."); fflush(stdout); /* 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); fmpz_sqrt(f, g); mpz_sqrt(mf, mg); fmpz_get_mpz(mf2, f); result = (mpz_cmp(mf2, mf) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("mf = %Zd, mf2 = %Zd, mg = %Zd\n", mf, mf2, mg); abort(); } fmpz_clear(f); fmpz_clear(g); mpz_clear(mf); mpz_clear(mf2); mpz_clear(mg); } /* Check aliasing of f and g */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f; mpz_t mf, mf2; fmpz_init(f); mpz_init(mf); mpz_init(mf2); fmpz_randtest(f, state, 200); fmpz_abs(f, f); fmpz_get_mpz(mf, f); fmpz_sqrt(f, f); mpz_sqrt(mf, mf); fmpz_get_mpz(mf2, f); result = (mpz_cmp(mf, mf2) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("mf = %Zd, mf2 = %Zd\n", mf, mf2); abort(); } fmpz_clear(f); mpz_clear(mf); mpz_clear(mf2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-sqrtmod.c000066400000000000000000000063511414523752600167720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrtmod...."); fflush(stdout); 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)); 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"); 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)); 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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(d); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-sqrtrem.c000066400000000000000000000062601414523752600167750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrtrem...."); fflush(stdout); /* Comparison with mpz routines */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t f, r, g; mpz_t mf, mf2, mr, mg; 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); fmpz_sqrtrem(f, r, g); mpz_sqrtrem(mf, mr, mg); fmpz_get_mpz(mf2, f); result = (mpz_cmp(mf2, mf) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("mf = %Zd, mf2 = %Zd, mr = %Zd, mg = %Zd\n", mf, mf2, mr, mg); abort(); } fmpz_clear(f); fmpz_clear(r); fmpz_clear(g); mpz_clear(mf); mpz_clear(mf2); mpz_clear(mr); mpz_clear(mg); } /* Check aliasing of r and g */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, f; mpz_t ma, mf, mf2; fmpz_init(a); fmpz_init(f); mpz_init(ma); mpz_init(mf); mpz_init(mf2); fmpz_randtest(a, state, 200); fmpz_abs(a, a); fmpz_get_mpz(ma, a); fmpz_sqrtrem(f, a, a); mpz_sqrtrem(mf, ma, ma); fmpz_get_mpz(mf2, f); result = (mpz_cmp(mf, mf2) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("ma = %Zd, mf = %Zd, mf2 = %Zd\n", ma, mf, mf2); abort(); } fmpz_clear(a); fmpz_clear(f); mpz_clear(ma); mpz_clear(mf); mpz_clear(mf2); } /* Check aliasing of f and g */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t r, f; mpz_t mr, mf, mf2; fmpz_init(r); fmpz_init(f); mpz_init(mr); mpz_init(mf); mpz_init(mf2); fmpz_randtest(f, state, 200); fmpz_abs(f, f); fmpz_get_mpz(mf, f); fmpz_sqrtrem(f, r, f); mpz_sqrtrem(mf, mr, mf); fmpz_get_mpz(mf2, f); result = (mpz_cmp(mf, mf2) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("mr = %Zd, mf = %Zd, mf2 = %Zd\n", mr, mf, mf2); abort(); } fmpz_clear(r); fmpz_clear(f); mpz_clear(mr); mpz_clear(mf); mpz_clear(mf2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-sub.c000066400000000000000000000076331414523752600160760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_sub(c, a, b); mpz_sub(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); fmpz_sub(c, a, a); mpz_sub(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_sub(a, a, b); mpz_sub(f, d, e); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_sub(b, a, b); mpz_sub(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-sub_ui.c000066400000000000000000000042541414523752600165670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub_ui...."); fflush(stdout); 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); fmpz_sub_ui(b, a, x); flint_mpz_sub_ui(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); 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, f; ulong x; fmpz_init(a); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randtest(state); fmpz_sub_ui(a, a, x); flint_mpz_sub_ui(e, d, x); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-submul.c000066400000000000000000000077071414523752600166160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("submul...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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_get_mpz(d, a); fmpz_get_mpz(e, b); fmpz_get_mpz(f, c); fmpz_submul(c, a, b); mpz_submul(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_randtest(c, state, 200); fmpz_get_mpz(d, a); fmpz_get_mpz(f, c); fmpz_submul(c, a, a); mpz_submul(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; 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); fmpz_submul(a, a, b); mpz_submul(d, d, e); fmpz_get_mpz(f, a); result = (mpz_cmp(d, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd\n", d, e, f); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f; 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); fmpz_submul(b, a, b); mpz_submul(e, d, e); fmpz_get_mpz(f, b); result = (mpz_cmp(f, e) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd\n", d, e, f); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-submul_si.c000066400000000000000000000044771414523752600173120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "long_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("submul_si...."); fflush(stdout); 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); fmpz_submul_si(b, a, x); flint_mpz_init_set_si(xx, x); mpz_submul(e, d, xx); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, xx = %Zd\n", d, e, f, xx); flint_abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(xx); 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, xx; slong 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_submul_si(a, a, x); flint_mpz_init_set_si(xx, x); mpz_submul(d, d, xx); fmpz_get_mpz(e, a); result = (mpz_cmp(d, e) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, xx = %Zd\n", d, e, xx); flint_abort(); } fmpz_clear(a); mpz_clear(xx); mpz_clear(d); mpz_clear(e); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-submul_ui.c000066400000000000000000000043031414523752600173000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("submul_ui...."); fflush(stdout); 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); fmpz_submul_ui(b, a, x); flint_mpz_submul_ui(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, x = %Mu\n", d, e, f, x); 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_submul_ui(a, a, x); flint_mpz_submul_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); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-swap.c000066400000000000000000000025021414523752600162450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("swap...."); fflush(stdout); 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); if (!result) { flint_printf("FAIL:\n"); gmp_printf("c = %Zd, d = %Zd\n", c, d); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(c); mpz_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-tdiv_q.c000066400000000000000000000100041414523752600165550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("tdiv_q...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_tdiv_q(c, a, b); mpz_tdiv_q(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest_not_zero(a, state, 200); fmpz_get_mpz(d, a); fmpz_tdiv_q(c, a, a); mpz_tdiv_q(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_tdiv_q(a, a, b); mpz_tdiv_q(f, d, e); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_tdiv_q(b, a, b); mpz_tdiv_q(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-tdiv_q_2exp.c000066400000000000000000000043051414523752600175220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("tdiv_q_2exp...."); fflush(stdout); 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); fmpz_tdiv_q_2exp(b, a, x); mpz_tdiv_q_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); 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, f; ulong x; fmpz_init(a); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); fmpz_tdiv_q_2exp(a, a, x); mpz_tdiv_q_2exp(e, d, x); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-tdiv_q_si.c000066400000000000000000000045431414523752600172630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("tdiv_q_si...."); fflush(stdout); 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); fmpz_tdiv_q_si(c, a, b); mpz_tdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (1):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { slong b; fmpz_t a; mpz_t d, e, f, g; fmpz_init(a); 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); fmpz_tdiv_q_si(a, a, b); mpz_tdiv_q(f, d, e); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (2):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-tdiv_q_ui.c000066400000000000000000000045441414523752600172660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("tdiv_q_ui...."); fflush(stdout); 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); fmpz_tdiv_q_ui(c, a, b); mpz_tdiv_q(f, d, e); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (1):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong b; fmpz_t a; mpz_t d, e, f, g; fmpz_init(a); 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); fmpz_tdiv_q_ui(a, a, b); mpz_tdiv_q(f, d, e); fmpz_get_mpz(g, a); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL (2):\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g); abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-tdiv_qr.c000066400000000000000000000145741414523752600167570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("tdiv_qr...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_tdiv_qr(c, r, a, b); 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); 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); 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); } /* Check aliasing of c and a */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_tdiv_qr(a, r, a, b); mpz_tdiv_qr(f, s, d, e); fmpz_get_mpz(g, a); 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); 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); } /* Check aliasing of c and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_tdiv_qr(b, r, a, b); mpz_tdiv_qr(f, s, d, e); fmpz_get_mpz(g, b); 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); 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); } /* Check aliasing of r and a */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_tdiv_qr(c, a, a, b); mpz_tdiv_qr(f, s, d, e); fmpz_get_mpz(g, c); fmpz_get_mpz(h, a); 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); 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); } /* Check aliasing of r and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c, r; mpz_t d, e, f, g, h, s; 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); fmpz_tdiv_qr(c, b, a, b); mpz_tdiv_qr(f, s, d, e); fmpz_get_mpz(g, c); fmpz_get_mpz(h, b); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-tdiv_r_2exp.c000066400000000000000000000043311414523752600175220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("tdiv_r_2exp...."); fflush(stdout); 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); fmpz_tdiv_r_2exp(b, a, x); mpz_tdiv_r_2exp(e, d, x); fmpz_get_mpz(f, b); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL 1:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); 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, f; ulong x; fmpz_init(a); mpz_init(d); mpz_init(e); mpz_init(f); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); x = n_randint(state, 200); fmpz_tdiv_r_2exp(a, a, x); mpz_tdiv_r_2exp(e, d, x); fmpz_get_mpz(f, a); result = (mpz_cmp(e, f) == 0); if (!result) { flint_printf("FAIL 2:\n"); gmp_printf("d = %Zd, e = %Zd, f = %Zd, exp = %Mu\n", d, e, f, x); flint_abort(); } fmpz_clear(a); mpz_clear(d); mpz_clear(e); mpz_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz/test/t-tdiv_ui.c000066400000000000000000000024641414523752600167450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("tdiv_ui...."); fflush(stdout); 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); if (!result) { flint_printf("FAIL:\n"); gmp_printf ("b = %Zd, x = %wu, r1 = %wu, r2 = %wu\n", b, x, r1, r2); abort(); } fmpz_clear(a); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-tstbit.c000066400000000000000000000025241414523752600166100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("tstbit...."); fflush(stdout); 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); abort(); } fmpz_clear(a); mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-val2.c000066400000000000000000000027061414523752600161450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("val2...."); fflush(stdout); 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); abort(); } fmpz_clear(x); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-xgcd.c000066400000000000000000000205671414523752600162330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("xgcd...."); fflush(stdout); /* Test aliasing of d and f, a and g */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t d, a, b, c, f, g, F, G; fmpz_init(d); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(f); fmpz_init(g); fmpz_init(F); fmpz_init(G); 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); fmpz_set(f, F); fmpz_set(g, G); fmpz_xgcd(d, a, b, f, g); fmpz_xgcd(f, g, c, f, g); result = (fmpz_equal(d, f) && fmpz_equal(b, c) && fmpz_equal(a, g)); 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("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); flint_printf("F = "), fmpz_print(F), flint_printf("\n"); flint_printf("G = "), fmpz_print(G), flint_printf("\n"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(f); fmpz_clear(g); fmpz_clear(F); fmpz_clear(G); } /* Test aliasing of a and f, d and g */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t d, a, b, c, f, g, F, G; fmpz_init(d); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(f); fmpz_init(g); fmpz_init(F); fmpz_init(G); 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); fmpz_set(f, F); fmpz_set(g, G); fmpz_xgcd(d, a, b, f, g); fmpz_xgcd(g, f, c, f, g); result = (fmpz_equal(d, g) && fmpz_equal(b, c) && fmpz_equal(a, f)); 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("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); flint_printf("F = "), fmpz_print(F), flint_printf("\n"); flint_printf("G = "), fmpz_print(G), flint_printf("\n"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(f); fmpz_clear(g); fmpz_clear(F); fmpz_clear(G); } /* Test aliasing of d and f, b and g */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t d, a, b, c, f, g, F, G; fmpz_init(d); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(f); fmpz_init(g); fmpz_init(F); fmpz_init(G); 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); fmpz_set(f, F); fmpz_set(g, G); fmpz_xgcd(d, a, b, f, g); fmpz_xgcd(f, c, g, f, g); result = (fmpz_equal(d, f) && fmpz_equal(a, c) && fmpz_equal(b, g)); 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("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); flint_printf("F = "), fmpz_print(F), flint_printf("\n"); flint_printf("G = "), fmpz_print(G), flint_printf("\n"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(f); fmpz_clear(g); fmpz_clear(F); fmpz_clear(G); } /* Test aliasing of b and f, d and g */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t d, a, b, c, f, g, F, G; fmpz_init(d); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(f); fmpz_init(g); fmpz_init(F); fmpz_init(G); 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); fmpz_set(f, F); fmpz_set(g, G); fmpz_xgcd(d, a, b, f, g); fmpz_xgcd(g, c, f, f, g); result = (fmpz_equal(d, g) && fmpz_equal(a, c) && fmpz_equal(b, f)); 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("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); flint_printf("F = "), fmpz_print(F), flint_printf("\n"); flint_printf("G = "), fmpz_print(G), flint_printf("\n"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(f); fmpz_clear(g); fmpz_clear(F); fmpz_clear(G); } /* 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; 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); fmpz_xgcd(d, a, b, f, g); fmpz_mul(t1, a, f); fmpz_mul(t2, b, g); fmpz_add(t1, t1, t2); result = fmpz_equal(t1, d) && fmpz_sgn(d) >= 0; 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("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"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(b); fmpz_clear(f); fmpz_clear(g); fmpz_clear(t1); fmpz_clear(t2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-xgcd_canonical_bezout.c000066400000000000000000000420431414523752600216230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int ix, result; fmpz_t maxval; fmpz_t nd, na, nb, nf, ng; FLINT_TEST_INIT(state); 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); flint_printf("xgcd_canonical_bezout...."); fflush(stdout); 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"); 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"); 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"); 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"); 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"); 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"); 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"); abort(); } } /* 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"); 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; fmpz_init(tmp); fmpz_randm(nf, state, maxval); fmpz_randm(ng, state, maxval); fmpz_xgcd_canonical_bezout(nd, na, nb, nf, ng); 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); 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"); abort(); } fmpz_clear(tmp); } /* Test aliasing of d and f, a and g */ for (ix = 0; ix < 1000 * flint_test_multiplier(); ix++) { fmpz_t d, a, b, c, f, g, F, G; fmpz_init(d); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(f); fmpz_init(g); fmpz_init(F); fmpz_init(G); 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); fmpz_set(f, F); fmpz_set(g, G); fmpz_xgcd(d, a, b, f, g); fmpz_xgcd(f, g, c, f, g); result = (fmpz_equal(d, f) && fmpz_equal(b, c) && fmpz_equal(a, g)); 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("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); flint_printf("F = "), fmpz_print(F), flint_printf("\n"); flint_printf("G = "), fmpz_print(G), flint_printf("\n"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(f); fmpz_clear(g); fmpz_clear(F); fmpz_clear(G); } /* Test aliasing of a and f, d and g */ for (ix = 0; ix < 1000 * flint_test_multiplier(); ix++) { fmpz_t d, a, b, c, f, g, F, G; fmpz_init(d); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(f); fmpz_init(g); fmpz_init(F); fmpz_init(G); 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); fmpz_set(f, F); fmpz_set(g, G); fmpz_xgcd(d, a, b, f, g); fmpz_xgcd(g, f, c, f, g); result = (fmpz_equal(d, g) && fmpz_equal(b, c) && fmpz_equal(a, f)); 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("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); flint_printf("F = "), fmpz_print(F), flint_printf("\n"); flint_printf("G = "), fmpz_print(G), flint_printf("\n"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(f); fmpz_clear(g); fmpz_clear(F); fmpz_clear(G); } /* Test aliasing of d and f, b and g */ for (ix = 0; ix < 1000 * flint_test_multiplier(); ix++) { fmpz_t d, a, b, c, f, g, F, G; fmpz_init(d); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(f); fmpz_init(g); fmpz_init(F); fmpz_init(G); 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); fmpz_set(f, F); fmpz_set(g, G); fmpz_xgcd(d, a, b, f, g); fmpz_xgcd(f, c, g, f, g); result = (fmpz_equal(d, f) && fmpz_equal(a, c) && fmpz_equal(b, g)); 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("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); flint_printf("F = "), fmpz_print(F), flint_printf("\n"); flint_printf("G = "), fmpz_print(G), flint_printf("\n"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(f); fmpz_clear(g); fmpz_clear(F); fmpz_clear(G); } /* Test aliasing of b and f, d and g */ for (ix = 0; ix < 1000 * flint_test_multiplier(); ix++) { fmpz_t d, a, b, c, f, g, F, G; fmpz_init(d); fmpz_init(a); fmpz_init(b); fmpz_init(c); fmpz_init(f); fmpz_init(g); fmpz_init(F); fmpz_init(G); 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); fmpz_set(f, F); fmpz_set(g, G); fmpz_xgcd(d, a, b, f, g); fmpz_xgcd(g, c, f, f, g); result = (fmpz_equal(d, g) && fmpz_equal(a, c) && fmpz_equal(b, f)); 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("b = "), fmpz_print(b), flint_printf("\n"); flint_printf("c = "), fmpz_print(c), flint_printf("\n"); flint_printf("f = "), fmpz_print(f), flint_printf("\n"); flint_printf("g = "), fmpz_print(g), flint_printf("\n"); flint_printf("F = "), fmpz_print(F), flint_printf("\n"); flint_printf("G = "), fmpz_print(G), flint_printf("\n"); abort(); } fmpz_clear(d); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(f); fmpz_clear(g); fmpz_clear(F); fmpz_clear(G); } fmpz_clear(nd); fmpz_clear(na); fmpz_clear(nb); fmpz_clear(nf); fmpz_clear(ng); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-xgcd_partial.c000066400000000000000000000042061414523752600177370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("xgcd_partial...."); fflush(stdout); /* 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"); abort(); } fmpz_clear(co1); fmpz_clear(co2); fmpz_clear(f); fmpz_clear(g); fmpz_clear(L); fmpz_clear(t1); fmpz_clear(t2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/test/t-xor.c000066400000000000000000000076371414523752600161210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("xor...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b, c; mpz_t d, e, f, g; 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); fmpz_xor(c, a, b); mpz_xor(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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Check aliasing of a and b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, c; mpz_t d, f, g; fmpz_init(a); fmpz_init(c); mpz_init(d); mpz_init(f); mpz_init(g); fmpz_randtest(a, state, 200); fmpz_get_mpz(d, a); fmpz_xor(c, a, a); mpz_xor(f, d, d); fmpz_get_mpz(g, c); result = (mpz_cmp(f, g) == 0); if (!result) { flint_printf("FAIL:\n"); gmp_printf("d = %Zd, f = %Zd, g = %Zd\n", d, f, g); abort(); } fmpz_clear(a); fmpz_clear(c); mpz_clear(d); mpz_clear(f); mpz_clear(g); } /* Test aliasing of a and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_xor(a, a, b); mpz_xor(f, d, e); fmpz_get_mpz(g, a); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } /* Test aliasing of b and c */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { fmpz_t a, b; mpz_t d, e, f, g; fmpz_init(a); fmpz_init(b); 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); fmpz_xor(b, a, b); mpz_xor(f, d, e); fmpz_get_mpz(g, b); 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); abort(); } fmpz_clear(a); fmpz_clear(b); mpz_clear(d); mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz/tstbit.c000066400000000000000000000013411414523752600153640ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/fmpz/val2.c000066400000000000000000000017031414523752600147210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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 count_trailing_zeros(t, 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; } count_trailing_zeros(u, *d); t += u; } return t; } flint2-2.8.4/fmpz/xgcd.c000066400000000000000000000044331414523752600150050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #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); } } flint2-2.8.4/fmpz/xgcd_canonical_bezout.c000066400000000000000000000052211414523752600204000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" 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); } flint2-2.8.4/fmpz/xgcd_partial.c000066400000000000000000000054211414523752600165170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz/xor.c000066400000000000000000000033321414523752600146650ustar00rootroot00000000000000/* Copyright (C) 2012 Thomas M. DuBuisson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" 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); } } } flint2-2.8.4/fmpz_factor.h000066400000000000000000000146201414523752600154220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define FMPZ_FACTOR_INLINE static __inline__ #endif #include #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]; /* Utility functions *********************************************************/ FLINT_DLL void fmpz_factor_init(fmpz_factor_t factor); FLINT_DLL void fmpz_factor_clear(fmpz_factor_t factor); FLINT_DLL void fmpz_factor_print(const fmpz_factor_t factor); FLINT_DLL void _fmpz_factor_fit_length(fmpz_factor_t factor, slong len); FLINT_DLL void _fmpz_factor_append_ui(fmpz_factor_t factor, mp_limb_t p, ulong exp); FLINT_DLL void _fmpz_factor_append(fmpz_factor_t factor, const fmpz_t p, ulong exp); FLINT_DLL void _fmpz_factor_set_length(fmpz_factor_t factor, slong newlen); FLINT_DLL void _fmpz_factor_concat(fmpz_factor_t factor1, fmpz_factor_t factor2, ulong exp); /* Factoring *****************************************************************/ FLINT_DLL void _fmpz_factor_extend_factor_ui(fmpz_factor_t factor, mp_limb_t n); FLINT_DLL int fmpz_factor_trial_range(fmpz_factor_t factor, const fmpz_t n, ulong start, ulong num_primes); FLINT_DLL int fmpz_factor_trial(fmpz_factor_t factor, const fmpz_t n, slong num_primes); FLINT_DLL void fmpz_factor(fmpz_factor_t factor, const fmpz_t n); FLINT_DLL void fmpz_factor_no_trial(fmpz_factor_t factor, const fmpz_t n); FLINT_DLL int fmpz_factor_smooth(fmpz_factor_t factor, const fmpz_t n, slong bits, int proved); FLINT_DLL void fmpz_factor_si(fmpz_factor_t factor, slong n); FLINT_DLL int fmpz_factor_pp1(fmpz_t factor, const fmpz_t n, ulong B1, ulong B2_sqrt, ulong c); FLINT_DLL void fmpz_factor_refine(fmpz_factor_t res, const fmpz_factor_t f); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 *****************************************************************/ FLINT_DLL void fmpz_factor_expand_iterative(fmpz_t n, const fmpz_factor_t factor); FLINT_DLL void fmpz_factor_expand_multiexp(fmpz_t n, const fmpz_factor_t factor); FLINT_DLL void fmpz_factor_expand(fmpz_t n, const fmpz_factor_t factor); /* Multiplicative functions **************************************************/ FLINT_DLL void fmpz_factor_euler_phi(fmpz_t res, const fmpz_factor_t fac); FLINT_DLL int fmpz_factor_moebius_mu(const fmpz_factor_t fac); FLINT_DLL void fmpz_factor_divisor_sigma(fmpz_t res, const fmpz_factor_t fac, ulong k); /* 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]; FLINT_DLL void fmpz_factor_ecm_init(ecm_t ecm_inf, mp_limb_t sz); FLINT_DLL void fmpz_factor_ecm_clear(ecm_t ecm_inf); FLINT_DLL void fmpz_factor_ecm_addmod(mp_ptr a, mp_ptr b, mp_ptr c, mp_ptr n, mp_limb_t n_size); FLINT_DLL void fmpz_factor_ecm_submod(mp_ptr x, mp_ptr a, mp_ptr b, mp_ptr n, mp_limb_t n_size); FLINT_DLL void fmpz_factor_ecm_double(mp_ptr x, mp_ptr z, mp_ptr x0, mp_ptr z0, mp_ptr n, ecm_t ecm_inf); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int fmpz_factor_ecm_select_curve(mp_ptr f, mp_ptr sig, mp_ptr n, ecm_t ecm_inf); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 *******************************************************************/ FLINT_DLL void fmpz_factor_get_fmpz(fmpz_t z, const fmpz_factor_t factor, slong i); #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpz_factor/000077500000000000000000000000001414523752600152465ustar00rootroot00000000000000flint2-2.8.4/fmpz_factor/append.c000066400000000000000000000013351414523752600166630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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++; } flint2-2.8.4/fmpz_factor/append_ui.c000066400000000000000000000013401414523752600173540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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++; } flint2-2.8.4/fmpz_factor/clear.c000066400000000000000000000011651414523752600165030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void fmpz_factor_clear(fmpz_factor_t factor) { _fmpz_vec_clear(factor->p, factor->alloc); flint_free(factor->exp); } flint2-2.8.4/fmpz_factor/concat.c000066400000000000000000000015671414523752600166720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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; } flint2-2.8.4/fmpz_factor/ecm.c000066400000000000000000000163371414523752600161700ustar00rootroot00000000000000/* 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 2.1 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 #include "flint.h" #include "fmpz.h" #include "mpn_extras.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, *mpz_ptr; 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))) { count_leading_zeros(ecm_inf->normbits, fmpz_get_ui(n_in)); n[0] = fmpz_get_ui(n_in); n[0] <<= ecm_inf->normbits; } else { mpz_ptr = COEFF_TO_PTR(* n_in); count_leading_zeros(ecm_inf->normbits, mpz_ptr->_mp_d[n_size - 1]); if (ecm_inf->normbits) mpn_lshift(n, mpz_ptr->_mp_d, n_size, ecm_inf->normbits); else flint_mpn_copyi(n, mpz_ptr->_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_printf("Exception (ecm). B1 > B2 encountered.\n"); flint_abort(); } 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 { mpz_ptr = COEFF_TO_PTR(*sig); if (ecm_inf->normbits) { cy = mpn_lshift(mpsig, mpz_ptr->_mp_d, mpz_ptr->_mp_size, ecm_inf->normbits); if (cy) mpsig[mpz_ptr->_mp_size] = cy; } else { flint_mpn_copyi(mpsig, mpz_ptr->_mp_d, mpz_ptr->_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; } flint2-2.8.4/fmpz_factor/ecm_add.c000066400000000000000000000060461414523752600167740ustar00rootroot00000000000000/* 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 2.1 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 #include "flint.h" #include "fmpz.h" #include "mpn_extras.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); } flint2-2.8.4/fmpz_factor/ecm_addmod.c000066400000000000000000000014721414523752600174720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "mpn_extras.h" /* a = (b + c) mod n Not a normal add mod function, assumes n is normalized (higest 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); } flint2-2.8.4/fmpz_factor/ecm_clear.c000066400000000000000000000014001414523752600173170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "mpn_extras.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); } flint2-2.8.4/fmpz_factor/ecm_double.c000066400000000000000000000043541414523752600175160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "mpn_extras.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); } flint2-2.8.4/fmpz_factor/ecm_init.c000066400000000000000000000024631414523752600172060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "mpn_extras.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; } flint2-2.8.4/fmpz_factor/ecm_mul_montgomery_ladder.c000066400000000000000000000044561414523752600226370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "mpn_extras.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; } flint2-2.8.4/fmpz_factor/ecm_select_curve.c000066400000000000000000000145241414523752600207270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "mpn_extras.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; } flint2-2.8.4/fmpz_factor/ecm_stage_I.c000066400000000000000000000032161414523752600176130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "mpn_extras.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; } flint2-2.8.4/fmpz_factor/ecm_stage_II.c000066400000000000000000000123731414523752600177300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpn_extras.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; } flint2-2.8.4/fmpz_factor/ecm_submod.c000066400000000000000000000017171414523752600175350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "mpn_extras.h" /* x = (a - b) mod n Not a normal sub mod function, assumes n is normalized (higest 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; } flint2-2.8.4/fmpz_factor/expand.c000066400000000000000000000010461414523752600166720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" void fmpz_factor_expand(fmpz_t n, const fmpz_factor_t factor) { fmpz_factor_expand_multiexp(n, factor); } flint2-2.8.4/fmpz_factor/expand_iterative.c000066400000000000000000000013661414523752600207530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } flint2-2.8.4/fmpz_factor/expand_multiexp.c000066400000000000000000000032721414523752600206240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } flint2-2.8.4/fmpz_factor/extend_factor_ui.c000066400000000000000000000021001414523752600207250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.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]; } } flint2-2.8.4/fmpz_factor/factor.c000066400000000000000000000067101414523752600166740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpn_extras.h" #include "ulong_extras.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_p(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_p(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; } flint2-2.8.4/fmpz_factor/factor_no_trial.c000066400000000000000000000042101414523752600205540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpn_extras.h" #include "ulong_extras.h" #include "qsieve.h" #include "thread_support.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); } } flint2-2.8.4/fmpz_factor/factor_pp1.c000066400000000000000000000353231414523752600174560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #define ulong mp_limb_t #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "mpn_extras.h" #include "ulong_extras.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_print(mp_srcptr x, mp_srcptr y, mp_size_t nn, ulong norm) { mp_ptr tx = flint_malloc(nn*sizeof(mp_limb_t)); mp_ptr ty = flint_malloc(nn*sizeof(mp_limb_t)); if (norm) { mpn_rshift(tx, x, nn, norm); mpn_rshift(ty, y, nn, norm); } else { flint_mpn_copyi(tx, x, nn); flint_mpn_copyi(ty, y, nn); } flint_printf("["), gmp_printf("%Nd", tx, nn), flint_printf(", "), gmp_printf("%Nd", ty, nn), flint_printf("]"); flint_free(tx); flint_free(ty); } 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); count_leading_zeros(norm, n[0]); n[0] <<= norm; } else { mp_ptr np = COEFF_TO_PTR(*n_in)->_mp_d; count_leading_zeros(norm, 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 ** tree, ** 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 tree = _fmpz_mod_poly_tree_alloc(num_roots); _fmpz_mod_poly_tree_build(tree, roots, num_roots, n_in); tree2 = _fmpz_mod_poly_tree_alloc(num_roots); _fmpz_mod_poly_tree_build(tree2, roots2, num_roots, n_in); fmpz_poly_mul(tree2[FLINT_CLOG2(num_roots)], tree2[FLINT_CLOG2(num_roots)-1], tree2[FLINT_CLOG2(num_roots)-1]+1); #if DEBUG flint_printf("built trees\n"); #endif _fmpz_mod_poly_evaluate_fmpz_vec_fast_precomp(evals, tree2[FLINT_CLOG2(num_roots)]->coeffs, tree2[FLINT_CLOG2(num_roots)]->length, tree, num_roots, n_in); _fmpz_mod_poly_tree_free(tree, num_roots); _fmpz_mod_poly_tree_free(tree2, num_roots); #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; } flint2-2.8.4/fmpz_factor/factor_si.c000066400000000000000000000014621414523752600173660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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); } } flint2-2.8.4/fmpz_factor/factor_smooth.c000066400000000000000000000173611414523752600202710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpn_extras.h" #include "ulong_extras.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_printf("(fmpz_factor_smooth) Number of bits must be at least 1\n"); flint_abort(); } 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]]; exp = 1; xsize = flint_mpn_divexact_1(xd, xsize, p); /* Check if p^2 divides n */ if (flint_mpn_divisible_1_p(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_p(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; } flint2-2.8.4/fmpz_factor/factor_trial.c000066400000000000000000000061711414523752600200700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpn_extras.h" #include "ulong_extras.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_printf("(fmpz_factor_trial) Number of primes must be in 0..3512\n"); flint_abort(); } 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]]; exp = 1; xsize = flint_mpn_divexact_1(xd, xsize, p); /* Check if p^2 divides n */ if (flint_mpn_divisible_1_p(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_p(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; } flint2-2.8.4/fmpz_factor/factor_trial_range.c000066400000000000000000000064311414523752600212430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpn_extras.h" #include "ulong_extras.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_p(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_p(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; } flint2-2.8.4/fmpz_factor/fit_length.c000066400000000000000000000020761414523752600175420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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; } } flint2-2.8.4/fmpz_factor/init.c000066400000000000000000000012411414523752600163530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void fmpz_factor_init(fmpz_factor_t factor) { factor->sign = 1; factor->p = NULL; factor->exp = NULL; factor->num = 0; factor->alloc = 0; } flint2-2.8.4/fmpz_factor/inlines.c000066400000000000000000000012621414523752600170540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_FACTOR_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "fmpz.h" void fmpz_factor_get_fmpz(fmpz_t z, const fmpz_factor_t factor, slong i) { fmpz_set(z, factor->p + i); } flint2-2.8.4/fmpz_factor/pollard_brent.c000066400000000000000000000100631414523752600202410ustar00rootroot00000000000000/* 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 2.1 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 #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" #include "mpn_extras.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, *mpz_ptr; 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; count_leading_zeros(normbits, 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 { mpz_ptr = COEFF_TO_PTR(*fy); temp = mpz_ptr->_mp_d; size = mpz_ptr->_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 { mpz_ptr = COEFF_TO_PTR(*fa); temp = mpz_ptr->_mp_d; size = mpz_ptr->_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; } flint2-2.8.4/fmpz_factor/pollard_brent_single.c000066400000000000000000000203611414523752600216040ustar00rootroot00000000000000/* 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 2.1 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 #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" #include "mpn_extras.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 funtion */ 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 paramete 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, *mpz_ptr; 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); count_leading_zeros(normbits, 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; } mpz_ptr = COEFF_TO_PTR(*yi); temp = COEFF_TO_PTR(*n_in)->_mp_d; count_leading_zeros(normbits, 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; count_leading_zeros(normbits, 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 { mpz_ptr = COEFF_TO_PTR(*yi); temp = mpz_ptr->_mp_d; size = mpz_ptr->_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 { mpz_ptr = COEFF_TO_PTR(*ai); temp = mpz_ptr->_mp_d; size = mpz_ptr->_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; } flint2-2.8.4/fmpz_factor/print.c000066400000000000000000000020511414523752600165440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" void fmpz_factor_print(const fmpz_factor_t factor) { slong i; if (factor->sign == 0) { flint_printf("0"); return; } if (factor->sign == -1) { if (factor->num) flint_printf("-1 * "); else flint_printf("-1"); } for (i = 0; i < factor->num; i++) { fmpz_print(factor->p + i); if (factor->exp[i] != UWORD(1)) flint_printf("^%wu", factor->exp[i]); if (i != factor->num - 1) flint_printf(" * "); } } flint2-2.8.4/fmpz_factor/profile/000077500000000000000000000000001414523752600167065ustar00rootroot00000000000000flint2-2.8.4/fmpz_factor/profile/p-factor_pp1.c000066400000000000000000000025261414523752600213520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "flint.h" #include "fmpz.h" #include "fmpz_factor.h" int main(void) { fmpz_t n, p; ulong c; ulong B1; fmpz_init(n); fmpz_init(p); FLINT_TEST_INIT(state); while(1) { flint_printf("Enter number to be factored: "); fflush(stdout); if (!fmpz_read(n)) { flint_printf("Read failed\n"); abort(); } flint_printf("Enter B1: "); fflush(stdout); if (!flint_scanf("%wu", &B1)) { flint_printf("Read failed\n"); 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; } flint2-2.8.4/fmpz_factor/refine.c000066400000000000000000000252231414523752600166660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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_printf("aliasing issue...\n"); abort(); } 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); } flint2-2.8.4/fmpz_factor/set_length.c000066400000000000000000000013531414523752600175500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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; } flint2-2.8.4/fmpz_factor/test/000077500000000000000000000000001414523752600162255ustar00rootroot00000000000000flint2-2.8.4/fmpz_factor/test/t-ecm.c000066400000000000000000000057261414523752600174100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main(void) { fmpz_t prime1, prime2, primeprod, fac, modval; int i, j, k, fails; FLINT_TEST_INIT(state); fmpz_init(prime1); fmpz_init(prime2); fmpz_init(primeprod); fmpz_init(fac); fmpz_init(modval); fails = 0; flint_printf("ecm...."); fflush(stdout); 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); abort(); } } } } if (fails > flint_test_multiplier()) { printf("FAIL : ECM failed too many times (%d times)\n", fails); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_factor/test/t-factor.c000066400000000000000000000175331414523752600201210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" 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"); 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"); 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"); abort(); } } fmpz_clear(m); fmpz_factor_clear(factor); } 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); } int main(void) { int i, j, k; fmpz_t x, y, z, n; fmpz_factor_t factors; mpz_t y1; FLINT_TEST_INIT(state); flint_printf("factor...."); fflush(stdout); fmpz_init(x); mpz_init(y1); /* 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); /* Small integers */ for (i = -10000; i < 10000; i++) { fmpz_set_si(x, i); check(x); } /* Powers */ for (i = 1; i < 250; i++) { for (j = 0; j < 250; j++) { fmpz_set_ui(x, i); fmpz_pow_ui(x, x, j); check(x); } } /* Factorials */ for (i = 0; i < 1000; i++) { flint_mpz_fac_ui(y1, i); fmpz_set_mpz(x, y1); check(x); } /* Powers of factorials */ for (i = 0; i < 100; i++) { for (j = 1; j < 5; j++) { flint_mpz_fac_ui(y1, i); fmpz_set_mpz(x, y1); fmpz_pow_ui(x, x, j); check(x); } } /* Whole limbs */ for (i = 0; i < 1000; i++) { fmpz_set_ui(x, n_randtest(state)); if (n_randint(state, 2)) fmpz_neg(x, x); check(x); } /* Large negative integers */ fmpz_set_ui(x, 10); fmpz_pow_ui(x, x, 100); fmpz_neg(x, x); check(x); flint_mpz_fac_ui(y1, 50); mpz_neg(y1, y1); fmpz_set_mpz(x, y1); check(x); mpz_clear(y1); fmpz_init(y); fmpz_init(z); fmpz_init(n); for (i = 0; i < 20; i++) /* Test random n, two factors */ { randprime(x, state, 50); randprime(y, state, 50); 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); abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 20; i++) /* Test random n, three factors */ { randprime(x, state, 40); randprime(y, state, 40); randprime(z, state, 40); 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); abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 20; i++) /* Test random n, small factors */ { randprime(x, state, 10); randprime(y, state, 10); randprime(z, state, 40); 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); abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 5; i++) /* Test random squares */ { randprime(x, state, 40); 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); abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 5; i++) /* Test random cubes */ { randprime(x, state, 40); 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); abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 5; i++) /* Test random p1*p2*p3^2 */ { randprime(x, state, 40); randprime(y, state, 40); randprime(z, state, 40); 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); abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 15; i++) /* p1^e1 * p2^e2 * p3^e3 * p4^e4, e1, .., e4 in [1, .., 5] */ { fmpz_set_ui(n, 1); for (j = 0; j < 4; j++) { slong exp; randprime(x, state, 20 + n_randint(state, 30)); exp = n_randint(state, 5) + 1; for (k = 0; k < exp; k++) 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); abort(); } fmpz_factor_clear(factors); } fmpz_clear(n); fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_factor/test/t-factor_pp1.c000066400000000000000000000044031414523752600206710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main(void) { int i, j, result; ulong count = UWORD(0); gmp_randstate_t st; FLINT_TEST_INIT(state); gmp_randinit_default(st); flint_printf("factor_pp1...."); fflush(stdout); 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"); 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); abort(); } gmp_randclear(st); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_factor/test/t-factor_smooth.c000066400000000000000000000130321414523752600215000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.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"); 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"); abort(); } } fmpz_clear(m); fmpz_factor_clear(factor); } 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); } int main(void) { int i, j; fmpz_t x, y, z, n; fmpz_factor_t factors; mpz_t y1; FLINT_TEST_INIT(state); flint_printf("factor_smooth...."); fflush(stdout); fmpz_init(x); mpz_init(y1); /* 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 = -10000; i < 10000; i++) { fmpz_set_si(x, i); checkb(x, 16); } /* Powers */ for (i = 1; i < 250; i++) { for (j = 0; j < 250; j++) { fmpz_set_ui(x, i); fmpz_pow_ui(x, x, j); checkb(x, 10); } } /* Factorials */ for (i = 0; i < 1000; i++) { flint_mpz_fac_ui(y1, i); fmpz_set_mpz(x, y1); checkb(x, 12); } /* Powers of factorials */ for (i = 0; i < 100; i++) { for (j = 1; j < 5; j++) { flint_mpz_fac_ui(y1, i); fmpz_set_mpz(x, y1); fmpz_pow_ui(x, x, j); checkb(x, 12); } } /* Whole limbs */ for (i = 0; i < 1000; i++) { fmpz_set_ui(x, n_randtest(state)); if (n_randint(state, 2)) fmpz_neg(x, x); checkb(x, 32); } /* Large negative integers */ fmpz_set_ui(x, 10); fmpz_pow_ui(x, x, 100); fmpz_neg(x, x); checkb(x, 8); flint_mpz_fac_ui(y1, 50); mpz_neg(y1, y1); fmpz_set_mpz(x, y1); checkb(x, 8); mpz_clear(y1); fmpz_init(y); fmpz_init(z); fmpz_init(n); for (i = 0; i < 20; i++) /* Test random n, three factors */ { randprime(x, state, 40); randprime(y, state, 40); randprime(z, state, 40); 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); abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 20; i++) /* Test random n, small factors */ { randprime(x, state, 10); randprime(y, state, 10); randprime(z, state, 40); 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); abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 5; i++) /* Test random squares */ { randprime(x, state, 40); 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); abort(); } fmpz_factor_clear(factors); } for (i = 0; i < 5; i++) /* Test random cubes */ { randprime(x, state, 40); 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); abort(); } fmpz_factor_clear(factors); } fmpz_clear(n); fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_factor/test/t-factor_trial.c000066400000000000000000000075171414523752600213150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" 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"); 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"); 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"); abort(); } } fmpz_clear(m); fmpz_factor_clear(factor); fmpz_factor_clear(factor2); } int main(void) { int i, j; fmpz_t x; mpz_t y1; FLINT_TEST_INIT(state); flint_printf("factor_trial...."); fflush(stdout); fmpz_init(x); mpz_init(y1); /* Some corner cases */ fmpz_set_si(x, COEFF_MAX); check(x); fmpz_set_si(x, COEFF_MIN); check(x); /* Small integers */ for (i = -10000; i < 10000; i++) { fmpz_set_si(x, i); check(x); } /* Powers */ for (i = 1; i < 250; i++) { for (j = 0; j < 250; j++) { fmpz_set_ui(x, i); fmpz_pow_ui(x, x, j); check(x); } } /* Factorials */ for (i = 0; i < 1000; i++) { flint_mpz_fac_ui(y1, i); fmpz_set_mpz(x, y1); check(x); } /* Powers of factorials */ for (i = 0; i < 100; i++) { for (j = 1; j < 5; j++) { flint_mpz_fac_ui(y1, i); fmpz_set_mpz(x, y1); fmpz_pow_ui(x, x, j); check(x); } } /* Large negative integers */ fmpz_set_ui(x, 10); fmpz_pow_ui(x, x, 100); fmpz_neg(x, x); check(x); flint_mpz_fac_ui(y1, 50); mpz_neg(y1, y1); fmpz_set_mpz(x, y1); check(x); mpz_clear(y1); /* 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_factor/test/t-pollard_brent.c000066400000000000000000000044361414523752600214700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main(void) { fmpz_t prime1, prime2, prime3, prime4, primeprod, fac, modval; int i, j, k, fails; FLINT_TEST_INIT(state); fmpz_init(prime1); fmpz_init(prime2); fmpz_init(prime3); fmpz_init(prime4); fmpz_init(primeprod); fmpz_init(fac); fmpz_init(modval); fails = 0; flint_printf("pollard_brent...."); fflush(stdout); 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); abort(); } } } } if (fails > 2*flint_test_multiplier()) { printf("FAIL : Pollard Rho failed too many times (%d times)\n", fails); abort(); } FLINT_TEST_CLEANUP(state); fmpz_clear(prime1); fmpz_clear(prime2); fmpz_clear(prime3); fmpz_clear(prime4); fmpz_clear(primeprod); fmpz_clear(fac); fmpz_clear(modval); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_factor/test/t-pollard_brent_single.c000066400000000000000000000056631414523752600230340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main(void) { fmpz_t prime1, prime2, prime3, prime4, primeprod, fac, modval, maxa, maxy, a, y; int i, j, k, fails; FLINT_TEST_INIT(state); 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; flint_printf("pollard_brent_single...."); fflush(stdout); 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); abort(); } } } } if (fails > flint_test_multiplier()) { printf("FAIL : Pollard Rho failed too many times (%d times)\n", fails); abort(); } FLINT_TEST_CLEANUP(state); 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); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_factor/test/t-refine.c000066400000000000000000000212201414523752600200770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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; } int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("refine...."); fflush(stdout); 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"); 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"); 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]); 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"); 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"); 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"); 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"); 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"); 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); abort(); } fmpz_clear(x); fmpz_clear(z); mpz_clear(y); fmpz_factor_clear(f); fmpz_factor_clear(g); fmpz_factor_clear(h); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_factorxx.h000066400000000000000000000116111414523752600157770ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_FACTORXX_H #define FMPZ_FACTORXX_H #include "fmpz_factor.h" #include "fmpz_vec.h" #include "flintxx/ltuple.h" // TODO codegen // TODO factor_pp1 multiple return values namespace flint { FLINT_DEFINE_THREEARY(factor_trial_range) FLINT_DEFINE_UNOP(expand) FLINT_DEFINE_UNOP(expand_iterative) FLINT_DEFINE_UNOP(expand_multiexp) namespace detail { template class fmpz_factorxx_delayed { private: fmpz_factor_t inner; void copy_init(const fmpz_factorxx_delayed& o) { _fmpz_factor_fit_length(inner, o.inner->num); _fmpz_factor_set_length(inner, o.inner->num); inner->sign = o.inner->sign; for(slong i = 0;i < o.inner->num;++i) { fmpz_set(inner->p + i, o.inner->p + i); inner->exp[i] = o.inner->exp[i]; } } public: fmpz_factorxx_delayed() {fmpz_factor_init(inner);} ~fmpz_factorxx_delayed() {fmpz_factor_clear(inner);} fmpz_factorxx_delayed(const fmpz_factorxx_delayed& o) { fmpz_factor_init(inner); copy_init(o); } fmpz_factorxx_delayed& operator=(const fmpz_factorxx_delayed& o) { copy_init(o); return *this; } bool operator==(const fmpz_factorxx_delayed& o) { if(o.sign() != sign() || o.size() != size()) return false; for(ulong i = 0;i < size();++i) if(p(i) != o.p(i) || exp(i) != o.exp(i)) return false; return true; } ulong size() const {return inner->num;} ulong exp(slong i) const {return inner->exp[i];} ulong& exp(slong i) {return inner->exp[i];} fmpzxx_srcref p(slong i) const {return fmpzxx_srcref::make(inner->p + i);} fmpzxx_ref p(slong i) {return fmpzxx_ref::make(inner->p + i);} int sign() const {return inner->sign;} int& sign() {return inner->sign;} fmpz_factor_t& _data() {return inner;} const fmpz_factor_t& _data() const {return inner;} void print() const {fmpz_factor_print(inner);} template typename mp::enable_if >::type set_factor(const Fmpz& f) { fmpz_factor(_data(), f.evaluate()._fmpz()); } template typename mp::enable_if >::type set_factor(T t) { fmpz_factor_si(_data(), t); } template typename mp::enable_if, bool>::type set_factor_trial_range(const Fmpz& f, ulong start, ulong nprimes) { return fmpz_factor_trial_range(_data(), f.evaluate()._fmpz(), start, nprimes); } template typename mp::enable_if, bool>::type set_factor_pp1(const Fmpz& f, ulong B1, ulong B2_sqrt, ulong c) { return fmpz_factor_pp1(_data(), f.evaluate()._fmpz(), B1, B2_sqrt, c); } #define FLINTXX_DEFINE_MEMBER_UNOP_EXTRA(funcname, Class, rtype) \ FLINT_UNOP_BUILD_RETTYPE(funcname, rtype, Class) \ funcname() const {return flint::funcname(*this);} FLINTXX_DEFINE_MEMBER_UNOP_EXTRA(expand, fmpz_factorxx_delayed, fmpzxx) FLINTXX_DEFINE_MEMBER_UNOP_EXTRA(expand_iterative, fmpz_factorxx_delayed, fmpzxx) FLINTXX_DEFINE_MEMBER_UNOP_EXTRA(expand_multiexp, fmpz_factorxx_delayed, fmpzxx) }; } // detail typedef detail::fmpz_factorxx_delayed fmpz_factorxx; template inline typename mp::enable_if, traits::fits_into_slong >, fmpz_factorxx>::type factor(const Fmpz& f) { fmpz_factorxx res; res.set_factor(f); return res; } namespace rules { namespace rdetail { typedef make_ltuple::type>::type fmpz_factor_rt; template struct signed_or_fmpz : mp::or_, traits::fits_into_slong > { }; } // rdetail FLINT_DEFINE_THREEARY_EXPR_COND3(factor_trial_range_op, rdetail::fmpz_factor_rt, rdetail::signed_or_fmpz, traits::is_unsigned_integer, traits::is_unsigned_integer, to.template get<0>() = to.template get<1>().set_factor_trial_range( e1, e2, e3)) FLINT_DEFINE_UNARY_EXPR_(expand_op, fmpzxx, fmpz_factorxx, fmpz_factor_expand(to._fmpz(), from._data())) FLINT_DEFINE_UNARY_EXPR_(expand_iterative_op, fmpzxx, fmpz_factorxx, fmpz_factor_expand_iterative(to._fmpz(), from._data())) FLINT_DEFINE_UNARY_EXPR_(expand_multiexp_op, fmpzxx, fmpz_factorxx, fmpz_factor_expand_multiexp(to._fmpz(), from._data())) } // rules template inline typename mp::enable_if, fmpz_factorxx>::type factor_pp1(const Fmpz& f, ulong B1, ulong B2_sqrt, ulong c) { fmpz_factorxx res; res.set_factor_pp1(f, B1, B2_sqrt, c); return res; } inline void print(const fmpz_factorxx& f) { f.print(); } } // flint #endif flint2-2.8.4/fmpz_lll.h000066400000000000000000000137251414523752600147340ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPZ_LLL_INLINE static __inline__ #endif #include #include #include "flint.h" #include "fmpz_mat.h" #include "d_mat.h" #include "mpf_mat.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 ***************************************************/ FLINT_DLL void fmpz_lll_context_init_default(fmpz_lll_t fl); FLINT_DLL void fmpz_lll_context_init(fmpz_lll_t fl, double delta, double eta, rep_type rt, gram_type gt); /* Random parameter generation **********************************************/ FLINT_DLL void fmpz_lll_randtest(fmpz_lll_t fl, flint_rand_t state); /* The various Babai's ******************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int fmpz_lll_shift(const fmpz_mat_t B); FLINT_DLL int fmpz_lll_d(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl); FLINT_DLL int fmpz_lll_d_heuristic(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl); FLINT_DLL 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); FLINT_DLL int fmpz_lll_mpf2(fmpz_mat_t B, fmpz_mat_t U, flint_bitcnt_t prec, const fmpz_lll_t fl); FLINT_DLL int fmpz_lll_mpf(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl); FLINT_DLL int fmpz_lll_wrapper(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl); FLINT_DLL 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); FLINT_DLL 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 ********************************************************/ FLINT_DLL int fmpz_lll_d_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_DLL int fmpz_lll_wrapper_with_removal(fmpz_mat_t B, fmpz_mat_t U, const fmpz_t gs_B, const fmpz_lll_t fl); FLINT_DLL 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); FLINT_DLL 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 *********************************************************************/ FLINT_DLL 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 ***********************************************************/ FLINT_DLL int fmpz_lll_is_reduced_d(const fmpz_mat_t B, const fmpz_lll_t fl); FLINT_DLL int fmpz_lll_is_reduced_mpfr(const fmpz_mat_t B, const fmpz_lll_t fl, flint_bitcnt_t prec); FLINT_DLL int fmpz_lll_is_reduced(const fmpz_mat_t B, const fmpz_lll_t fl, flint_bitcnt_t prec); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 *********************************************************/ FLINT_DLL void fmpz_lll(fmpz_mat_t B, fmpz_mat_t U, const fmpz_lll_t fl); FLINT_DLL 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 ************************************************************/ FLINT_DLL void fmpz_lll_storjohann_ulll(fmpz_mat_t FM, slong new_size, const fmpz_lll_t fl); #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpz_lll/000077500000000000000000000000001414523752600145535ustar00rootroot00000000000000flint2-2.8.4/fmpz_lll/advance_check_babai.c000066400000000000000000000023611414523752600205750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fmpz_lll/advance_check_babai_heuristic_d.c000066400000000000000000000025431414523752600231610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fmpz_lll/babai.c000066400000000000000000000651371414523752600157710ustar00rootroot00000000000000/* 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 2.1 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 = ldexp(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 = ldexp(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 = ldexp(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 = ldexp(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 = ldexp(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 = ldexp(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 = ldexp(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 = ldexp(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 = ldexp(rtmp, (exp - expo[kappa])) - tmp; for (k = zeros + 2; k < j - 1; k++) { tmp = ldexp(d_mat_entry(mu, j, k) * d_mat_entry(r, kappa, k), (expo[j] - expo[k])); rtmp = rtmp - tmp; } tmp = ldexp(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 = ldexp(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) = ldexp(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) = ldexp(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 = ldexp(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 = ldexp(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 = ldexp(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 = ldexp(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 = ldexp(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 = ldexp(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 = ldexp(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] = ldexp(s[zeros + 1], exp - expo[kappa]); for (k = zeros + 1; k < kappa - 1; k++) { tmp = ldexp(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 #else void osxdummy18464823876() /* OSX doesn't like empty files */ { } #endif flint2-2.8.4/fmpz_lll/check_babai.c000066400000000000000000000027101414523752600171120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fmpz_lll/check_babai_heuristic.c000066400000000000000000000502271414523752600211770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 cancelation 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? */ { _fmpz_vec_get_mpf_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 flint2-2.8.4/fmpz_lll/check_babai_heuristic_d.c000066400000000000000000000025101414523752600214720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fmpz_lll/context_init.c000066400000000000000000000012451414523752600174300ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_lll/context_init_default.c000066400000000000000000000011531414523752600211320ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_lll/d_lll.c000066400000000000000000000602251414523752600160120ustar00rootroot00000000000000/* 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 2.1 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_printf ("Exception (fmpz_lll_d*). Incompatible dimensions of capturing matrix.\n"); flint_abort(); } } 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 = ldexp(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 = ldexp(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_printf ("Exception (fmpz_lll_d*). Incompatible dimensions of capturing matrix.\n"); flint_abort(); } 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) = ldexp(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 = ldexp(tmp, (expo[kappa - 1] - expo[kappa])); if (tmp <= s[kappa - 1]) { alpha[kappa] = kappa; tmp = ldexp(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 = ldexp(2 * d_mat_entry(mu, kappa, kappa - 1) * d_mat_entry(r, kappa, kappa - 1), (expo[kappa] - expo[kappa - 1])); fmpz_set_d(rii, ldexp(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 = ldexp(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) = ldexp(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, ldexp(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 #else void osxdummy29398462983() /* OSX doesn't like empty files */ { } #endif flint2-2.8.4/fmpz_lll/heuristic_dot.c000066400000000000000000000021101414523752600175560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" 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 = ldexp(tmp*tmp2, -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; } flint2-2.8.4/fmpz_lll/is_reduced.c000066400000000000000000000024341414523752600170300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" static int want_mpfr(const fmpz_mat_t A) { slong bits; bits = fmpz_mat_max_bits(A); bits = FLINT_ABS(bits); /* highest double exponent is 1023; use mpfr when products in is_reduced_d could possibly have overflowed */ return bits > 512 - 32; } int fmpz_lll_is_reduced(const fmpz_mat_t B, const fmpz_lll_t fl, flint_bitcnt_t prec) { return ((fmpz_lll_is_reduced_d(B, fl) || (want_mpfr(B) && fmpz_lll_is_reduced_mpfr(B, fl, prec)) ) || ((fl->rt == Z_BASIS) ? fmpz_mat_is_reduced(B, fl->delta, fl->eta) : fmpz_mat_is_reduced_gram(B, fl->delta, fl->eta))); } flint2-2.8.4/fmpz_lll/is_reduced_d.c000066400000000000000000000603331414523752600173350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" #if FLINT_USES_FENV #include #endif int fmpz_lll_is_reduced_d(const fmpz_mat_t B, const fmpz_lll_t fl) { #if FLINT_USES_FENV if (fl->rt == Z_BASIS) { /* NOTE: this algorithm should *not* be changed */ slong i, j, k, m, n; d_mat_t A, Q, R, V, Wu, Wd, bound, bound2, bound3, boundt, mm, rm, mn, rn, absR; double *du, *dd; double s, norm = 0, ti, tj; int rounding_direction = fegetround(); 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(A); d_mat_clear(Q); d_mat_clear(R); d_mat_clear(V); return 0; } 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) { d_mat_clear(A); d_mat_clear(R); d_mat_clear(V); d_mat_clear(Wu); d_mat_clear(Wd); _d_vec_clear(du); _d_vec_clear(dd); fesetround(rounding_direction); 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); 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } } 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } } 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 A, R, V, Wu, Wd, bound, bound2, bound3, boundt, mm, rm, mn, rn, absR; double *du, *dd; double s, norm = 0, ti, tj; int rounding_direction = fegetround(); 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) { d_mat_clear(A); d_mat_clear(R); d_mat_clear(V); return 0; } 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); } } 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) { d_mat_clear(A); d_mat_clear(R); d_mat_clear(V); d_mat_clear(Wu); d_mat_clear(Wd); _d_vec_clear(du); _d_vec_clear(dd); fesetround(rounding_direction); 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } } 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } } d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); } return 1; #else return 0; #endif } flint2-2.8.4/fmpz_lll/is_reduced_d_with_removal.c000066400000000000000000000627041414523752600221210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" #if FLINT_USES_FENV #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 FLINT_USES_FENV if (fl->rt == Z_BASIS) { /* NOTE: this algorithm should *not* be changed */ slong i, j, k, m, n; d_mat_t A, Q, R, V, Wu, Wd, bound, bound2, bound3, boundt, mm, rm, mn, rn, absR; double *du, *dd; double s, norm = 0, ti, tj, d_gs_B; int rounding_direction = fegetround(); 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(A); d_mat_clear(Q); d_mat_clear(R); d_mat_clear(V); return 0; } 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) { d_mat_clear(A); d_mat_clear(R); d_mat_clear(V); d_mat_clear(Wu); d_mat_clear(Wd); _d_vec_clear(du); _d_vec_clear(dd); fesetround(rounding_direction); 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); 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } } 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } } fesetround(FE_DOWNWARD); s = (d_mat_entry(R, i, i) - d_mat_entry(bound, i, i)); if (i >= newd && s * s < d_gs_B) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } 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 A, R, V, Wu, Wd, bound, bound2, bound3, boundt, mm, rm, mn, rn, absR; double *du, *dd; double s, norm = 0, ti, tj, d_gs_B; int rounding_direction = fegetround(); 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) { d_mat_clear(A); d_mat_clear(R); d_mat_clear(V); return 0; } 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); } } 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) { d_mat_clear(A); d_mat_clear(R); d_mat_clear(V); d_mat_clear(Wu); d_mat_clear(Wd); _d_vec_clear(du); _d_vec_clear(dd); fesetround(rounding_direction); 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } } 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) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } } fesetround(FE_DOWNWARD); s = (d_mat_entry(R, i, i) - d_mat_entry(bound, i, i)); if (i >= newd && s * s < d_gs_B) { d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); return 0; } d_mat_clear(R); d_mat_clear(bound); fesetround(rounding_direction); } return 1; #else return 0; #endif } flint2-2.8.4/fmpz_lll/is_reduced_mpfr.c000066400000000000000000001017761414523752600200650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" #include "mpfr_vec.h" #include "mpfr_mat.h" int fmpz_lll_is_reduced_mpfr(const fmpz_mat_t B, const fmpz_lll_t fl, flint_bitcnt_t prec) { if (fl->rt == Z_BASIS) { /* NOTE: this algorithm should *not* be changed */ slong i, j, k, m, n; mpfr_mat_t A, Q, R, V, Wu, Wd, bound, bound2, bound3, boundt, mm, rm, mn, rn, absR; flint_mpfr *du, *dd; mpfr_t s, norm, ti, tj, tmp; 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) { mpfr_mat_clear(A); mpfr_mat_clear(R); mpfr_mat_clear(V); 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); 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); 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) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, NULL); return 0; } 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_greater_p(tj, ti)) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, NULL); return 0; } } 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_greater_p(s, tj)) { 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); } else { slong i, j, k, m, n; mpfr_mat_t A, R, V, Wu, Wd, bound, bound2, bound3, boundt, mm, rm, mn, rn, absR; flint_mpfr *du, *dd; mpfr_t s, norm, ti, tj, tmp; 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); } } 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) { mpfr_mat_clear(A); mpfr_mat_clear(R); mpfr_mat_clear(V); 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); 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) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, NULL); return 0; } 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_greater_p(tj, ti)) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, NULL); return 0; } } 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_greater_p(s, tj)) { 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); } return 1; } flint2-2.8.4/fmpz_lll/is_reduced_mpfr_with_removal.c000066400000000000000000001053111414523752600226320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { if (fl->rt == Z_BASIS) { /* NOTE: this algorithm should *not* be changed */ slong i, j, k, m, n; mpfr_mat_t A, Q, R, V, Wu, Wd, bound, bound2, bound3, boundt, mm, rm, mn, rn, absR; flint_mpfr *du, *dd; mpfr_t s, norm, ti, tj, tmp, mpfr_gs_B; 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) { mpfr_mat_clear(A); mpfr_mat_clear(R); mpfr_mat_clear(V); 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); 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); 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) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, NULL); return 0; } 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_less_p(tmp, mpfr_gs_B)) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, mpfr_gs_B, NULL); return 0; } 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_greater_p(tj, ti)) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, mpfr_gs_B, NULL); return 0; } } 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_greater_p(s, tj)) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, mpfr_gs_B, NULL); return 0; } } 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_less_p(tmp, mpfr_gs_B)) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, mpfr_gs_B, NULL); return 0; } 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, n; mpfr_mat_t A, R, V, Wu, Wd, bound, bound2, bound3, boundt, mm, rm, mn, rn, absR; flint_mpfr *du, *dd; mpfr_t s, norm, ti, tj, tmp, mpfr_gs_B; 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); } } 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) { mpfr_mat_clear(A); mpfr_mat_clear(R); mpfr_mat_clear(V); 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); 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) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, NULL); return 0; } 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_less_p(tmp, mpfr_gs_B)) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, mpfr_gs_B, NULL); return 0; } 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_greater_p(tj, ti)) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, mpfr_gs_B, NULL); return 0; } } 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_greater_p(s, tj)) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, mpfr_gs_B, NULL); return 0; } } 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_less_p(tmp, mpfr_gs_B)) { mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, mpfr_gs_B, NULL); return 0; } mpfr_mat_clear(R); mpfr_mat_clear(bound); mpfr_clears(s, norm, ti, tj, tmp, mpfr_gs_B, NULL); } return 1; } flint2-2.8.4/fmpz_lll/is_reduced_with_removal.c000066400000000000000000000033471414523752600216140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" static int want_mpfr(const fmpz_mat_t A, const fmpz_t b) { slong bits, bits2; bits = fmpz_mat_max_bits(A); bits = FLINT_ABS(bits); bits2 = fmpz_bits(b); bits = FLINT_MAX(bits, bits2); /* highest double exponent is 1023; use mpfr when products in is_reduced_d could possibly have overflowed */ return bits > 512 - 32; } 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) { return (gs_B != NULL) ? ((fmpz_lll_is_reduced_d_with_removal(B, fl, gs_B, newd) || (want_mpfr(B, gs_B) && fmpz_lll_is_reduced_mpfr_with_removal(B, fl, gs_B, newd, prec)) ) || ((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))) : fmpz_lll_is_reduced(B, fl, prec); } flint2-2.8.4/fmpz_lll/lll.c000066400000000000000000000011451414523752600155030ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_lll/lll_d.c000066400000000000000000000052571414523752600160160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fmpz_lll/lll_d_heuristic.c000066400000000000000000000056241414523752600200730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fmpz_lll/lll_d_heuristic_with_removal.c000066400000000000000000000056611414523752600226540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fmpz_lll/lll_d_with_removal.c000066400000000000000000000053141414523752600205700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fmpz_lll/lll_d_with_removal_knapsack.c000066400000000000000000000053601414523752600224440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fmpz_lll/lll_mpf.c000066400000000000000000000016301414523752600163440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_lll/lll_mpf2.c000066400000000000000000000014261414523752600164310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fmpz_lll/lll_mpf2_with_removal.c000066400000000000000000000014631414523752600212120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fmpz_lll/lll_mpf_with_removal.c000066400000000000000000000020341414523752600211230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_lll/lll_with_removal.c000066400000000000000000000012411414523752600202600ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_lll/lll_with_removal_ulll.c000066400000000000000000000076541414523752600213260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_lll/mpf2_lll.c000066400000000000000000000467261414523752600164450ustar00rootroot00000000000000/* 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 2.1 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_printf ("Exception (fmpz_lll_mpf*). Incompatible dimensions of capturing matrix.\n"); flint_abort(); } } 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++) _fmpz_vec_get_mpf_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_printf ("Exception (fmpz_lll_mpf*). Incompatible dimensions of capturing matrix.\n"); flint_abort(); } 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 #else void osxdummy9283479238479() /* OSX doesn't like empty files */ { } #endif flint2-2.8.4/fmpz_lll/profile/000077500000000000000000000000001414523752600162135ustar00rootroot00000000000000flint2-2.8.4/fmpz_lll/profile/p-lll.c000066400000000000000000000053341414523752600174040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "flint.h" #include "fmpz_lll.h" #include "fmpz.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; flint_rand_t rnd; 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; } flint2-2.8.4/fmpz_lll/randtest.c000066400000000000000000000023151414523752600165440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_lll.h" void fmpz_lll_randtest(fmpz_lll_t fl, flint_rand_t state) { double randd, delta, eta; rep_type rt; gram_type gt; randd = d_randtest(state); if (randd > 0.5 && n_randint(state, 1)) { delta = 0.25 + (randd - 0.5) * 0.75; if (n_randint(state, 1)) eta = 0.5 + (randd - 0.5) * (sqrt(delta) - 0.5); else eta = 0.5 + randd * (sqrt(delta) - 0.5); } else { delta = 0.25 + randd * 0.75; if (n_randint(state, 1)) eta = 0.5 + (randd - 0.5) * (sqrt(delta) - 0.5); else eta = 0.5 + randd * (sqrt(delta) - 0.5); } rt = n_randint(state, 2); gt = n_randint(state, 2); fmpz_lll_context_init(fl, delta, eta, rt, gt); } flint2-2.8.4/fmpz_lll/shift.c000066400000000000000000000014701414523752600160360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_lll/storjohann_ulll.c000066400000000000000000000102231414523752600201320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_lll/test/000077500000000000000000000000001414523752600155325ustar00rootroot00000000000000flint2-2.8.4/fmpz_lll/test/t-heuristic_dot.c000066400000000000000000000043441414523752600210110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" #define FMPZ_LLL_HD_EPS (1.0E-10) int main(void) { int i; fmpz_mat_t B; FLINT_TEST_INIT(state); flint_printf("heuristic_dot...."); fflush(stdout); 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)); abort(); } _d_vec_clear(v1); _d_vec_clear(v2); fmpz_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/test/t-lll.c000066400000000000000000000324121414523752600167240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" int main(void) { int i, result = 1; fmpz_mat_t mat, mat2, U; fmpz_lll_t fl; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("lll...."); fflush(stdout); /* test zeros */ { fmpz_mat_init(mat, 4, 4); fmpz_set_si(fmpz_mat_entry(mat, 0, 0), 584067842); fmpz_set_si(fmpz_mat_entry(mat, 0, 1), 0); fmpz_set_si(fmpz_mat_entry(mat, 0, 2), 24573982); fmpz_set_si(fmpz_mat_entry(mat, 0, 3), 521334123); fmpz_set_si(fmpz_mat_entry(mat, 1, 0), 0); fmpz_set_si(fmpz_mat_entry(mat, 1, 1), -584067842); fmpz_set_si(fmpz_mat_entry(mat, 1, 2), -434026422); fmpz_set_si(fmpz_mat_entry(mat, 1, 3), -496760141); fmpz_set_si(fmpz_mat_entry(mat, 2, 0), 24573982); fmpz_set_si(fmpz_mat_entry(mat, 2, 1), -434026422); fmpz_set_si(fmpz_mat_entry(mat, 2, 2), -321495282); fmpz_set_si(fmpz_mat_entry(mat, 2, 3), -347212699); fmpz_set_si(fmpz_mat_entry(mat, 3, 0), 521334123); fmpz_set_si(fmpz_mat_entry(mat, 3, 1), -496760141); fmpz_set_si(fmpz_mat_entry(mat, 3, 2), -347212699); fmpz_set_si(fmpz_mat_entry(mat, 3, 3), 42835143); fl->delta = 0.99; fl->eta = 0.51; fl->rt = GRAM; fl->gt = EXACT; for (i = 0; i < 1; i++) { fmpz_mat_init_set(mat2, mat); fmpz_lll(mat2, NULL, fl); fmpz_mat_clear(mat2); } 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_mat_clear(mat); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/test/t-lll_d.c000066400000000000000000000300001414523752600172160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" int main(void) { int i, result = 1; fmpz_mat_t mat, mat2, U; fmpz_lll_t fl; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("lll_d...."); fflush(stdout); /* 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); 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); 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); 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_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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_mat_clear(mat); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/test/t-lll_d_heuristic.c000066400000000000000000000302521414523752600213060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" int main(void) { int i, result = 1; fmpz_mat_t mat, mat2, U; fmpz_lll_t fl; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("lll_d_heuristic...."); fflush(stdout); /* 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); 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); 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); 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_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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_mat_clear(mat); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/test/t-lll_d_heuristic_with_removal.c000066400000000000000000000334011414523752600240650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" int main(void) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("lll_d_heuristic_with_removal...."); fflush(stdout); /* 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); 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); 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); 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_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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/test/t-lll_d_with_removal.c000066400000000000000000000331031414523752600220050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" int main(void) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("lll_d_with_removal...."); fflush(stdout); /* 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); 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); 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); 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_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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/test/t-lll_d_with_removal_knapsack.c000066400000000000000000000333341414523752600236660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" int main(void) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("lll_d_with_removal_knapsack...."); fflush(stdout); /* 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); 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); 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); 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_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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/test/t-lll_mpf.c000066400000000000000000000300421414523752600175630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" int main(void) { int i, result = 1; fmpz_mat_t mat, mat2, U; fmpz_lll_t fl; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("lll_mpf...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_mat_clear(mat); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/test/t-lll_mpf_with_removal.c000066400000000000000000000331451414523752600223520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" int main(void) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("lll_mpf_with_removal...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/test/t-lll_with_removal.c000066400000000000000000000330411414523752600215030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" int main(void) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("lll_with_removal...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/test/t-wrapper.c000066400000000000000000000301421414523752600176170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" int main(void) { int i, result = 1; fmpz_mat_t mat, mat2, U; fmpz_lll_t fl; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("wrapper...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_mat_clear(mat); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/test/t-wrapper_with_removal.c000066400000000000000000000332451414523752600224060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" int main(void) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("wrapper_with_removal...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/test/t-wrapper_with_removal_knapsack.c000066400000000000000000000351261414523752600242610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_lll.h" #include "ulong_extras.h" int main(void) { int i, result = 1, newd; fmpz_mat_t mat, mat2, U; fmpz_t bound; fmpz_lll_t fl; flint_bitcnt_t bits; FLINT_TEST_INIT(state); flint_printf("wrapper_with_removal_knapsack...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_mat_clear(mat); fmpz_clear(bound); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_lll/wrapper.c000066400000000000000000000020051414523752600163740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_lll/wrapper_with_removal.c000066400000000000000000000023471414523752600211650ustar00rootroot00000000000000/* 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 2.1 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, D_BITS))) { 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, D_BITS))) { 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; } flint2-2.8.4/fmpz_lll/wrapper_with_removal_knapsack.c000066400000000000000000000024021414523752600230300ustar00rootroot00000000000000/* 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 2.1 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, D_BITS))) { 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, D_BITS))) { 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; } flint2-2.8.4/fmpz_mat.h000066400000000000000000000561631414523752600147350ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPZ_MAT_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "nmod_mat.h" #include "d_mat.h" #include "mpf_mat.h" #ifdef __cplusplus extern "C" { #endif typedef struct { fmpz * entries; slong r; slong c; fmpz ** rows; } fmpz_mat_struct; typedef fmpz_mat_struct fmpz_mat_t[1]; /* used for column partitioning, used by van Hoeij poly factoring */ typedef struct { ulong col; ulong hash; } col_hash_t; /* 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 ********************************************************/ FLINT_DLL void fmpz_mat_init(fmpz_mat_t mat, slong rows, slong cols); FLINT_DLL void fmpz_mat_init_set(fmpz_mat_t mat, const fmpz_mat_t src); FLINT_DLL void fmpz_mat_swap(fmpz_mat_t mat1, fmpz_mat_t mat2); FMPZ_MAT_INLINE 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)); } FLINT_DLL void fmpz_mat_set(fmpz_mat_t mat1, const fmpz_mat_t mat2); FLINT_DLL void fmpz_mat_clear(fmpz_mat_t mat); FLINT_DLL int fmpz_mat_equal(const fmpz_mat_t mat1, const fmpz_mat_t mat2); FLINT_DLL int fmpz_mat_is_zero(const fmpz_mat_t mat); FLINT_DLL int fmpz_mat_is_one(const fmpz_mat_t mat); FMPZ_MAT_INLINE int fmpz_mat_is_zero_row(const fmpz_mat_t mat, slong i) { return _fmpz_vec_is_zero(mat->rows[i], mat->c); } FMPZ_MAT_INLINE int fmpz_mat_col_equal(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; } FMPZ_MAT_INLINE int fmpz_mat_row_equal(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; } 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); } FLINT_DLL void fmpz_mat_zero(fmpz_mat_t mat); FLINT_DLL void fmpz_mat_one(fmpz_mat_t mat); /* Windows and concatenation */ FLINT_DLL void fmpz_mat_window_init(fmpz_mat_t window, const fmpz_mat_t mat, slong r1, slong c1, slong r2, slong c2); FLINT_DLL void fmpz_mat_window_clear(fmpz_mat_t window); FLINT_DLL void fmpz_mat_concat_horizontal(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_mat_t mat2); FLINT_DLL void fmpz_mat_concat_vertical(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_mat_t mat2); /* Input and output *********************************************************/ FLINT_DLL int fmpz_mat_fprint(FILE * file, const fmpz_mat_t mat); FLINT_DLL int fmpz_mat_fprint_pretty(FILE * file, const fmpz_mat_t mat); FMPZ_MAT_INLINE int fmpz_mat_print(const fmpz_mat_t mat) { return fmpz_mat_fprint(stdout, mat); } FMPZ_MAT_INLINE int fmpz_mat_print_pretty(const fmpz_mat_t mat) { return fmpz_mat_fprint_pretty(stdout, mat); } FLINT_DLL int fmpz_mat_fread(FILE* file, fmpz_mat_t mat); FMPZ_MAT_INLINE int fmpz_mat_read(fmpz_mat_t mat) { return fmpz_mat_fread(stdin, mat); } /* Random matrix generation *************************************************/ FLINT_DLL void fmpz_mat_randbits(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void fmpz_mat_randtest(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void fmpz_mat_randtest_unsigned(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void fmpz_mat_randintrel(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); FLINT_DLL void fmpz_mat_randsimdioph(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits, flint_bitcnt_t bits2); FLINT_DLL void fmpz_mat_randntrulike(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits, ulong q); FLINT_DLL void fmpz_mat_randntrulike2(fmpz_mat_t mat, flint_rand_t state, flint_bitcnt_t bits, ulong q); FLINT_DLL void fmpz_mat_randajtai(fmpz_mat_t mat, flint_rand_t state, double alpha); FLINT_DLL void fmpz_mat_randrank(fmpz_mat_t mat, flint_rand_t state, slong rank, flint_bitcnt_t bits); FLINT_DLL void fmpz_mat_randdet(fmpz_mat_t mat, flint_rand_t state, const fmpz_t det); FLINT_DLL void fmpz_mat_randops(fmpz_mat_t mat, flint_rand_t state, slong count); FLINT_DLL int fmpz_mat_randpermdiag(fmpz_mat_t mat, flint_rand_t state, const fmpz * diag, slong n); /* Norms */ FLINT_DLL slong fmpz_mat_max_bits(const fmpz_mat_t mat); /* Transpose */ FLINT_DLL void fmpz_mat_transpose(fmpz_mat_t B, const fmpz_mat_t A); /* Addition and subtraction */ FLINT_DLL void fmpz_mat_add(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL void fmpz_mat_sub(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL void fmpz_mat_neg(fmpz_mat_t B, const fmpz_mat_t A); /* Scalar operations */ FLINT_DLL void fmpz_mat_scalar_mul_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c); FLINT_DLL void fmpz_mat_scalar_mul_si(fmpz_mat_t B, const fmpz_mat_t A, slong c); FLINT_DLL void fmpz_mat_scalar_mul_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c); FLINT_DLL void fmpz_mat_scalar_addmul_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c); FLINT_DLL void fmpz_mat_scalar_addmul_si(fmpz_mat_t B, const fmpz_mat_t A, slong c); FLINT_DLL void fmpz_mat_scalar_addmul_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c); FLINT_DLL void fmpz_mat_scalar_submul_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c); FLINT_DLL void fmpz_mat_scalar_submul_si(fmpz_mat_t B, const fmpz_mat_t A, slong c); FLINT_DLL void fmpz_mat_scalar_submul_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c); FLINT_DLL void fmpz_mat_scalar_addmul_nmod_mat_fmpz(fmpz_mat_t B, const nmod_mat_t A, const fmpz_t c); FLINT_DLL void fmpz_mat_scalar_addmul_nmod_mat_ui(fmpz_mat_t B, const nmod_mat_t A, ulong c); FLINT_DLL void fmpz_mat_scalar_divexact_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t c); FLINT_DLL void fmpz_mat_scalar_divexact_si(fmpz_mat_t B, const fmpz_mat_t A, slong c); FLINT_DLL void fmpz_mat_scalar_divexact_ui(fmpz_mat_t B, const fmpz_mat_t A, ulong c); FLINT_DLL void fmpz_mat_scalar_mul_2exp(fmpz_mat_t B, const fmpz_mat_t A, ulong exp); FLINT_DLL void fmpz_mat_scalar_tdiv_q_2exp(fmpz_mat_t B, const fmpz_mat_t A, ulong exp); FLINT_DLL void fmpz_mat_scalar_smod(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t P); FLINT_DLL void fmpz_mat_scalar_mod_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const fmpz_t m); /* Multiplication */ FLINT_DLL void fmpz_mat_mul(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL void fmpz_mat_mul_classical(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL void fmpz_mat_mul_strassen(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL void fmpz_mat_mul_classical_inline(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL 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); FLINT_DLL void fmpz_mat_mul_multi_mod(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL 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); FLINT_DLL int fmpz_mat_mul_blas(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL void _fmpz_mat_mul_small_1(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL void _fmpz_mat_mul_small_2a(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL void _fmpz_mat_mul_small_2b(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL void _fmpz_mat_mul_small_internal(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B, flint_bitcnt_t Cbits); FLINT_DLL void _fmpz_mat_mul_small(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL void _fmpz_mat_mul_double_word(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL 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); FLINT_DLL void fmpz_mat_sqr_bodrato(fmpz_mat_t B, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_sqr(fmpz_mat_t B, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_pow(fmpz_mat_t B, const fmpz_mat_t A, ulong exp); FLINT_DLL void fmpz_mat_mul_fmpz_vec(fmpz * c, const fmpz_mat_t A, const fmpz * b, slong blen); FLINT_DLL void fmpz_mat_mul_fmpz_vec_ptr(fmpz * const * c, const fmpz_mat_t A, const fmpz * const * b, slong blen); FLINT_DLL void fmpz_mat_fmpz_vec_mul(fmpz * c, const fmpz * a, slong alen, const fmpz_mat_t B); FLINT_DLL void fmpz_mat_fmpz_vec_mul_ptr(fmpz * const * c, const fmpz * const * a, slong alen, const fmpz_mat_t B); /* Kronecker product */ FLINT_DLL void fmpz_mat_kronecker_product(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); /* Content */ FLINT_DLL 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)) { fmpz * 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; } } FMPZ_MAT_INLINE 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); } FMPZ_MAT_INLINE void fmpz_mat_swap_cols(fmpz_mat_t mat, slong * perm, slong r, slong s) { if (r != s && !fmpz_mat_is_empty(mat)) { slong t; if (perm) { t = perm[s]; perm[s] = perm[r]; perm[r] = t; } for (t = 0; t < mat->r; t++) { fmpz_swap(fmpz_mat_entry(mat, t, r), fmpz_mat_entry(mat, t, s)); } } } FMPZ_MAT_INLINE void fmpz_mat_invert_cols(fmpz_mat_t mat, slong * perm) { if (!fmpz_mat_is_empty(mat)) { slong t; slong i; slong c = mat->c; slong k = mat->c/2; if (perm) { for (i =0; i < k; i++) { t = perm[i]; perm[i] = perm[c - i]; perm[c - i] = t; } } 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)); } } } } /* Gaussian elimination *****************************************************/ FLINT_DLL slong fmpz_mat_find_pivot_any(const fmpz_mat_t mat, slong start_row, slong end_row, slong c); FLINT_DLL slong fmpz_mat_find_pivot_smallest(const fmpz_mat_t mat, slong start_row, slong end_row, slong c); FLINT_DLL slong fmpz_mat_fflu(fmpz_mat_t B, fmpz_t den, slong * perm, const fmpz_mat_t A, int rank_check); FLINT_DLL slong fmpz_mat_rank_small_inplace(fmpz_mat_t B); FLINT_DLL slong fmpz_mat_rref(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A); FLINT_DLL slong fmpz_mat_rref_fflu(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A); FLINT_DLL slong fmpz_mat_rref_mul(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A); FLINT_DLL int fmpz_mat_is_in_rref_with_rank(const fmpz_mat_t A, const fmpz_t den, slong rank); /* Modular gaussian elimination *********************************************/ FLINT_DLL slong fmpz_mat_rref_mod(slong * perm, fmpz_mat_t A, const fmpz_t p); /* Modular Howell and strong echelon form ***********************************/ FLINT_DLL slong fmpz_mat_howell_form_mod(fmpz_mat_t A, const fmpz_t mod); FLINT_DLL void fmpz_mat_strong_echelon_form_mod(fmpz_mat_t A, const fmpz_t mod); /* Trace ********************************************************************/ FLINT_DLL void fmpz_mat_trace(fmpz_t trace, const fmpz_mat_t mat); /* Determinant **************************************************************/ FLINT_DLL void fmpz_mat_det(fmpz_t det, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_det_cofactor(fmpz_t det, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_det_bareiss(fmpz_t det, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_det_modular(fmpz_t det, const fmpz_mat_t A, int proved); FLINT_DLL void fmpz_mat_det_modular_accelerated(fmpz_t det, const fmpz_mat_t A, int proved); FLINT_DLL void fmpz_mat_det_modular_given_divisor(fmpz_t det, const fmpz_mat_t A, const fmpz_t d, int proved); FLINT_DLL void fmpz_mat_det_bound(fmpz_t bound, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_det_bound_nonzero(fmpz_t bound, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_det_divisor(fmpz_t d, const fmpz_mat_t A); /* Transforms */ FLINT_DLL void fmpz_mat_similarity(fmpz_mat_t A, slong r, fmpz_t d); #include "fmpz_poly.h" /* Characteristic polynomial ************************************************/ FLINT_DLL void _fmpz_mat_charpoly_berkowitz(fmpz * rop, const fmpz_mat_t op); FLINT_DLL void fmpz_mat_charpoly_berkowitz(fmpz_poly_t cp, const fmpz_mat_t mat); FLINT_DLL void _fmpz_mat_charpoly_modular(fmpz * rop, const fmpz_mat_t op); FLINT_DLL 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_printf("Exception (nmod_mat_charpoly). Non-square matrix.\n"); flint_abort(); } fmpz_mat_charpoly_modular(cp, mat); } /* Characteristic polynomial ************************************************/ FLINT_DLL slong _fmpz_mat_minpoly_modular(fmpz * rop, const fmpz_mat_t op); FLINT_DLL 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_printf("Exception (fmpz_mat_minpoly). Non-square matrix.\n"); flint_abort(); } fmpz_mat_minpoly_modular(cp, mat); } /* Rank **********************************************************************/ FLINT_DLL slong fmpz_mat_rank(const fmpz_mat_t A); /* Nonsingular solving *******************************************************/ FLINT_DLL void fmpz_mat_solve_bound(fmpz_t N, fmpz_t D, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL int fmpz_mat_solve(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL int fmpz_mat_solve_cramer(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL int fmpz_mat_solve_fflu(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL int fmpz_mat_solve_fflu_precomp(fmpz_mat_t X, const slong * perm, const fmpz_mat_t FFLU, const fmpz_mat_t B); FLINT_DLL mp_limb_t fmpz_mat_find_good_prime_and_invert(nmod_mat_t Ainv, const fmpz_mat_t A, const fmpz_t det_bound); FLINT_DLL mp_limb_t * fmpz_mat_dixon_get_crt_primes(slong * num_primes, const fmpz_mat_t A, mp_limb_t p); FLINT_DLL 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); FLINT_DLL int fmpz_mat_solve_dixon(fmpz_mat_t X, fmpz_t mod, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL 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); FLINT_DLL int fmpz_mat_solve_dixon_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL int fmpz_mat_solve_multi_mod_den(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL 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); FLINT_DLL int fmpz_mat_can_solve_fflu(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL int fmpz_mat_can_solve(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B); /* Nullspace *****************************************************************/ FLINT_DLL slong fmpz_mat_nullspace(fmpz_mat_t res, const fmpz_mat_t mat); /* Inverse *******************************************************************/ FLINT_DLL int fmpz_mat_inv(fmpz_mat_t B, fmpz_t den, const fmpz_mat_t A); /* Modular reduction and reconstruction **************************************/ FLINT_DLL void fmpz_mat_set_nmod_mat(fmpz_mat_t A, const nmod_mat_t Amod); FLINT_DLL void fmpz_mat_set_nmod_mat_unsigned(fmpz_mat_t A, const nmod_mat_t Amod); FLINT_DLL void fmpz_mat_get_nmod_mat(nmod_mat_t Amod, const fmpz_mat_t A); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mat_multi_mod_ui(nmod_mat_t * residues, slong nres, const fmpz_mat_t mat); FLINT_DLL 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); FLINT_DLL void fmpz_mat_multi_CRT_ui(fmpz_mat_t mat, nmod_mat_t * const residues, slong nres, int sign); /* HNF and SNF **************************************************************/ FLINT_DLL void fmpz_mat_hnf(fmpz_mat_t H, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_hnf_transform(fmpz_mat_t H, fmpz_mat_t U, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_hnf_classical(fmpz_mat_t H, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_hnf_xgcd(fmpz_mat_t H, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_hnf_minors(fmpz_mat_t H, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_hnf_minors_transform(fmpz_mat_t H, fmpz_mat_t U, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_hnf_modular(fmpz_mat_t H, const fmpz_mat_t A, const fmpz_t D); FLINT_DLL void fmpz_mat_hnf_modular_eldiv(fmpz_mat_t A, const fmpz_t D); FLINT_DLL void fmpz_mat_hnf_pernet_stein(fmpz_mat_t H, const fmpz_mat_t A, flint_rand_t state); FLINT_DLL int fmpz_mat_is_in_hnf(const fmpz_mat_t A); FLINT_DLL void fmpz_mat_snf(fmpz_mat_t S, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_snf_diagonal(fmpz_mat_t S, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_snf_kannan_bachem(fmpz_mat_t S, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_snf_iliopoulos(fmpz_mat_t S, const fmpz_mat_t A, const fmpz_t mod); FLINT_DLL int fmpz_mat_is_in_snf(const fmpz_mat_t A); /* Special matrices **********************************************************/ FLINT_DLL int fmpz_mat_is_hadamard(const fmpz_mat_t A); FLINT_DLL int fmpz_mat_hadamard(fmpz_mat_t A); /* Gram matrix **************************************************************/ FLINT_DLL void fmpz_mat_gram(fmpz_mat_t B, const fmpz_mat_t A); /* Conversions **************************************************************/ FLINT_DLL int fmpz_mat_get_d_mat(d_mat_t B, const fmpz_mat_t A); FLINT_DLL int fmpz_mat_get_d_mat_transpose(d_mat_t B, const fmpz_mat_t A); FLINT_DLL void fmpz_mat_get_mpf_mat(mpf_mat_t B, const fmpz_mat_t A); /* Cholesky Decomposition ****************************************************/ FLINT_DLL void fmpz_mat_chol_d(d_mat_t R, const fmpz_mat_t A); /* LLL ***********************************************************************/ FLINT_DLL int fmpz_mat_is_reduced(const fmpz_mat_t A, double delta, double eta); FLINT_DLL int fmpz_mat_is_reduced_gram(const fmpz_mat_t A, double delta, double eta); FLINT_DLL int fmpz_mat_is_reduced_with_removal(const fmpz_mat_t A, double delta, double eta, const fmpz_t gs_B, int newd); FLINT_DLL 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 *************************************************************/ FLINT_DLL void fmpz_mat_lll_original(fmpz_mat_t A, const fmpq_t delta, const fmpq_t eta); /* Modified LLL **************************************************************/ FLINT_DLL void fmpz_mat_lll_storjohann(fmpz_mat_t A, const fmpq_t delta, const fmpq_t eta); /* Column partitioning *******************************************************/ FLINT_DLL int fmpz_mat_col_partition(slong * part, fmpz_mat_t M, int short_circuit); /* Van Hoeij helper function *************************************************/ FLINT_DLL 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 flint2-2.8.4/fmpz_mat/000077500000000000000000000000001414523752600145515ustar00rootroot00000000000000flint2-2.8.4/fmpz_mat/CRT_ui.c000066400000000000000000000022701414523752600160430ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_mat_CRT_ui). m1 not invertible modulo m2.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_mat/add.c000066400000000000000000000012131414523752600154420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/can_solve.c000066400000000000000000000012651414523752600166720ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_mat/can_solve_fflu.c000066400000000000000000000046101414523752600177030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "perm.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; } flint2-2.8.4/fmpz_mat/can_solve_multi_mod_den.c000066400000000000000000000020471414523752600215700ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (fmpz_mat_can_solve_multi_mod_den). Incompatible matrix dimensions.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpz_mat/charpoly_berkowitz.c000066400000000000000000000051761414523752600206470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_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) { const slong n = mat->r; if (n == 0) { fmpz_one(cp); } else if (n == 1) { fmpz_neg(cp + 0, fmpz_mat_entry(mat, 0, 0)); fmpz_one(cp + 1); } else { slong i, j, k, t; fmpz *a, *A, *s; a = _fmpz_vec_init(n * n); A = a + (n - 1) * n; _fmpz_vec_zero(cp, n + 1); fmpz_neg(cp + 0, fmpz_mat_entry(mat, 0, 0)); for (t = 1; t < n; t++) { for (i = 0; i <= t; i++) { fmpz_set(a + 0 * n + i, fmpz_mat_entry(mat, i, t)); } fmpz_set(A + 0, fmpz_mat_entry(mat, t, t)); for (k = 1; k < t; k++) { for (i = 0; i <= t; i++) { s = a + k * n + i; fmpz_zero(s); for (j = 0; j <= t; j++) { fmpz_addmul(s, fmpz_mat_entry(mat, i, j), a + (k - 1) * n + j); } } fmpz_set(A + k, a + k * n + t); } fmpz_zero(A + t); for (j = 0; j <= t; j++) { fmpz_addmul(A + t, fmpz_mat_entry(mat, t, j), a + (t - 1) * n + j); } for (k = 0; k <= t; k++) { for (j = 0; j < k; j++) { fmpz_submul(cp + k, A + j, cp + (k - j - 1)); } fmpz_sub(cp + k, cp + k, A + k); } } /* Shift all coefficients up by one */ for (i = n; i > 0; i--) { fmpz_swap(cp + i, cp + (i - 1)); } fmpz_one(cp + 0); _fmpz_poly_reverse(cp, cp, n + 1, n + 1); _fmpz_vec_clear(a, n * n); } } 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); } flint2-2.8.4/fmpz_mat/charpoly_modular.c000066400000000000000000000112111414523752600202550ustar00rootroot00000000000000/* Copyright (C) 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "nmod_poly.h" #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); } flint2-2.8.4/fmpz_mat/chol_d.c000066400000000000000000000025651414523752600161550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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_printf ("Exception (fmpz_mat_chol_d). Incompatible dimensions.\n"); flint_abort(); } 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); } } } flint2-2.8.4/fmpz_mat/clear.c000066400000000000000000000014371414523752600160100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/col_partition.c000066400000000000000000000050211414523752600175610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include /* qsort */ #include "fmpz.h" #include "fmpz_mat.h" /* cheap hash of all columns of M */ void fmpz_mat_col_hash(col_hash_t * 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_t * col_a = (col_hash_t *) a; col_hash_t * col_b = (col_hash_t *) 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_t * col_h; TMP_INIT; TMP_START; col_h = (col_hash_t *) TMP_ALLOC(sizeof(col_hash_t)*M->c); fmpz_mat_col_hash(col_h, M); qsort(col_h, M->c, sizeof(col_hash_t), 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_col_equal(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; } flint2-2.8.4/fmpz_mat/concat_horizontal.c000066400000000000000000000017141414523752600204400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } } } flint2-2.8.4/fmpz_mat/concat_vertical.c000066400000000000000000000017121414523752600200560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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)); } } } flint2-2.8.4/fmpz_mat/content.c000066400000000000000000000013651414523752600163740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpz.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; } flint2-2.8.4/fmpz_mat/det.c000066400000000000000000000017671414523752600155040ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (fmpz_mat_det). Non-square matrix.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpz_mat/det_bareiss.c000066400000000000000000000016521414523752600172050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/det_bound.c000066400000000000000000000023401414523752600166570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/det_cofactor.c000066400000000000000000000046331414523752600173570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_mat_det_cofactor). dim > 4 not implemented."); flint_abort(); } } flint2-2.8.4/fmpz_mat/det_divisor.c000066400000000000000000000030001414523752600172210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_printf("Exception (fmpz_mat_det_divisor): " "Rational reconstruction failed.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_mat/det_modular.c000066400000000000000000000011411414523752600172110ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/det_modular_accelerated.c000066400000000000000000000011741414523752600215330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/det_modular_given_divisor.c000066400000000000000000000046331414523752600221510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); /* accomodate 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); } flint2-2.8.4/fmpz_mat/equal.c000066400000000000000000000014411414523752600160240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/fflu.c000066400000000000000000000115541414523752600156570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "perm.h" #include "longlong.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) <= FLINT_BITS - 2; int dsgn = 0, sgn, den1 = 0, work_to_do; if (fmpz_mat_is_empty(A)) { fmpz_one(den); 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); count_leading_zeros(norm, uden); invert_limb(dinv, uden << norm); if (fmpz_sizeinbase(den, 2) > FLINT_BITS - 2) small = 0; } pivot_row++; pivot_col++; } return rank; } flint2-2.8.4/fmpz_mat/find_pivot_any.c000066400000000000000000000012751414523752600177320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/find_pivot_smallest.c000066400000000000000000000016711414523752600207670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/fmpz_vec_mul.c000066400000000000000000000013401414523752600174010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } } flint2-2.8.4/fmpz_mat/fmpz_vec_mul_ptr.c000066400000000000000000000013611414523752600202710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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)); } } flint2-2.8.4/fmpz_mat/fprint.c000066400000000000000000000045701414523752600162250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" /* 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, "%li %li ", 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 flint2-2.8.4/fmpz_mat/fread.c000066400000000000000000000037471414523752600160110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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_printf("Exception (fmpz_mat_fread). " "Number of rows does not fit into a slong.\n"); flint_abort(); } 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_printf("Exception (fmpz_mat_fread). " "Number of columns does not fit into a slong.\n"); flint_abort(); } 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_printf("Exception (fmpz_mat_fread). \n" "Dimensions are non-zero and do not match input dimensions.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpz_mat/get_d_mat.c000066400000000000000000000016641414523752600166470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/get_d_mat_transpose.c000066400000000000000000000016761414523752600207500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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; } flint2-2.8.4/fmpz_mat/get_mpf_mat.c000066400000000000000000000012001414523752600171700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" void fmpz_mat_get_mpf_mat(mpf_mat_t B, const fmpz_mat_t A) { slong i; if (A->c != 0) for (i = 0; i < A->r; i++) _fmpz_vec_get_mpf_vec(B->rows[i], A->rows[i], A->c); } flint2-2.8.4/fmpz_mat/get_nmod_mat.c000066400000000000000000000023041414523752600173510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" void fmpz_mat_get_nmod_mat(nmod_mat_t Amod, const fmpz_mat_t A) { slong i, j; mp_limb_t m = Amod->mod.n; 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_fdiv_ui(A->rows[i]+i, m); for (j = i + 1; j < A->c; j++) { Amod->rows[i][j] = fmpz_fdiv_ui(A->rows[i] + j, m); 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_fdiv_ui(A->rows[j] + i, m); } } } else { for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) Amod->rows[i][j] = fmpz_fdiv_ui(A->rows[i] + j, m); } } flint2-2.8.4/fmpz_mat/gram.c000066400000000000000000000022521414523752600156440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_mat_gram). Incompatible dimensions.\n"); flint_abort(); } 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)); } } } } flint2-2.8.4/fmpz_mat/hadamard.c000066400000000000000000000131601414523752600164570ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; fmpz_t pp; 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) { printf("Exception (fmpz_mat_jacobsthal). Not an odd prime power.\n"); flint_abort(); p = 0; /* not reached, but silence compiler warning */ } fmpz_init_set_ui(pp, p); fq_nmod_ctx_init(ctx, pp, 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); fmpz_clear(pp); } /* 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; count_trailing_zeros(v, 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; } flint2-2.8.4/fmpz_mat/hnf.c000066400000000000000000000023101414523752600154640ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/fmpz_mat/hnf_classical.c000066400000000000000000000064361414523752600175170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/hnf_minors.c000066400000000000000000000124061414523752600170620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/hnf_minors_transform.c000066400000000000000000000161621414523752600211600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/hnf_modular.c000066400000000000000000000062441414523752600172210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/hnf_modular_eldiv.c000066400000000000000000000021211414523752600203720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } } flint2-2.8.4/fmpz_mat/hnf_pernet_stein.c000066400000000000000000000460261414523752600202570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq_mat.h" #include "perm.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_printf("Exception (fmpz_mat_hnf_pernet_stein). " "Nullspace was not dimension one.\n"); flint_abort(); } 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_printf("Exception (fmpz_mat_hnf_pernet_stein). " "Singular input matrix for solve."); flint_abort(); } /* 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); } flint2-2.8.4/fmpz_mat/hnf_transform.c000066400000000000000000000037511414523752600175710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mat/hnf_xgcd.c000066400000000000000000000052171414523752600165020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/howell_form_mod.c000066400000000000000000000017711414523752600200770ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_mat/init.c000066400000000000000000000020151414523752600156560ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_mat/init_set.c000066400000000000000000000011011414523752600165240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/inlines.c000066400000000000000000000011561414523752600163610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mat.h" flint2-2.8.4/fmpz_mat/inv.c000066400000000000000000000033211414523752600155100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/fmpz_mat/is_hadamard.c000066400000000000000000000021501414523752600171470ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/is_in_hnf.c000066400000000000000000000026721414523752600166600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/is_in_rref_with_rank.c000066400000000000000000000027671414523752600211160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/is_in_snf.c000066400000000000000000000022661414523752600166720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/is_one.c000066400000000000000000000014421414523752600161720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/is_reduced.c000066400000000000000000000060071414523752600170260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq_vec.h" #include "fmpq_mat.h" int fmpz_mat_is_reduced(const fmpz_mat_t A, double delta, double eta) { 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); 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 */ { fmpq_mat_clear(Aq); fmpq_mat_clear(Bq); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); return 0; } } 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 */ { fmpq_mat_clear(Aq); fmpq_mat_clear(Bq); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); return 0; } } fmpq_mat_clear(Aq); fmpq_mat_clear(Bq); fmpq_mat_clear(mu); fmpq_clear(deltaq); fmpq_clear(etaq); fmpq_clear(tmp); return 1; } flint2-2.8.4/fmpz_mat/is_reduced_gram.c000066400000000000000000000053741414523752600200420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq_mat.h" #include "fmpq_vec.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; } flint2-2.8.4/fmpz_mat/is_reduced_gram_with_removal.c000066400000000000000000000075201414523752600226150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq_mat.h" #include "fmpq_vec.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; } flint2-2.8.4/fmpz_mat/is_reduced_with_removal.c000066400000000000000000000101411414523752600216000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.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) { 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) { 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 0; } 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); 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 */ { 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 0; } } } _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 */ { 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 0; } 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 */ { 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 0; } } } 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 1; } flint2-2.8.4/fmpz_mat/is_zero.c000066400000000000000000000012241414523752600163660ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/kronecker_product.c000066400000000000000000000017251414523752600204450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } } } } } flint2-2.8.4/fmpz_mat/lll_original.c000066400000000000000000000135351414523752600173730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.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); } flint2-2.8.4/fmpz_mat/lll_storjohann.c000066400000000000000000000202321414523752600177440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.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); } flint2-2.8.4/fmpz_mat/max_bits.c000066400000000000000000000015401414523752600165230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/minpoly_modular.c000066400000000000000000000165461414523752600201430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "nmod_poly.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); } flint2-2.8.4/fmpz_mat/mul.c000066400000000000000000000160431414523752600155160ustar00rootroot00000000000000/* Copyright (C) 2010,2011,2018 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 2.1 of the License, or (at your option) any later version. See . */ #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; 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) { 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)); return; } 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 <= FLINT_BITS - 2 && bbits <= FLINT_BITS - 2) { /* 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 <= FLINT_BITS - 2) _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 <= FLINT_BITS - 2 && dim - 1000 > limit) { /* strassen avoids big fmpz intermediates */ fmpz_mat_mul_strassen(C, A, B); return; } else if (cbits > FLINT_BITS - 2 && 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 { if (dim >= 3 * FLINT_BIT_COUNT(cbits)) /* tuning param */ _fmpz_mat_mul_multi_mod(C, A, B, sign, cbits); else if (abits >= 500 && bbits >= 500 && dim >= 8) /* tuning param */ fmpz_mat_mul_strassen(C, A, B); else fmpz_mat_mul_classical_inline(C, A, B); } } flint2-2.8.4/fmpz_mat/mul_blas.c000066400000000000000000000405151414523752600165200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" #include "n_poly.h" #include "mpn_extras.h" #if FLINT_USES_BLAS && FLINT_BITS == 64 #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); } flint2-2.8.4/fmpz_mat/mul_classical.c000066400000000000000000000021361414523752600175320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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, bc, br; slong i, j, k; ar = A->r; br = B->r; bc = B->c; if (br == 0) { fmpz_mat_zero(C); return; } 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)); for (k = 1; k < br; k++) { fmpz_addmul(fmpz_mat_entry(C, i, j), fmpz_mat_entry(A, i, k), fmpz_mat_entry(B, k, j)); } } } } flint2-2.8.4/fmpz_mat/mul_classical_inline.c000066400000000000000000000065331414523752600210750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "longlong.h" void fmpz_mat_mul_classical_inline(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B) { slong ar, bc, br; slong i, j, k; fmpz a, b; mpz_t t; mp_limb_t au, bu; mp_limb_t pos[3]; mp_limb_t neg[3]; ar = A->r; br = B->r; bc = B->c; mpz_init(t); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { flint_mpz_set_ui(t, UWORD(0)); pos[2] = pos[1] = pos[0] = neg[2] = neg[1] = neg[0] = UWORD(0); for (k = 0; k < br; k++) { a = A->rows[i][k]; b = B->rows[k][j]; if (a == 0 || b == 0) continue; if (!COEFF_IS_MPZ(a)) /* a is small */ { if (!COEFF_IS_MPZ(b)) /* both are small */ { au = FLINT_ABS(a); bu = FLINT_ABS(b); umul_ppmm(au, bu, au, bu); if ((a ^ b) >= WORD(0)) add_sssaaaaaa(pos[2], pos[1], pos[0], pos[2], pos[1], pos[0], 0, au, bu); else add_sssaaaaaa(neg[2], neg[1], neg[0], neg[2], neg[1], neg[0], 0, au, bu); } else { if (a >= 0) flint_mpz_addmul_ui(t, COEFF_TO_PTR(b), a); else flint_mpz_submul_ui(t, COEFF_TO_PTR(b), -a); } } else if (!COEFF_IS_MPZ(b)) /* b is small */ { if (b >= 0) flint_mpz_addmul_ui(t, COEFF_TO_PTR(a), b); else flint_mpz_submul_ui(t, COEFF_TO_PTR(a), -b); } else { mpz_addmul(t, COEFF_TO_PTR(a), COEFF_TO_PTR(b)); } } if (mpz_sgn(t) != 0 || pos[2] || neg[2] || pos[1] || neg[1]) { __mpz_struct r; r._mp_size = pos[2] ? 3 : (pos[1] ? 2 : pos[0] != 0); r._mp_alloc = r._mp_size; r._mp_d = pos; mpz_add(t, t, &r); r._mp_size = neg[2] ? 3 : (neg[1] ? 2 : neg[0] != 0); r._mp_alloc = r._mp_size; r._mp_d = neg; mpz_sub(t, t, &r); fmpz_set_mpz(fmpz_mat_entry(C, i, j), t); } else { if (neg[0] > pos[0]) fmpz_neg_ui(fmpz_mat_entry(C, i, j), neg[0] - pos[0]); else fmpz_set_ui(fmpz_mat_entry(C, i, j), pos[0] - neg[0]); } } } mpz_clear(t); } flint2-2.8.4/fmpz_mat/mul_double_word.c000066400000000000000000000337031414523752600201050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 */ FLINT_DLL 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); } flint2-2.8.4/fmpz_mat/mul_fmpz_vec.c000066400000000000000000000012071414523752600174030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/mul_fmpz_vec_ptr.c000066400000000000000000000014351414523752600202730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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]); } } flint2-2.8.4/fmpz_mat/mul_multi_mod.c000066400000000000000000000341131414523752600175650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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]; } 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); } 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 */ 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); 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]); 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], 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]); nmod_mat_clear(mainarg.mod_B[i]); nmod_mat_clear(mainarg.mod_C[i]); } flint_free(mainarg.mod_A); 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); } flint2-2.8.4/fmpz_mat/mul_small.c000066400000000000000000000262471414523752600167150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 <= FLINT_BITS - 2) 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); } flint2-2.8.4/fmpz_mat/mul_strassen.c000066400000000000000000000076171414523752600174470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpz.h" #include "fmpz_vec.h" #include "flint.h" 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 <= 4 || b <= 4 || c <= 4) { fmpz_mat_mul(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_sub(X1, A11, A21); fmpz_mat_sub(X2, B22, B12); fmpz_mat_mul(C21, X1, X2); fmpz_mat_add(X1, A21, A22); fmpz_mat_sub(X2, B12, B11); fmpz_mat_mul(C22, X1, X2); fmpz_mat_sub(X1, X1, A11); fmpz_mat_sub(X2, B22, X2); fmpz_mat_mul(C12, X1, X2); fmpz_mat_sub(X1, A12, X1); fmpz_mat_mul(C11, X1, B22); X1->c = bnc; fmpz_mat_mul(X1, A11, B11); fmpz_mat_add(C12, X1, C12); fmpz_mat_add(C21, C12, C21); fmpz_mat_add(C12, C12, C22); fmpz_mat_add(C22, C21, C22); fmpz_mat_add(C12, C12, C11); fmpz_mat_sub(X2, X2, B21); fmpz_mat_mul(C11, A22, X2); fmpz_mat_clear(X2); fmpz_mat_sub(C21, C21, C11); fmpz_mat_mul(C11, A12, B21); 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); } } flint2-2.8.4/fmpz_mat/multi_CRT_ui.c000066400000000000000000000027301414523752600172560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/multi_mod_ui.c000066400000000000000000000026601414523752600174070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/neg.c000066400000000000000000000011431414523752600154650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/next_col_van_hoeij.c000066400000000000000000000065121414523752600205560ustar00rootroot00000000000000/* 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 2.1 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) abort(); 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; } flint2-2.8.4/fmpz_mat/nullspace.c000066400000000000000000000034041414523752600167040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/one.c000066400000000000000000000011241414523752600154740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpz_mat/pow.c000066400000000000000000000025621414523752600155270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mat/profile/000077500000000000000000000000001414523752600162115ustar00rootroot00000000000000flint2-2.8.4/fmpz_mat/profile/p-big_mul.c000066400000000000000000000146071414523752600202400ustar00rootroot00000000000000/* 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 2.1 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" /* 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; } flint2-2.8.4/fmpz_mat/profile/p-det.c000066400000000000000000000045271414523752600173760ustar00rootroot00000000000000/* 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 2.1 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" 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; } flint2-2.8.4/fmpz_mat/profile/p-mul.c000066400000000000000000000064341414523752600174160ustar00rootroot00000000000000/* 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 2.1 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" 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, m = params->m, n = params->n, k = params->k; 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, n, k); fmpz_mat_init(C, m, k); fmpz_mat_randbits(A, state, bits); fmpz_mat_randbits(B, state, bits); 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_mul_classical(C, A, B); else if (algorithm == 2) for (i = 0; i < count; i++) fmpz_mat_mul_classical_inline(C, A, B); else if (algorithm == 3) for (i = 0; i < count; i++) fmpz_mat_mul_multi_mod(C, A, B); else if (algorithm == 4) for (i = 0; i < count; i++) fmpz_mat_mul_strassen(C, A, B); 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, min_inline, min_multi_mod, min_strassen, max; mat_mul_t params; slong bits, dim; for (bits = 1; bits <= 2000; bits = (slong) ((double) bits * 1.3) + 1) { params.bits = bits; flint_printf("fmpz_mat_mul (bits = %wd):\n", params.bits); for (dim = 1; dim <= 512; dim = (slong) ((double) dim * 1.3) + 1) { params.m = dim; params.n = dim; params.k = dim; 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_inline, &max, sample, ¶ms); params.algorithm = 3; prof_repeat(&min_multi_mod, &max, sample, ¶ms); params.algorithm = 4; prof_repeat(&min_strassen, &max, sample, ¶ms); flint_printf("dim = %wd default/classical/inline/multi_mod/strassen %.2f %.2f %.2f %.2f %.2f (us)\n", dim, min_default, min_classical, min_inline, min_multi_mod, min_strassen); if (min_multi_mod < 0.6*min_default) flint_printf("BAD!\n"); if (min_inline < 0.6*min_default) flint_printf("BAD!\n"); if (min_strassen < 0.7*min_default) flint_printf("BAD!\n"); if (min_multi_mod < 0.7*min_inline) break; } } return 0; } flint2-2.8.4/fmpz_mat/profile/p-mul_blas_v_mul.c000066400000000000000000000051051414523752600216130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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 flint2-2.8.4/fmpz_mat/profile/p-mul_double_word.c000066400000000000000000000056601414523752600220030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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_inline(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; } flint2-2.8.4/fmpz_mat/profile/p-mul_double_word_v_mul_multi_mod.c000066400000000000000000000060431414523752600252520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/fmpz_mat/profile/p-mul_multi_mod.c000066400000000000000000000046501414523752600214650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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_inline(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; } flint2-2.8.4/fmpz_mat/profile/p-mul_small.c000066400000000000000000000115221414523752600206000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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 <= FLINT_BITS - 2; Abits += 16) for (Bbits = Abits; Bbits <= FLINT_BITS - 2; 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 <= FLINT_BITS - 2; Abits += 8) for (Bbits = Abits; Bbits <= FLINT_BITS - 2; 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; } flint2-2.8.4/fmpz_mat/profile/p-mul_small_v_mul_multi_mod.c000066400000000000000000000054651414523752600240640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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 <= FLINT_BITS - 2; Abits += FLINT_BITS) for (Bbits = Abits; Bbits <= FLINT_BITS - 2; Bbits += 16) { if (FLINT_BIT_COUNT(dim) + Abits + Bbits <= FLINT_BITS - 2) 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; } flint2-2.8.4/fmpz_mat/profile/p-sqr.c000066400000000000000000000041331414523752600174200ustar00rootroot00000000000000/* 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 2.1 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" 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, C; FLINT_TEST_INIT(state); fmpz_mat_init(A, m, n); fmpz_mat_init(C, m, n); fmpz_mat_randbits(A, state, bits); prof_start(); if (algorithm == 0) for (i = 0; i < count; i++) fmpz_mat_mul(C, A, A); else if (algorithm == 1) for (i = 0; i < count; i++) fmpz_mat_sqr(C, A); prof_stop(); fmpz_mat_clear(A); 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 = 1; bits <=2000; bits = (slong) ((double) bits) + 100) { params.bits = bits; flint_printf("bits = %wd :\n", params.bits); for (dim = 1; dim <= 312; dim = (slong) ((double) dim * 2.3) + 2) { 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; } flint2-2.8.4/fmpz_mat/randajtai.c000066400000000000000000000026751414523752600166640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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_printf("Exception (fmpz_mat_ajtai): Non-square matrix.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_mat/randbits.c000066400000000000000000000012251414523752600165230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/randdet.c000066400000000000000000000040041414523752600163340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpz.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_printf("Exception (fmpz_mat_randdet). Non-square matrix.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_mat/randintrel.c000066400000000000000000000020111414523752600170510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_mat_randintrel). c != r + 1.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpz_mat/randntrulike.c000066400000000000000000000032631414523752600174230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_mat_randntrulike). Ill-formed matrix.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_mat/randntrulike2.c000066400000000000000000000032651414523752600175070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_mat_randntrulike2). Ill-formed matrix.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_mat/randops.c000066400000000000000000000031351414523752600163650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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]); } } } flint2-2.8.4/fmpz_mat/randpermdiag.c000066400000000000000000000017041414523752600173540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "perm.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; } flint2-2.8.4/fmpz_mat/randrank.c000066400000000000000000000016311414523752600165160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_mat_randrank). Impossible rank.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_mat/randsimdioph.c000066400000000000000000000023231414523752600173760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_mat_randsimdioph). Ill-formed matrix.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpz_mat/randtest.c000066400000000000000000000012251414523752600165410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/randtest_unsigned.c000066400000000000000000000012471414523752600204410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/rank.c000066400000000000000000000016521414523752600156540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/rank_small_inplace.c000066400000000000000000000053021414523752600205330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "perm.h" #include "longlong.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; } flint2-2.8.4/fmpz_mat/rref.c000066400000000000000000000013571414523752600156610ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_mat/rref_fflu.c000066400000000000000000000044551414523752600166770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/rref_mod.c000066400000000000000000000036341414523752600165200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #define E(j,k) fmpz_mat_entry(A,j,k) slong fmpz_mat_rref_mod(slong * perm, fmpz_mat_t A, const fmpz_t p) { fmpz_t t, inv; slong m, n, j, k, rank, r, pivot_row, pivot_col; if (fmpz_mat_is_empty(A)) { return 0; } m = A->r; n = A->c; rank = pivot_row = pivot_col = 0; fmpz_init(t); fmpz_init(inv); while (pivot_row < m && pivot_col < n) { r = fmpz_mat_find_pivot_any(A, pivot_row, m, pivot_col); if (r == -1) { pivot_col++; continue; } else if (r != pivot_row) { fmpz_mat_swap_rows(A, perm, pivot_row, r); } rank++; fmpz_invmod(inv, E(pivot_row, pivot_col), p); /* pivot row */ for (k = pivot_col + 1; k < n; k++) { fmpz_mul(E(pivot_row, k), E(pivot_row, k), inv); fmpz_mod(E(pivot_row, k), E(pivot_row, k), p); } fmpz_one(E(pivot_row, pivot_col)); /* other rows */ for (j = 0; j < m; j++) { if (j == pivot_row) continue; for (k = pivot_col + 1; k < n; k++) { fmpz_mul(t, E(j, pivot_col), E(pivot_row, k)); fmpz_sub(E(j, k), E(j, k), t); fmpz_mod(E(j, k), E(j, k), p); } fmpz_zero(E(j, pivot_col)); } pivot_row++; pivot_col++; } fmpz_clear(inv); fmpz_clear(t); return rank; } flint2-2.8.4/fmpz_mat/rref_mul.c000066400000000000000000000103041414523752600165260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "fmpq_mat.h" #include "perm.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_printf("Exception (fmpz_mat_rref_mul). " "Singular input matrix for solve."); flint_abort(); } 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; } flint2-2.8.4/fmpz_mat/scalar_addmul_fmpz.c000066400000000000000000000012141414523752600205420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/scalar_addmul_nmod_mat_fmpz.c000066400000000000000000000012601414523752600224210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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)); } flint2-2.8.4/fmpz_mat/scalar_addmul_nmod_mat_ui.c000066400000000000000000000012041414523752600220600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_addmul_si.c000066400000000000000000000011271414523752600202040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_addmul_ui.c000066400000000000000000000012061414523752600202040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_divexact_fmpz.c000066400000000000000000000012201414523752600211000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_divexact_si.c000066400000000000000000000012121414523752600205400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_divexact_ui.c000066400000000000000000000012121414523752600205420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_mod_fmpz.c000066400000000000000000000012121414523752600200510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_mul_2exp.c000066400000000000000000000015471414523752600200040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_mul_fmpz.c000066400000000000000000000012061414523752600200720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_mul_si.c000066400000000000000000000012001414523752600175230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_mul_ui.c000066400000000000000000000012001414523752600175250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_smod.c000066400000000000000000000011721414523752600172050ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_submul_fmpz.c000066400000000000000000000012141414523752600206030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_submul_si.c000066400000000000000000000011271414523752600202450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_submul_ui.c000066400000000000000000000012061414523752600202450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/scalar_tdiv_q_2exp.c000066400000000000000000000014361414523752600204720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/set.c000066400000000000000000000013031414523752600155050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mat/set_nmod_mat.c000066400000000000000000000012621414523752600173670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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); } flint2-2.8.4/fmpz_mat/set_nmod_mat_unsigned.c000066400000000000000000000012141414523752600212600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" 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)); } flint2-2.8.4/fmpz_mat/similarity.c000066400000000000000000000020411414523752600171000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #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); } } flint2-2.8.4/fmpz_mat/snf.c000066400000000000000000000022501414523752600155020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mat/snf_diagonal.c000066400000000000000000000021551414523752600173440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/snf_iliopoulos.c000066400000000000000000000150521414523752600177640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/snf_kannan_bachem.c000066400000000000000000000116701414523752600203350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/solve.c000066400000000000000000000015431414523752600160500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "perm.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); } flint2-2.8.4/fmpz_mat/solve_bound.c000066400000000000000000000021131414523752600172310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/solve_cramer.c000066400000000000000000000102471414523752600174020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_mat_solve_cramer). dim > 3 not implemented."); flint_abort(); return 0; /* not reached, but silence compiler warning */ } } flint2-2.8.4/fmpz_mat/solve_dixon.c000066400000000000000000000141161414523752600172510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_mat_solve_dixon). Non-square system matrix.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpz_mat/solve_dixon_den.c000066400000000000000000000014571414523752600201030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpz_mat/solve_fflu.c000066400000000000000000000022041414523752600170570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "perm.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; } flint2-2.8.4/fmpz_mat/solve_fflu_precomp.c000066400000000000000000000244061414523752600206140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_abort(); } else { slong i, j; if (perm == NULL) flint_abort(); 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) <= FLINT_BITS - 2 && FLINT_ABS(bbits) <= FLINT_BITS - 2; 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 */ { count_leading_zeros(norm, uden); invert_limb(dinv, 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 */ { count_leading_zeros(norm, uden); invert_limb(dinv, 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; } flint2-2.8.4/fmpz_mat/solve_multi_mod_den.c000066400000000000000000000031621414523752600207460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/sqr.c000066400000000000000000000022421414523752600155220ustar00rootroot00000000000000/* Copyright (C) 2012 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #define E fmpz_mat_entry 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 <= 12) { if (n <= 3) { fmpz_mat_sqr_bodrato(B, A); } else { fmpz_mat_mul(B, A, A); } } else { ab = fmpz_mat_max_bits(A); ab = FLINT_ABS(ab); if (5*(ab + ab) > n * n ) { fmpz_mat_sqr_bodrato(B, A); } else { fmpz_mat_mul(B, A, A); } } } flint2-2.8.4/fmpz_mat/sqr_bodrato.c000066400000000000000000000163521414523752600172430ustar00rootroot00000000000000/* Copyright (C) 2012 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #define E fmpz_mat_entry 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) { fmpz_t t, u; fmpz_init(t); fmpz_init(u); fmpz_add(t, E(A, 0, 0), E(A, 1, 1)); fmpz_mul(u, 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), u); fmpz_mul(E(B, 1, 1), E(A, 1, 1), E(A, 1, 1)); fmpz_add(E(B, 1, 1), E(B, 1, 1), u); 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); fmpz_clear(u); } else if (n == 3) { fmpz_t temp13, temp12, temp23; fmpz_init(temp13); fmpz_init(temp12); fmpz_init(temp23); fmpz_mul(temp13, E(A, 0, 2), E(A, 2, 0)); fmpz_mul(temp12, E(A, 0, 1), E(A, 1, 0)); fmpz_mul(temp23, E(A, 1, 2), E(A, 2, 1)); fmpz_add(E(B, 0, 0), temp13, temp12); fmpz_addmul(E(B, 0, 0), E(A, 0, 0), E(A, 0, 0)); fmpz_add(E(B, 1, 1), temp23, temp12); fmpz_addmul(E(B, 1, 1), E(A, 1, 1), E(A, 1, 1)); fmpz_add(E(B, 2, 2), temp13, temp23); fmpz_addmul(E(B, 2, 2), E(A, 2, 2), E(A, 2, 2)); fmpz_add(temp12, E(A, 0, 0), E(A, 1, 1)); fmpz_add(temp13, E(A, 0, 0), E(A, 2, 2)); fmpz_add(temp23, E(A, 1, 1), E(A, 2, 2)); fmpz_mul(E(B, 0, 1), temp12, E(A, 0, 1)); fmpz_addmul(E(B, 0, 1), E(A, 0, 2), E(A, 2, 1)); fmpz_mul(E(B, 0, 2), temp13, E(A, 0, 2)); fmpz_addmul(E(B, 0, 2), E(A, 0, 1), E(A, 1, 2)); fmpz_mul(E(B, 1, 0), temp12, E(A, 1, 0)); fmpz_addmul(E(B, 1, 0), E(A, 2, 0), E(A, 1, 2)); fmpz_mul(E(B, 1, 2), temp23, E(A, 1, 2)); fmpz_addmul(E(B, 1, 2), E(A, 1, 0), E(A, 0, 2)); fmpz_mul(E(B, 2, 0), temp13, E(A, 2, 0)); fmpz_addmul(E(B, 2, 0), E(A, 2, 1), E(A, 1, 0)); fmpz_mul(E(B, 2, 1), temp23, E(A, 2, 1)); fmpz_addmul(E(B, 2, 1), E(A, 0, 1), E(A, 2, 0)); fmpz_clear(temp13); fmpz_clear(temp23); fmpz_clear(temp12); } else { slong i,j; fmpz_mat_t window11, window12, window21, window22; fmpz_mat_t s1, s2, s3; fmpz_mat_t p1, p2, p3, p5, p6; slong m = n, x, iseven = 1; if (n % 2 == 1) { m = n - 1; iseven = 0; } fmpz_mat_init(s1, m/2, m/2); fmpz_mat_init(s2, m/2, m/2); fmpz_mat_init(s3, m/2, m/2); fmpz_mat_init(p1, m/2, m/2); fmpz_mat_init(p2, m/2, m/2); fmpz_mat_init(p3, m/2, m/2); fmpz_mat_init(p5, m/2, m/2); fmpz_mat_init(p6, m/2, m/2); fmpz_mat_window_init(window11, A, 0, 0, m/2, m/2); fmpz_mat_window_init(window12, A, 0, m/2, m/2, m); fmpz_mat_window_init(window21, A, m/2, 0, m, m/2); fmpz_mat_window_init(window22, A, m/2, m/2, m, m); fmpz_mat_add(s1, window22, window12); fmpz_mat_sqr(p1, s1); fmpz_mat_sub(s2, window22, window21); fmpz_mat_sqr(p2, s2); fmpz_mat_add(s3, s2, window12); fmpz_mat_sqr(p3, s3); fmpz_mat_sub(s1, s3, window11); fmpz_mat_mul(p6, s1, window12); fmpz_mat_mul(s3, window21, s1); fmpz_mat_mul(p5, window12, window21); fmpz_mat_add(s1, p3, p5); fmpz_mat_sub(s2, p1, s1); if (iseven == 1) { for (i = n/2; i < n; i++) { for (j = 0; j < n/2; j++) { fmpz_sub(E(B, i, j), E(s2, i - n/2, j), E(s3, i - n/2, j)); } } fmpz_mat_sub(s3, s1, p2); fmpz_mat_sqr(s1, window11); for (i = 0; i < n/2; i++) { for (j = 0; j < n/2; j++) { fmpz_add(E(B, i, j), E(s1, i, j), E(p5, i, j)); } } for (i = n/2; i < n; i++) { for (j = n/2; j < n; j++) { fmpz_add(E(B, i, j), E(p2, i - n/2, j - n/2), E(s2, i - n/2, j - n/2)); } } for (i = 0; i < n/2; i++) { for (j = n/2; j < n; j++) { fmpz_sub(E(B, i, j), E(s3, i, j - n/2), E(p6, i, j - n/2) ); } } } else { for (i = 0; i < n; i++) { fmpz_mul(E(B, n - 1, i), E(A, n - 1, 0), E(A, 0, i)); for (x = 1; x < n; x++) { fmpz_addmul(E(B, n - 1, i), E(A, n - 1, x), E(A, x, i)); } } for (i = 0; i < n; i++) { fmpz_mul(E(B, i, n - 1), E(A, 0, n - 1), E(A, i, 0)); for (x = 1; x < n; x++) { fmpz_addmul(E(B, i, n - 1), E(A, x, n - 1), E(A, i, x)); } } for (i = m/2; i < m; i++) { for (j = 0; j < m/2; j++) { fmpz_sub(E(B, i, j), E(s2, i - m/2, j), E(s3, i - m/2, j)); fmpz_addmul(E(B, i, j), E(A, i, n - 1), E(A, n - 1, j)); } } fmpz_mat_sub(s3, s1, p2); fmpz_mat_sqr(s1, window11); for (i = 0; i < m/2; i++) { for (j = 0; j < m/2; j++) { fmpz_add(E(B, i, j), E(s1, i, j), E(p5, i, j)); fmpz_addmul(E(B, i, j), E(A, i, n - 1), E(A, n - 1, j)); } } for (i = m/2; i < m; i++) { for (j = m/2; j < m; j++) { fmpz_add(E(B, i, j), E(p2, i - m/2, j - m/2), E(s2, i - m/2, j - m/2)); fmpz_addmul(E(B, i, j), E(A, i, n - 1), E(A, n - 1, j)); } } for (i = 0; i < m/2; i++) { for (j = m/2; j < m; j++) { fmpz_sub(E(B, i, j), E(s3, i, j - m/2), E(p6, i, j - m/2)); fmpz_addmul(E(B, i, j), E(A, i, n - 1), E(A, n - 1, j)); } } } fmpz_mat_window_clear(window11); fmpz_mat_window_clear(window12); fmpz_mat_window_clear(window21); fmpz_mat_window_clear(window22); fmpz_mat_clear(s1); fmpz_mat_clear(s2); fmpz_mat_clear(s3); fmpz_mat_clear(p1); fmpz_mat_clear(p2); fmpz_mat_clear(p3); fmpz_mat_clear(p5); fmpz_mat_clear(p6); } } flint2-2.8.4/fmpz_mat/strong_echelon_form_mod.c000066400000000000000000000202501414523752600216070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 wether 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); } flint2-2.8.4/fmpz_mat/sub.c000066400000000000000000000012131414523752600155030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mat/swap.c000066400000000000000000000011221414523752600156630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" void fmpz_mat_swap(fmpz_mat_t mat1, fmpz_mat_t mat2) { if (mat1 != mat2) { fmpz_mat_struct tmp; tmp = *mat1; *mat1 = *mat2; *mat2 = tmp; } } flint2-2.8.4/fmpz_mat/test/000077500000000000000000000000001414523752600155305ustar00rootroot00000000000000flint2-2.8.4/fmpz_mat/test/t-CRT_ui.c000066400000000000000000000053411414523752600172650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("CRT_ui...."); fflush(stdout); 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"); abort(); } nmod_mat_clear(Amod); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-CRT_ui_unsigned.c000066400000000000000000000053351414523752600211640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("CRT_ui_unsigned...."); fflush(stdout); 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"); abort(); } nmod_mat_clear(Amod); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-add_sub.c000066400000000000000000000026721414523752600175450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep; FLINT_TEST_INIT(state); flint_printf("add/sub/neg...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-can_solve_fflu.c000066400000000000000000000102261414523752600211230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, k; int success; FLINT_TEST_INIT(state); flint_printf("can_solve_fflu...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-can_solve_multi_mod_den.c000066400000000000000000000102571414523752600230120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, k; int success; FLINT_TEST_INIT(state); flint_printf("can_solve_multi_mod_den...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-charpoly.c000066400000000000000000000063021414523752600177570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep, i; FLINT_TEST_INIT(state); flint_printf("charpoly...."); fflush(stdout); 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"); 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"); abort(); } fmpz_clear(c); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_poly_clear(f); fmpz_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-charpoly_berkowitz.c000066400000000000000000000063641414523752600220670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep, i; FLINT_TEST_INIT(state); flint_printf("charpoly_berkowitz...."); fflush(stdout); 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"); 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"); abort(); } fmpz_clear(c); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_poly_clear(f); fmpz_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-chol_d.c000066400000000000000000000034141414523752600173670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "ulong_extras.h" #define FMPZ_MAT_CHOL_EPS (1.0E-9) int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("chol_d...."); fflush(stdout); /* 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); abort(); } fmpz_mat_clear(A); d_mat_clear(R); d_mat_clear(Rt); d_mat_clear(Atmp); d_mat_clear(Btmp); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_mat/test/t-col_partition.c000066400000000000000000000052061414523752600210060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { int result = 0; slong i; FLINT_TEST_INIT(state); flint_printf("col_partition...."); fflush(stdout); 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); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); flint_free(part); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-concat_horizontal.c000066400000000000000000000034631414523752600216630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, B, C; fmpz_mat_t window1, window2; slong i; FLINT_TEST_INIT(state); flint_printf("concat_horizontal...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_window_clear(window1); fmpz_mat_window_clear(window2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-concat_vertical.c000066400000000000000000000034471414523752600213050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, B, C; fmpz_mat_t window1, window2; slong i; FLINT_TEST_INIT(state); flint_printf("concat_vertical...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_window_clear(window1); fmpz_mat_window_clear(window2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-content.c000066400000000000000000000031431414523752600176100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "long_extras.h" int main() { int i; fmpz_mat_t A,B; fmpz_t scalar, gcd_mat, temp; FLINT_TEST_INIT(state); flint_printf("fmpz_mat_content...."); fflush(stdout); 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"); 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"); abort(); } cleanup: fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_clear(scalar); fmpz_clear(temp); fmpz_clear(gcd_mat); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-det.c000066400000000000000000000044411414523752600167140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A; slong i, m; fmpz_t det, result; FLINT_TEST_INIT(state); flint_printf("det...."); fflush(stdout); 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(result); 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"); flint_printf("wrong determinant!\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"); abort(); } fmpz_mat_clear(A); fmpz_clear(det); fmpz_clear(result); } /* Generate nontrivial singular matrices */ for (i = 0; i < 10000; i++) { m = 2 + n_randint(state, 10); fmpz_mat_init(A, m, m); fmpz_init(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)); fmpz_mat_det(det, A); if (*det) { flint_printf("FAIL:\n"); flint_printf("expected zero determinant!\n"); fmpz_mat_print_pretty(A), flint_printf("\n"); abort(); } fmpz_mat_clear(A); fmpz_clear(det); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-det_bound.c000066400000000000000000000030311414523752600200750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A; slong i, m; fmpz_t det, bound; FLINT_TEST_INIT(state); flint_printf("det_bound...."); fflush(stdout); 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"); abort(); } fmpz_clear(det); fmpz_clear(bound); fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-det_divisor.c000066400000000000000000000042111414523752600204460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong i; int result; FLINT_TEST_INIT(state); flint_printf("det_divisor...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); fmpz_clear(det); fmpz_clear(d); fmpz_clear(q); fmpz_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-det_modular.c000066400000000000000000000044421414523752600204400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A; slong i, m; fmpz_t det1, det2; FLINT_TEST_INIT(state); flint_printf("det_modular...."); fflush(stdout); 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"); 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"); abort(); } fmpz_mat_clear(A); fmpz_clear(det2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-det_modular_accelerated.c000066400000000000000000000045021414523752600227510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A; slong i, m; fmpz_t det1, det2; FLINT_TEST_INIT(state); flint_printf("det_modular_accelerated...."); fflush(stdout); 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"); 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"); abort(); } fmpz_mat_clear(A); fmpz_clear(det2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-entry.c000066400000000000000000000030071414523752600172760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("entry...."); fflush(stdout); 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); abort(); } } } fmpz_mat_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-equal.c000066400000000000000000000036261414523752600172530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("equal...."); fflush(stdout); 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"); 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"); 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"); abort(); } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); fmpz_mat_clear(E); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-fmpz_vec_mul.c000066400000000000000000000052151414523752600206260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("fmpz_vec_mul...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-get_d_mat.c000066400000000000000000000035071414523752600200650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("get_d_mat...."); fflush(stdout); /* 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); abort(); } } } fmpz_mat_clear(A); d_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-get_d_mat_transpose.c000066400000000000000000000035331414523752600221620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("get_d_mat_transpose...."); fflush(stdout); /* 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); abort(); } } } fmpz_mat_clear(A); d_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-get_mpf_mat.c000066400000000000000000000036041414523752600204220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("get_mpf_mat...."); fflush(stdout); /* set entries of an fmpz_mat, convert to mpf_mat and then check that the entries remain same */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mat_t A; mpf_mat_t B; slong j, k; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); fmpz_mat_init(A, rows, cols); mpf_mat_init(B, rows, cols, mpf_get_default_prec()); 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_mpf_mat(B, A); for (j = 0; j < rows; j++) { for (k = 0; k < cols; k++) { if (flint_mpf_cmp_ui(mpf_mat_entry(B, j, k), 3 * j + 7 * k) != 0) { flint_printf("FAIL: j = %wd, k = %wd\n", j, k); fmpz_mat_print_pretty(A); mpf_mat_print(B); abort(); } } } fmpz_mat_clear(A); mpf_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-get_nmod_mat.c000066400000000000000000000031601414523752600205720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("get/set_nmod_mat...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); nmod_mat_clear(M); nmod_mat_clear(M2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-gram.c000066400000000000000000000024531414523752600170670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" int main(void) { fmpz_mat_t A, B, C, D; slong i; FLINT_TEST_INIT(state); flint_printf("gram...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-hadamard.c000066400000000000000000000032111414523752600176730ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.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; } int main(void) { int n; FLINT_TEST_INIT(state); flint_printf("hadamard...."); fflush(stdout); 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"); abort(); } } else if (should_have_hadamard(n)) { printf("FAIL: expected Hadamard matrix of size %d to work\n\n", n); abort(); } fmpz_mat_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-hnf.c000066400000000000000000000106001414523752600167050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("hnf...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(B); fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-hnf_classical.c000066400000000000000000000041761414523752600207360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("hnf_classical...."); fflush(stdout); 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"); 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"); abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-hnf_minors.c000066400000000000000000000047771414523752600203160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("hnf_minors...."); fflush(stdout); 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"); 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"); 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"); abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-hnf_minors_transform.c000066400000000000000000000053171414523752600224000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("hnf_minors_transform...."); fflush(stdout); 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"); 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"); 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"); abort(); } fmpz_mat_clear(UA); fmpz_mat_clear(U); fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-hnf_modular.c000066400000000000000000000062241414523752600204370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("hnf_modular...."); fflush(stdout); 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"); 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"); 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"); abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(B); fmpz_mat_clear(A); fmpz_clear(det); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-hnf_modular_eldiv.c000066400000000000000000000065361414523752600216300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("hnf_modular_eldiv...."); fflush(stdout); 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"); 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"); 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"); abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(B); fmpz_mat_clear(A); fmpz_clear(det); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-hnf_pernet_stein.c000066400000000000000000000107371414523752600214770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("hnf_pernet_stein...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(B); fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-hnf_transform.c000066400000000000000000000133061414523752600210060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("hnf_transform...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_mat_clear(U); fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-hnf_xgcd.c000066400000000000000000000051521414523752600177200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("hnf_xgcd...."); fflush(stdout); 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"); 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"); 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"); abort(); } fmpz_mat_clear(U); fmpz_mat_clear(H2); fmpz_mat_clear(H); fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-howell_form_mod.c000066400000000000000000000156301414523752600213160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_mat.h" #include "perm.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; } int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("howell_form...."); 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"); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-init_clear.c000066400000000000000000000021231414523752600202440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-inv.c000066400000000000000000000076671414523752600167510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, B, C, I; fmpz_t den; slong i, j, m, r; FLINT_TEST_INIT(state); flint_printf("inv...."); fflush(stdout); { 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"); 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"); 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"); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-invert_rows_cols.c000066400000000000000000000033321414523752600215370ustar00rootroot00000000000000/* Copyright (C) 2019 Tommy Hofmann Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong n, rep; FLINT_TEST_INIT(state); flint_printf("invert_rows/cols...."); fflush(stdout); /* 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); abort(); } } } fmpz_mat_clear(A); fmpz_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-is_empty.c000066400000000000000000000021261414523752600177670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_empty...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-is_one.c000066400000000000000000000025141414523752600174130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_one...."); fflush(stdout); 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"); abort(); } if (rows && cols) { fmpz_mat_randbits(A, state, 100); if (fmpz_mat_is_one(A)) { flint_printf("FAIL!\n"); abort(); } } fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-is_square.c000066400000000000000000000021161414523752600201300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_square...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-is_zero.c000066400000000000000000000024611414523752600176120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_zero...."); fflush(stdout); 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"); abort(); } if (rows && cols) { fmpz_mat_randrank(A, state, FLINT_MIN(rows, cols), 100); if (fmpz_mat_is_zero(A)) { flint_printf("FAIL!\n"); abort(); } } fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-kronecker_product.c000066400000000000000000000045021414523752600216610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { int r, result; fmpz_mat_t A, B, C; fmpz_mat_t window1, window2; slong m, n, k, l, i, j; slong bits; FLINT_TEST_INIT(state); flint_printf("kronecker_product...."); fflush(stdout); 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); abort(); } fmpz_mat_window_clear(window1); fmpz_mat_window_clear(window2); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_mat/test/t-lll_original.c000066400000000000000000000030061414523752600206030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" #include "fmpq_vec.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("lll_original...."); fflush(stdout); /* 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); abort(); } fmpz_mat_clear(A); fmpq_clear(delta); fmpq_clear(eta); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_mat/test/t-lll_storjohann.c000066400000000000000000000030121414523752600211610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_mat.h" #include "fmpq.h" #include "fmpq_mat.h" #include "fmpq_vec.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("lll_storjohann...."); fflush(stdout); /* 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); abort(); } fmpz_mat_clear(A); fmpq_clear(delta); fmpq_clear(eta); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_mat/test/t-max_bits.c000066400000000000000000000023471414523752600177510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { slong m, n, rep, res1, res2; FLINT_TEST_INIT(state); flint_printf("max_bits...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-minpoly.c000066400000000000000000000075161414523752600176350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep, i, j; FLINT_TEST_INIT(state); flint_printf("minpoly...."); fflush(stdout); 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"); 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"); abort(); } fmpz_clear(c); fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_poly_clear(f); fmpz_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-mul.c000066400000000000000000000125241414523752600167360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, B, C, D; slong i; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); 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_inline(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"); flint_abort(); } if (bits <= FLINT_BITS - 2) { _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"); flint_abort(); } } if (abits <= FLINT_BITS - 2 && bbits <= FLINT_BITS - 2 && 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"); flint_abort(); } } if (abits <= FLINT_BITS - 2 && bbits <= FLINT_BITS - 2) { _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"); 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"); flint_abort(); } } if (n == k) { fmpz_mat_mul(A, A, B); if (!fmpz_mat_equal(A, C)) { flint_printf("FAIL: aliasing failed\n"); 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"); flint_abort(); } fmpz_mat_window_clear(A_window); fmpz_mat_clear(A); fmpz_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-mul_blas.c000066400000000000000000000067151414523752600177440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong i; slong max_num_threads = 5; FLINT_TEST_INIT(state); flint_printf("mul_blas...."); fflush(stdout); 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_inline(C, A, B); if (fmpz_mat_mul_blas(D, A, B)) { if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); flint_abort(); } } #if FLINT_USES_BLAS && FLINT_BITS == 64 else { flint_printf("FAIL: blas should have worked\n"); 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_inline(C, A, B); if (fmpz_mat_mul_blas(D, A, B)) { if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); flint_abort(); } } #if FLINT_USES_BLAS && FLINT_BITS == 64 else { flint_printf("FAIL: blas should have worked\n"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-mul_classical.c000066400000000000000000000032201414523752600207450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, B, C, D; slong i; FLINT_TEST_INIT(state); flint_printf("mul_classical...."); fflush(stdout); for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong m, n, k; 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); fmpz_mat_mul_classical_inline(D, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-mul_double_word.c000066400000000000000000000061271414523752600213250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.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); } } } int main(void) { fmpz_mat_t A, B, C, D; slong i; FLINT_TEST_INIT(state); flint_printf("mul_double_word...."); fflush(stdout); 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_inline(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"); flint_abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-mul_fmpz_vec.c000066400000000000000000000052151414523752600206260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mul_fmpz_vec...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-mul_multi_mod.c000066400000000000000000000050161414523752600210050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, B, C, D; slong i; FLINT_TEST_INIT(state); flint_printf("mul_multi_mod...."); fflush(stdout); for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong m, n, k; 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_inline(C, A, B); fmpz_mat_mul_multi_mod(D, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); 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); fmpz_mat_mul_classical_inline(C, A, B); fmpz_mat_mul_multi_mod(D, A, B); if (!fmpz_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-mul_small.c000066400000000000000000000043071414523752600201260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, B, C, D; slong i; slong max_threads = 6; FLINT_TEST_INIT(state); flint_printf("mul_small...."); fflush(stdout); 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, FLINT_BITS - 2) + 1); fmpz_mat_randtest(B, state, n_randint(state, FLINT_BITS - 2) + 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_inline(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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-mul_strassen.c000066400000000000000000000032311414523752600206530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz_mat.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mul_strassen...."); fflush(stdout); for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_mat_t A, B, C, D; slong m, k, n; m = n_randint(state, 150); k = n_randint(state, 150); n = n_randint(state, 150); 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); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-multi_CRT_ui.c000066400000000000000000000050411414523752600204740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("multi_CRT_ui...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-multi_CRT_ui_unsigned.c000066400000000000000000000050241414523752600223710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("multi_CRT_ui_unsigned...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-nullspace.c000066400000000000000000000077501414523752600201340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, B, ker; slong i, m, n, b, d, r, nullity, nulrank; FLINT_TEST_INIT(state); flint_printf("nullspace...."); fflush(stdout); /* 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"); abort(); } if (nullity + r != n) { flint_printf("FAIL:\n"); flint_printf("nullity + rank != n\n"); fmpz_mat_print_pretty(A); flint_printf("\n"); 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"); 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"); abort(); } if (nullity + r != n) { flint_printf("FAIL:\n"); flint_printf("nullity + rank != n\n"); fmpz_mat_print_pretty(A); flint_printf("\n"); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(ker); fmpz_mat_clear(B); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-one.c000066400000000000000000000024751414523752600167260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, i, j, rep; FLINT_TEST_INIT(state); flint_printf("one...."); fflush(stdout); 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"); abort(); } } } fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-pow.c000066400000000000000000000033751414523752600167520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("pow...."); fflush(stdout); 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"); abort(); } fmpz_mat_pow(A, A, e); if (!fmpz_mat_equal(A, B)) { flint_printf("FAIL: aliasing failed\n"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-print_read.c000066400000000000000000000142351414523752600202710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ #undef __STRICT_ANSI__ #endif #include #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) #include #endif #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) int main(void) { int i, j, m, n, k = 1000, result; FILE *in, *out; int fd[2]; pid_t childpid; FLINT_TEST_INIT(state); flint_printf("print/ read...."); fflush(stdout); /* 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"); abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_mat_clear(t); } fclose(in); } if (i != k) { flint_printf("FAIL:\n"); flint_printf("Only %d out of %d objects were processed.\n", i, n); 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"); abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); 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"); abort(); } r = flint_fprintf(out, "blah"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); 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"); 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); abort(); } ++i; } fmpz_mat_clear(t); fclose(in); } /* 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); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #else int main(void) { flint_printf("print/ read...."); fflush(stdout); flint_printf("SKIPPED\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fmpz_mat/test/t-rank.c000066400000000000000000000040621414523752600170720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A; slong i, m, n, b, d, r; FLINT_TEST_INIT(state); flint_printf("rank...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_mat_clear(A); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-rref.c000066400000000000000000000074021414523752600170760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "perm.h" #include "ulong_extras.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("rref...."); fflush(stdout); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-rref_fflu.c000066400000000000000000000074111414523752600201120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "perm.h" #include "ulong_extras.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("rref_fflu...."); fflush(stdout); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-rref_mod.c000066400000000000000000000072521414523752600177400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" static void check_rref(fmpz_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"); abort(); } if (j <= prev_pivot) { flint_printf("pivot not strictly to the right of previous\n"); abort(); } prev_pivot = j; break; } prev_row_zero = (j + 1 == A->c); } } } int main(void) { fmpz_mat_t A; fmpz_t p; slong i, j, k, m, n, b, d, r, rank; slong *perm; FLINT_TEST_INIT(state); flint_printf("rref_mod...."); fflush(stdout); /* Maximally sparse matrices of given rank */ for (i = 0; i < 10000; i++) { m = n_randint(state, 10); n = n_randint(state, 10); perm = flint_malloc(FLINT_MAX(1, m) * sizeof(slong)); fmpz_init_set_ui(p, n_randtest_prime(state, 0)); for (r = 0; r <= FLINT_MIN(m, n); r++) { b = 1 + n_randint(state, 10) * n_randint(state, 10); fmpz_mat_init(A, m, n); fmpz_mat_randrank(A, state, r, b); for (j = 0; j < m; j++) for (k = 0; k < n; k++) fmpz_mod(fmpz_mat_entry(A, j, k), fmpz_mat_entry(A, j, k), p); rank = fmpz_mat_rref_mod(perm, A, p); if (r < rank) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); abort(); } check_rref(A); fmpz_mat_clear(A); } fmpz_clear(p); flint_free(perm); } /* Dense */ for (i = 0; i < 10000; i++) { m = n_randint(state, 10); n = n_randint(state, 10); perm = flint_malloc(FLINT_MAX(1, m) * sizeof(slong)); fmpz_init_set_ui(p, n_randtest_prime(state, 0)); 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); for (j = 0; j < m; j++) for (k = 0; k < n; k++) fmpz_mod(fmpz_mat_entry(A, j, k), fmpz_mat_entry(A, j, k), p); rank = fmpz_mat_rref_mod(perm, A, p); if (r < rank) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); abort(); } check_rref(A); fmpz_mat_clear(A); } fmpz_clear(p); flint_free(perm); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-rref_mul.c000066400000000000000000000117011414523752600177500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "perm.h" #include "ulong_extras.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("rref_mul...."); fflush(stdout); 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-scalar_addmul_fmpz.c000066400000000000000000000031021414523752600217600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("scalar_add/submul_fmpz...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-scalar_addmul_nmod_mat_fmpz.c000066400000000000000000000034261414523752600236470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("scalar_add/submul_nmod_mat_fmpz...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); nmod_mat_clear(M); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-scalar_addmul_nmod_mat_ui.c000066400000000000000000000033341414523752600233060ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("scalar_add/submul_nmod_mat_ui...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); nmod_mat_clear(M); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-scalar_addmul_si.c000066400000000000000000000030101414523752600214150ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("scalar_add/submul_si...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-scalar_addmul_ui.c000066400000000000000000000030101414523752600214170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("scalar_add/submul_ui...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-scalar_mod_fmpz.c000066400000000000000000000030111414523752600212700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("scalar_mod_fmpz...."); fflush(stdout); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(Amod); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-scalar_mul_2exp.c000066400000000000000000000044351414523752600212230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("scalar_mul/tdiv_q_2exp...."); fflush(stdout); 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"); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-scalar_mul_fmpz.c000066400000000000000000000033541414523752600213200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("scalar_mul/divexact_fmpz...."); fflush(stdout); 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"); abort(); } } else { fmpz_mat_scalar_divexact_fmpz(C, B, c); if (!fmpz_mat_equal(C, A)) { flint_printf("FAIL!\n"); abort(); } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-scalar_mul_si.c000066400000000000000000000032501414523752600207520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("scalar_mul/divexact_si...."); fflush(stdout); 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"); abort(); } } else { fmpz_mat_scalar_divexact_si(C, B, c); if (!fmpz_mat_equal(C, A)) { flint_printf("FAIL!\n"); abort(); } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-scalar_mul_ui.c000066400000000000000000000032171414523752600207570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("scalar_mul/divexact_ui...."); fflush(stdout); 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"); abort(); } } else { fmpz_mat_scalar_divexact_ui(C, B, c); if (!fmpz_mat_equal(C, A)) { flint_printf("FAIL!\n"); abort(); } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-scalar_smod.c000066400000000000000000000037501414523752600204310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("scalar_smod...."); fflush(stdout); 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"); abort(); } } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_clear(P); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-snf_diagonal.c000066400000000000000000000040041414523752600205570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("snf_diagonal...."); fflush(stdout); 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"); 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"); abort(); } fmpz_mat_clear(S2); fmpz_mat_clear(S); fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-snf_iliopoulos.c000066400000000000000000000051771414523752600212130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("snf_iliopoulos...."); fflush(stdout); 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"); 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"); 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"); abort(); } fmpz_mat_clear(S2); fmpz_mat_clear(S); fmpz_mat_clear(A); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-snf_kannan_bachem.c000066400000000000000000000042121414523752600215470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("snf_kannan_bachem...."); fflush(stdout); 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"); 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"); abort(); } fmpz_mat_clear(S2); fmpz_mat_clear(S); fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-solve.c000066400000000000000000000063431414523752600172730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, r; int success; FLINT_TEST_INIT(state); flint_printf("solve...."); fflush(stdout); 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"); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-solve_bound.c000066400000000000000000000054541414523752600204640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("solve_bound...."); fflush(stdout); 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"); 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"); abort(); } } } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_clear(den); fmpz_clear(N); fmpz_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-solve_cramer.c000066400000000000000000000063661414523752600206310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, r; int success; FLINT_TEST_INIT(state); flint_printf("solve_cramer...."); fflush(stdout); 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"); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-solve_dixon.c000066400000000000000000000065241414523752600204750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, X, B, AX, AXm, Bm; fmpz_t mod; slong i, m, n, r; int success; FLINT_TEST_INIT(state); flint_printf("solve_dixon...."); fflush(stdout); 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"); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-solve_dixon_den.c000066400000000000000000000063771414523752600213310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, r; int success; FLINT_TEST_INIT(state); flint_printf("solve_dixon_den...."); fflush(stdout); 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"); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-solve_multi_mod_den.c000066400000000000000000000064131414523752600221700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mat_t A, X, B, AX; fmpz_t den; slong i, m, n, r; int success; FLINT_TEST_INIT(state); flint_printf("solve_multi_mod_den...."); fflush(stdout); 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"); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(X); fmpz_mat_clear(AX); fmpz_clear(den); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-sqr.c000066400000000000000000000032151414523752600167430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("sqr...."); fflush(stdout); 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"); abort(); } fmpz_mat_sqr(A, A); if (!fmpz_mat_equal(A, B)) { flint_printf("FAIL: aliasing failed\n"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-trace.c000066400000000000000000000041101414523752600172270ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("trace...."); fflush(stdout); /* 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); fmpz_mat_clear(AB); fmpz_mat_clear(BA); fmpz_clear(trab); fmpz_clear(trba); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-transpose.c000066400000000000000000000036611414523752600201610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep; FLINT_TEST_INIT(state); flint_printf("transpose...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_mat_clear(A); fmpz_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-window_init_clear.c000066400000000000000000000030601414523752600216340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("window_init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/test/t-zero.c000066400000000000000000000024641414523752600171220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, i, j, rep; FLINT_TEST_INIT(state); flint_printf("zero...."); fflush(stdout); 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"); abort(); } } } fmpz_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mat/trace.c000066400000000000000000000013151414523752600160130ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } } flint2-2.8.4/fmpz_mat/transpose.c000066400000000000000000000021711414523752600167340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_mat_transpose). Incompatible dimensions.\n"); flint_abort(); } 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]); } } flint2-2.8.4/fmpz_mat/window_clear.c000066400000000000000000000007771414523752600174050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" void fmpz_mat_window_clear(fmpz_mat_t window) { if (window->r != 0) flint_free(window->rows); } flint2-2.8.4/fmpz_mat/window_init.c000066400000000000000000000017161414523752600172540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mat/zero.c000066400000000000000000000011011414523752600156650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_matxx.h000066400000000000000000000455521414523752600153150ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MATXX_H #define FMPZ_MATXX_H FMPZ_MATXX_H #include "fmpz_mat.h" #include "fmpq_mat.h" // fmpq_mat_get_fmpz_mat_mod_fmpz #include "fmpzxx.h" #include "fmpz_polyxx.h" #include "permxx.h" #include "flintxx/ltuple.h" #include "flintxx/matrix.h" #include "flintxx/traits_fwd.h" // TODO input and output // TODO addmul // TODO nullspace member namespace flint { FLINT_DEFINE_BINOP(det_modular) FLINT_DEFINE_BINOP(det_modular_accelerated) FLINT_DEFINE_BINOP(mul_multi_mod) FLINT_DEFINE_BINOP(solve_dixon) FLINT_DEFINE_BINOP(solve_cramer) FLINT_DEFINE_BINOP(solve_bound) FLINT_DEFINE_THREEARY(det_modular_given_divisor) FLINT_DEFINE_UNOP(det_bareiss) FLINT_DEFINE_UNOP(det_bound) FLINT_DEFINE_UNOP(det_cofactor) FLINT_DEFINE_UNOP(det_divisor) namespace detail { template struct fmpz_matxx_traits : matrices::generic_traits { }; } // detail template class fmpz_matxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef detail::fmpz_matxx_traits traits_t; FLINTXX_DEFINE_BASICS(fmpz_matxx_expression) FLINTXX_DEFINE_CTORS(fmpz_matxx_expression) FLINTXX_DEFINE_C_REF(fmpz_matxx_expression, fmpz_mat_struct, _mat) template static evaluated_t create_temporary_rowscols( const Expr&, slong rows, slong cols) { return evaluated_t(rows, cols); } FLINTXX_DEFINE_MATRIX_METHODS(traits_t) template static fmpz_matxx_expression lift(const Nmod_mat& mat, typename mp::enable_if >::type* = 0) { fmpz_matxx_expression res(mat.rows(), mat.cols()); fmpz_mat_set_nmod_mat(res._mat(), mat.evaluate()._mat()); return res; } template static fmpz_matxx_expression lift_unsigned(const Nmod_mat& mat, typename mp::enable_if >::type* = 0) { fmpz_matxx_expression res(mat.rows(), mat.cols()); fmpz_mat_set_nmod_mat_unsigned(res._mat(), mat.evaluate()._mat()); return res; } template static fmpz_matxx_expression reduce(const Fmpq_mat& mat, const Fmpz& mod, typename mp::enable_if >::type* = 0, typename mp::enable_if >::type* = 0) { fmpz_matxx_expression res(mat.rows(), mat.cols()); fmpq_mat_get_fmpz_mat_mod_fmpz(res._mat(), mat.evaluate()._mat(), mod.evaluate()._fmpz()); return res; } template static fmpz_matxx_expression from_integral_fraction(const Fmpq_mat& mat, typename mp::enable_if >::type* = 0) { fmpz_matxx_expression res(mat.rows(), mat.cols()); res.set_integral_fraction(mat); return res; } template void set_integral_fraction(const Fmpq_mat& mat, typename mp::enable_if >::type* = 0) { execution_check(fmpq_mat_get_fmpz_mat(_mat(), mat.evaluate()._mat()), "set_integral_fraction", "fmpq_matxx"); } static fmpz_matxx_expression randbits(slong rows, slong cols, frandxx& state, flint_bitcnt_t bits) { fmpz_matxx_expression res(rows, cols); res.set_randbits(state, bits); return res; } static fmpz_matxx_expression randtest(slong rows, slong cols, frandxx& state, flint_bitcnt_t bits) { fmpz_matxx_expression res(rows, cols); res.set_randtest(state, bits); return res; } static fmpz_matxx_expression randintrel(slong rows, slong cols, frandxx& state, flint_bitcnt_t bits) { fmpz_matxx_expression res(rows, cols); res.set_randintrel(state, bits); return res; } static fmpz_matxx_expression randsimdioph(slong rows, slong cols, frandxx& state, flint_bitcnt_t bits, flint_bitcnt_t bits2) { fmpz_matxx_expression res(rows, cols); res.set_randsimdioph(state, bits, bits2); return res; } static fmpz_matxx_expression randntrulike(slong rows, slong cols, frandxx& state, flint_bitcnt_t bits, ulong q) { fmpz_matxx_expression res(rows, cols); res.set_randntrulike(state, bits, q); return res; } static fmpz_matxx_expression randntrulike2(slong rows, slong cols, frandxx& state, flint_bitcnt_t bits, ulong q) { fmpz_matxx_expression res(rows, cols); res.set_randntrulike2(state, bits, q); return res; } static fmpz_matxx_expression randajtai(slong rows, slong cols, frandxx& state, flint_bitcnt_t bits, double alpha) { fmpz_matxx_expression res(rows, cols); res.set_randajtai(state, bits, alpha); return res; } static fmpz_matxx_expression randrank(slong rows, slong cols, frandxx& state, slong rank, flint_bitcnt_t bits) { fmpz_matxx_expression res(rows, cols); res.set_randrank(state, rank, bits); return res; } template static typename mp::enable_if, fmpz_matxx_expression>::type randdet(slong rows, slong cols, frandxx& state, const Fmpz& d) { fmpz_matxx_expression res(rows, cols); res.set_randdet(state, d); return res; } static fmpz_matxx_expression zero(slong rows, slong cols) {return fmpz_matxx_expression(rows, cols);} static fmpz_matxx_expression one(slong rows, slong cols) { fmpz_matxx_expression res(rows, cols); res.set_one(); return res; } // these only make sense with targets void set_randbits(frandxx& state, flint_bitcnt_t bits) {fmpz_mat_randbits(_mat(), state._data(), bits);} void set_randtest(frandxx& state, flint_bitcnt_t bits) {fmpz_mat_randtest(_mat(), state._data(), bits);} void set_randintrel(frandxx& state, flint_bitcnt_t bits) {fmpz_mat_randintrel(_mat(), state._data(), bits);} void set_randsimdioph(frandxx& state, flint_bitcnt_t bits, flint_bitcnt_t bits2) {fmpz_mat_randsimdioph(_mat(), state._data(), bits, bits2);} void set_randntrulike(frandxx& state, flint_bitcnt_t bits, ulong q) {fmpz_mat_randntrulike(_mat(), state._data(), bits, q);} void set_randntrulike2(frandxx& state, flint_bitcnt_t bits, ulong q) {fmpz_mat_randntrulike2(_mat(), state._data(), bits, q);} void set_randajtai(frandxx& state, flint_bitcnt_t bits, double alpha) {fmpz_mat_randajtai(_mat(), state._data(), bits, alpha);} void set_randrank(frandxx& state, slong rank, flint_bitcnt_t bits) {fmpz_mat_randrank(_mat(), state._data(), rank, bits);} template typename mp::enable_if >::type set_randdet(frandxx& state, const Fmpz& d) {fmpz_mat_randdet(_mat(), state._data(), d.evaluate()._fmpz());} template int set_randpermdiag(frandxx& state, const Vec& v) { return fmpz_mat_randpermdiag(_mat(), state._data(), v._array(), v.size()); } void apply_randops(frandxx& state, slong count) {fmpz_mat_randops(_mat(), state._data(), count);} void set_zero() {fmpz_mat_zero(_mat());} void set_one() {fmpz_mat_one(_mat());} template slong set_rref_mod(const Fmpz& p, permxx* perm = 0, typename mp::enable_if >::type* = 0) { return fmpz_mat_rref_mod(maybe_perm_data(perm), _mat(), p.evaluate()._fmpz()); } // these cause evaluation slong rank() const {return fmpz_mat_rank(this->evaluate()._mat());} bool is_zero() const {return fmpz_mat_is_zero(this->evaluate()._mat());} bool is_empty() const {return fmpz_mat_is_empty(this->evaluate()._mat());} bool is_square() const {return fmpz_mat_is_square(this->evaluate()._mat());} slong find_pivot_any(slong start, slong end, slong c) const {return fmpz_mat_find_pivot_any(this->evaluate()._mat(), start, end, c);} // forwarded lazy ops FLINTXX_DEFINE_MEMBER_BINOP(det_modular) FLINTXX_DEFINE_MEMBER_BINOP(det_modular_accelerated) FLINTXX_DEFINE_MEMBER_BINOP(divexact) FLINTXX_DEFINE_MEMBER_BINOP(mul_classical) FLINTXX_DEFINE_MEMBER_BINOP(mul_multi_mod) FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_BINOP(solve) FLINTXX_DEFINE_MEMBER_BINOP(solve_bound) FLINTXX_DEFINE_MEMBER_BINOP(solve_cramer) FLINTXX_DEFINE_MEMBER_BINOP(solve_dixon) FLINTXX_DEFINE_MEMBER_BINOP(solve_fflu) FLINTXX_DEFINE_MEMBER_3OP(det_modular_given_divisor) FLINTXX_DEFINE_MEMBER_UNOP(sqr) FLINTXX_DEFINE_MEMBER_UNOP(transpose) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, charpoly) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, det) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, det_bareiss) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, det_bound) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, det_cofactor) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, det_divisor) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, trace) //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(nullspace) // TODO //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(???, inv) // TODO //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(???, rref) // TODO FLINTXX_DEFINE_MEMBER_4OP(CRT) FLINTXX_DEFINE_MEMBER_FFLU }; namespace detail { struct fmpz_mat_data; } // detail typedef fmpz_matxx_expression fmpz_matxx; typedef fmpz_matxx_expression > fmpz_matxx_ref; typedef fmpz_matxx_expression > fmpz_matxx_srcref; template<> struct matrix_traits { template static slong rows(const M& m) { return fmpz_mat_nrows(m._mat()); } template static slong cols(const M& m) { return fmpz_mat_ncols(m._mat()); } template static fmpzxx_srcref at(const M& m, slong i, slong j) { return fmpzxx_srcref::make(fmpz_mat_entry(m._mat(), i, j)); } template static fmpzxx_ref at(M& m, slong i, slong j) { return fmpzxx_ref::make(fmpz_mat_entry(m._mat(), i, j)); } }; namespace detail { template<> struct fmpz_matxx_traits : matrices::generic_traits_srcref { }; template<> struct fmpz_matxx_traits : matrices::generic_traits_ref { }; template<> struct fmpz_matxx_traits : matrices::generic_traits_nonref { }; struct fmpz_mat_data { typedef fmpz_mat_t& data_ref_t; typedef const fmpz_mat_t& data_srcref_t; fmpz_mat_t inner; fmpz_mat_data(slong m, slong n) { fmpz_mat_init(inner, m, n); } fmpz_mat_data(const fmpz_mat_data& o) { fmpz_mat_init_set(inner, o.inner); } fmpz_mat_data(fmpz_matxx_srcref o) { fmpz_mat_init_set(inner, o._data().inner); } ~fmpz_mat_data() {fmpz_mat_clear(inner);} }; } // detail #define FMPZ_MATXX_COND_S FLINTXX_COND_S(fmpz_matxx) #define FMPZ_MATXX_COND_T FLINTXX_COND_T(fmpz_matxx) namespace traits { template struct is_fmpz_matxx : flint_classes::is_Base { }; } // traits namespace mp { template struct all_fmpz_matxx : mp::and_, all_fmpz_matxx > { }; template struct all_fmpz_matxx : traits::is_fmpz_matxx { }; template struct enable_all_fmpz_matxx : mp::enable_if, Out> { }; } // mp namespace matrices { template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; } // matrices // temporary instantiation stuff FLINTXX_DEFINE_TEMPORARY_RULES(fmpz_matxx) namespace rules { FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_MATXX_COND_T, FMPZ_MATXX_COND_S, fmpz_mat_set(to._mat(), from._mat())) FLINTXX_DEFINE_SWAP(fmpz_matxx, fmpz_mat_swap(e1._mat(), e2._mat())) FLINTXX_DEFINE_EQUALS(fmpz_matxx, fmpz_mat_equal(e1._mat(), e2._mat())) FLINT_DEFINE_PRINT_COND(FMPZ_MATXX_COND_S, fmpz_mat_fprint(to, from._mat())) FLINT_DEFINE_READ_COND(FMPZ_MATXX_COND_T, fmpz_mat_fread(from, to._mat())) FLINT_DEFINE_PRINT_PRETTY_COND(FMPZ_MATXX_COND_S, fmpz_mat_fprint_pretty(to, from._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpz_matxx, FMPZ_MATXX_COND_S, FMPZ_MATXX_COND_S, fmpz_mat_mul(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_matxx, FMPZ_MATXX_COND_S, FMPZXX_COND_S, fmpz_mat_scalar_mul_fmpz(to._mat(), e1._mat(), e2._fmpz())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_matxx, FMPZ_MATXX_COND_S, traits::is_unsigned_integer, fmpz_mat_scalar_mul_ui(to._mat(), e1._mat(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_matxx, FMPZ_MATXX_COND_S, traits::is_signed_integer, fmpz_mat_scalar_mul_si(to._mat(), e1._mat(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(divexact_op, fmpz_matxx, FMPZ_MATXX_COND_S, FMPZXX_COND_S, fmpz_mat_scalar_divexact_fmpz(to._mat(), e1._mat(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(divexact_op, fmpz_matxx, FMPZ_MATXX_COND_S, traits::is_unsigned_integer, fmpz_mat_scalar_divexact_ui(to._mat(), e1._mat(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(divexact_op, fmpz_matxx, FMPZ_MATXX_COND_S, traits::is_signed_integer, fmpz_mat_scalar_divexact_si(to._mat(), e1._mat(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpz_matxx, FMPZ_MATXX_COND_S, FMPZ_MATXX_COND_S, fmpz_mat_add(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpz_matxx, FMPZ_MATXX_COND_S, FMPZ_MATXX_COND_S, fmpz_mat_sub(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpz_matxx, FMPZ_MATXX_COND_S, fmpz_mat_neg(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(transpose_op, fmpz_matxx, FMPZ_MATXX_COND_S, fmpz_mat_transpose(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(trace_op, fmpzxx, FMPZ_MATXX_COND_S, fmpz_mat_trace(to._fmpz(), from._mat())) #define FMPZ_MATXX_DEFINE_DET(name) \ FLINT_DEFINE_UNARY_EXPR_COND(name##_op, fmpzxx, FMPZ_MATXX_COND_S, \ fmpz_mat_##name(to._fmpz(), from._mat())) FMPZ_MATXX_DEFINE_DET(det) FMPZ_MATXX_DEFINE_DET(det_cofactor) FMPZ_MATXX_DEFINE_DET(det_bareiss) FMPZ_MATXX_DEFINE_DET(det_divisor) FMPZ_MATXX_DEFINE_DET(det_bound) FLINT_DEFINE_BINARY_EXPR_COND2(det_modular_op, fmpzxx, FMPZ_MATXX_COND_S, tools::is_bool, fmpz_mat_det_modular(to._fmpz(), e1._mat(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(det_modular_accelerated_op, fmpzxx, FMPZ_MATXX_COND_S, tools::is_bool, fmpz_mat_det_modular_accelerated(to._fmpz(), e1._mat(), e2)) FLINT_DEFINE_THREEARY_EXPR_COND3(det_modular_given_divisor_op, fmpzxx, FMPZ_MATXX_COND_S, FMPZXX_COND_S, tools::is_bool, fmpz_mat_det_modular_given_divisor(to._fmpz(), e1._mat(), e2._fmpz(), e3)) FLINT_DEFINE_THREEARY_EXPR_COND3(mat_at_op, fmpzxx, FMPZ_MATXX_COND_S, traits::fits_into_slong, traits::fits_into_slong, fmpz_set(to._fmpz(), fmpz_mat_entry(e1._mat(), e2, e3))) FLINT_DEFINE_BINARY_EXPR_COND2(mul_classical_op, fmpz_matxx, FMPZ_MATXX_COND_S, FMPZ_MATXX_COND_S, fmpz_mat_mul_classical(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(mul_multi_mod_op, fmpz_matxx, FMPZ_MATXX_COND_S, FMPZ_MATXX_COND_S, fmpz_mat_mul_multi_mod(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_op, fmpz_matxx, FMPZ_MATXX_COND_S, fmpz_mat_sqr(to._mat(), from._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpz_matxx, FMPZ_MATXX_COND_S, traits::is_unsigned_integer, fmpz_mat_pow(to._mat(), e1._mat(), e2)) namespace rdetail { typedef make_ltuple::type >::type fmpz_mat_inv_rt; typedef make_ltuple::type >::type fmpz_solve_bound_rt; typedef make_ltuple::type >::type fmpz_mat_nullspace_rt; } // rdetail FLINT_DEFINE_UNARY_EXPR_COND(inv_op, rdetail::fmpz_mat_inv_rt, FMPZ_MATXX_COND_S, to.template get<0>() = fmpz_mat_inv(to.template get<1>()._mat(), to.template get<2>()._fmpz(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(charpoly_op, fmpz_polyxx, FMPZ_MATXX_COND_S, fmpz_mat_charpoly(to._poly(), from._mat())) #define FMPZ_MATXX_DEFINE_SOLVE(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, rdetail::fmpz_mat_inv_rt, \ FMPZ_MATXX_COND_S, FMPZ_MATXX_COND_S, \ to.template get<0>() = fmpz_mat_##name(to.template get<1>()._mat(), \ to.template get<2>()._fmpz(), e1._mat(), e2._mat())) FMPZ_MATXX_DEFINE_SOLVE(solve) FMPZ_MATXX_DEFINE_SOLVE(solve_dixon) FMPZ_MATXX_DEFINE_SOLVE(solve_cramer) FMPZ_MATXX_DEFINE_SOLVE(solve_fflu) FLINT_DEFINE_BINARY_EXPR_COND2(solve_bound_op, rdetail::fmpz_solve_bound_rt, FMPZ_MATXX_COND_S, FMPZ_MATXX_COND_S, fmpz_mat_solve_bound(to.template get<0>()._fmpz(), to.template get<1>()._fmpz(), e1._mat(), e2._mat())) FLINT_DEFINE_UNARY_EXPR_COND(nullspace_op, rdetail::fmpz_mat_nullspace_rt, FMPZ_MATXX_COND_S, to.template get<0>() = fmpz_mat_nullspace( to.template get<1>()._mat(), from._mat())) namespace rdetail { typedef make_ltuple::type>::type fmpz_matxx_fflu_rt; } // rdetail FLINT_DEFINE_THREEARY_EXPR_COND3(fflu_op, rdetail::fmpz_matxx_fflu_rt, FMPZ_MATXX_COND_S, traits::is_maybe_perm, tools::is_bool, to.template get<0>() = fmpz_mat_fflu(to.template get<1>()._mat(), to.template get<2>()._fmpz(), maybe_perm_data(e2), e1._mat(), e3)) FLINT_DEFINE_UNARY_EXPR_COND(rref_op, rdetail::fmpz_matxx_fflu_rt, FMPZ_MATXX_COND_S, to.template get<0>() = fmpz_mat_rref(to.template get<1>()._mat(), to.template get<2>()._fmpz(), from._mat())) } // rules } // flint #include "nmod_matxx.h" // modular reconstruction code #endif flint2-2.8.4/fmpz_mod.h000066400000000000000000000250401414523752600147210ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPZ_MOD_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.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. */ 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_mod_ctx_struct; typedef fmpz_mod_ctx_struct fmpz_mod_ctx_t[1]; FLINT_DLL void fmpz_mod_ctx_init(fmpz_mod_ctx_t ctx, const fmpz_t n); FLINT_DLL void fmpz_mod_ctx_init_ui(fmpz_mod_ctx_t ctx, ulong n); FLINT_DLL 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; } FMPZ_MOD_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; } } FLINT_DLL void fmpz_mod_ctx_set_modulus(fmpz_mod_ctx_t ctx, const fmpz_t n); FLINT_DLL void fmpz_mod_ctx_set_modulus_ui(fmpz_mod_ctx_t ctx, ulong n); FLINT_DLL int fmpz_mod_is_canonical(const fmpz_t a, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_assert_canonical(const fmpz_t a, const fmpz_mod_ctx_t ctx); FMPZ_MOD_INLINE 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_DLL int fmpz_mod_equal_fmpz(const fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_equal_si(const fmpz_t a, slong b, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_set_fmpz(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_set_ui(fmpz_t a, ulong b, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_set_si(fmpz_t a, slong b, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_add1(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_add2s(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_add2(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL void fmpz_mod_add_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_add_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_add_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_sub1(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_sub2s(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_sub2(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL void fmpz_mod_sub_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_sub_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_sub_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_fmpz_sub(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_ui_sub(fmpz_t a, ulong b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_si_sub(fmpz_t a, slong b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_neg(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_mul1(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_mul2s(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_mul2(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL 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); FLINT_DLL void fmpz_mod_mul_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_mul_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_mul_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_is_invertible(const fmpz_t a, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_inv(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_divides(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_pow_ui(fmpz_t a, const fmpz_t b, ulong pow, const fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_pow_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t pow, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_rand(fmpz_t a, flint_rand_t state, const fmpz_mod_ctx_t ctx); FLINT_DLL 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]; FLINT_DLL void fmpz_mod_discrete_log_pohlig_hellman_init( fmpz_mod_discrete_log_pohlig_hellman_t L); FLINT_DLL void fmpz_mod_discrete_log_pohlig_hellman_clear( fmpz_mod_discrete_log_pohlig_hellman_t L); FLINT_DLL double fmpz_mod_discrete_log_pohlig_hellman_precompute_prime( fmpz_mod_discrete_log_pohlig_hellman_t L, const fmpz_t p); FLINT_DLL 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; } FLINT_DLL int fmpz_next_smooth_prime(fmpz_t a, const fmpz_t b); #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpz_mod/000077500000000000000000000000001414523752600145475ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod/add.c000066400000000000000000000044321414523752600154460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpz_mod/add_fmpz.c000066400000000000000000000024171414523752600165030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" 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)); } flint2-2.8.4/fmpz_mod/addmul.c000066400000000000000000000012241414523752600161600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); fmpz_mod(a, t, ctx->n); fmpz_clear(t); } flint2-2.8.4/fmpz_mod/ctx_clear.c000066400000000000000000000007351414523752600166640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" void fmpz_mod_ctx_clear(fmpz_mod_ctx_t ctx) { fmpz_clear(ctx->n); } flint2-2.8.4/fmpz_mod/ctx_init.c000066400000000000000000000037041414523752600165400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; 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; } } } flint2-2.8.4/fmpz_mod/ctx_init_ui.c000066400000000000000000000010601414523752600172260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" 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_); } flint2-2.8.4/fmpz_mod/discrete_log_pohlig_hellman.c000066400000000000000000000266551414523752600224360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" #include /* 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; } flint2-2.8.4/fmpz_mod/divides.c000066400000000000000000000024431414523752600163450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod/equal_fmpz.c000066400000000000000000000016651414523752600170660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod/inlines.c000066400000000000000000000011051414523752600163510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_MOD_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "fmpz_mod.h" flint2-2.8.4/fmpz_mod/inv.c000066400000000000000000000015611414523752600155120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpz_mod/is_canonical.c000066400000000000000000000013011414523752600173300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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"); } flint2-2.8.4/fmpz_mod/is_invertible.c000066400000000000000000000011441414523752600175510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod/mul.c000066400000000000000000000114571414523752600155200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); fmpz_mod(a, a, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } flint2-2.8.4/fmpz_mod/mul_fmpz.c000066400000000000000000000024171414523752600165500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" 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); fmpz_mod(a, a, ctx->n); 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)); } flint2-2.8.4/fmpz_mod/neg.c000066400000000000000000000012321414523752600154620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpz_mod/next_smooth_prime.c000066400000000000000000000762051414523752600204700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod/pow_fmpz.c000066400000000000000000000020741414523752600165570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" 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_powm(a, b, pow, ctx->n); } else { fmpz_t d; fmpz_init(d); fmpz_gcdinv(d, a, b, ctx->n); if (fmpz_is_one(d)) { fmpz_neg(d, pow); fmpz_powm(a, a, d, ctx->n); } else { success = 0; } fmpz_clear(d); } FLINT_ASSERT(!success || fmpz_mod_is_canonical(a, ctx)); return success; } flint2-2.8.4/fmpz_mod/pow_ui.c000066400000000000000000000012511414523752600162140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" 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_powm_ui(a, b, pow, ctx->n); FLINT_ASSERT(fmpz_mod_is_canonical(a, ctx)); } flint2-2.8.4/fmpz_mod/rand.c000066400000000000000000000014471414523752600156450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod/set_fmpz.c000066400000000000000000000016121414523752600165420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" void fmpz_mod_set_fmpz(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx) { fmpz_mod(a, b, ctx->n); 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)); } flint2-2.8.4/fmpz_mod/set_modulus.c000066400000000000000000000010271414523752600172560ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_mod/set_modulus_ui.c000066400000000000000000000010261414523752600177520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" 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); } flint2-2.8.4/fmpz_mod/sub.c000066400000000000000000000042551414523752600155120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpz_mod/sub_fmpz.c000066400000000000000000000042631414523752600165450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" 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)); } flint2-2.8.4/fmpz_mod/test/000077500000000000000000000000001414523752600155265ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod/test/t-add_sub_neg.c000066400000000000000000000044551414523752600203750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("add/sub/neg...."); fflush(stdout); flint_randinit(state); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod/test/t-discrete_log_pohlig_hellman.c000066400000000000000000000107531414523752600236460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("discrete_log_pohlig_hellman...."); fflush(stdout); flint_randinit(state); /* 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod/test/t-divides.c000066400000000000000000000073151414523752600175700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" int main(void) { flint_bitcnt_t max_modulus_bits = 200; slong i, j; FLINT_TEST_INIT(state); flint_printf("divides...."); fflush(stdout); flint_randinit(state); { 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"); 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"); 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); 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); 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); flint_abort(); } } } fmpz_clear(p); fmpz_mod_ctx_clear(fpctx); fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_clear(u); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod/test/t-inv.c000066400000000000000000000036571414523752600167420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("inv...."); fflush(stdout); flint_randinit(state); 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); 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); flint_abort(); } } fmpz_mod_ctx_clear(fpctx); fmpz_clear(p); fmpz_clear(a); fmpz_clear(ainv); fmpz_clear(b); fmpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod/test/t-mul.c000066400000000000000000000076101414523752600167340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" int main(void) { flint_bitcnt_t max_bits = 200; slong i, j, k; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); flint_randinit(state); 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 { 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod/test/t-next_smooth_prime.c000066400000000000000000000020221414523752600216720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" int main(void) { slong i; fmpz_t p; int success; FLINT_TEST_INIT(state); flint_printf("next_smooth_prime...."); fflush(stdout); flint_randinit(state); 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); flint_abort(); } } fmpz_clear(p); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod/test/t-pow_fmpz.c000066400000000000000000000101451414523752600177750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" int main(void) { flint_bitcnt_t max_exp_bits = 200; flint_bitcnt_t max_modulus_bits = 200; slong i, j; FLINT_TEST_INIT(state); flint_printf("pow_fmpz...."); fflush(stdout); flint_randinit(state); 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++) { 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod/test/t-pow_ui.c000066400000000000000000000071131414523752600174370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod.h" int main(void) { flint_bitcnt_t max_modulus_bits = 200; slong i, j; FLINT_TEST_INIT(state); flint_printf("pow_ui...."); fflush(stdout); flint_randinit(state); 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++) { 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat.h000066400000000000000000000162641414523752600155720ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPZ_MOD_MAT_INLINE static __inline__ #endif #include "flint.h" #include "fmpz_mat.h" #ifdef __cplusplus extern "C" { #endif #define FMPZ_MOD_MAT_MUL_TRANSPOSE_CUTOFF 10 typedef struct { fmpz_mat_t mat; fmpz_t mod; } fmpz_mod_mat_struct; /* fmpz_mod_mat_t allows reference-like semantics for fmpz_mod_mat_struct */ typedef fmpz_mod_mat_struct fmpz_mod_mat_t[1]; /* 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->mat, i, j); } FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_set_entry(fmpz_mod_mat_t mat, slong i, slong j, const fmpz_t val) { fmpz_set(fmpz_mat_entry(mat->mat, i, j), val); } /* Memory management ********************************************************/ FLINT_DLL void fmpz_mod_mat_init(fmpz_mod_mat_t mat, slong rows, slong cols, const fmpz_t n); FLINT_DLL void fmpz_mod_mat_init_set(fmpz_mod_mat_t mat, const fmpz_mod_mat_t src); FLINT_DLL void fmpz_mod_mat_clear(fmpz_mod_mat_t mat); /* Basic manipulation ********************************************************/ FMPZ_MOD_MAT_INLINE slong fmpz_mod_mat_nrows(const fmpz_mod_mat_t mat) { return fmpz_mat_nrows(mat->mat); } FMPZ_MOD_MAT_INLINE slong fmpz_mod_mat_ncols(const fmpz_mod_mat_t mat) { return fmpz_mat_ncols(mat->mat); } FMPZ_MOD_MAT_INLINE void _fmpz_mod_mat_set_mod(fmpz_mod_mat_t mat, const fmpz_t n) { fmpz_set(mat->mod, n); } FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_one(fmpz_mod_mat_t mat) { fmpz_mat_one(mat->mat); } FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_zero(fmpz_mod_mat_t mat) { fmpz_mat_zero(mat->mat); } FMPZ_MOD_MAT_INLINE int fmpz_mod_mat_is_empty(const fmpz_mod_mat_t mat) { return fmpz_mat_is_empty(mat->mat); } FMPZ_MOD_MAT_INLINE int fmpz_mod_mat_is_square(const fmpz_mod_mat_t mat) { return fmpz_mat_is_square(mat->mat); } FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_swap(fmpz_mod_mat_t mat1, fmpz_mod_mat_t mat2) { if (mat1 != mat2) { fmpz_mod_mat_struct tmp; tmp = *mat1; *mat1 = *mat2; *mat2 = tmp; } } FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_swap_entrywise(fmpz_mod_mat_t mat1, fmpz_mod_mat_t mat2) { slong i, j; for (i = 0; i < fmpz_mod_mat_nrows(mat1); i++) for (j = 0; j < fmpz_mod_mat_ncols(mat1); j++) fmpz_swap(fmpz_mod_mat_entry(mat2, i, j), fmpz_mod_mat_entry(mat1, i, j)); } FLINT_DLL void _fmpz_mod_mat_reduce(fmpz_mod_mat_t mat); /* Random matrix generation */ FLINT_DLL void fmpz_mod_mat_randtest(fmpz_mod_mat_t mat, flint_rand_t state); /* Windows and concatenation */ FLINT_DLL 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); FLINT_DLL void fmpz_mod_mat_window_clear(fmpz_mod_mat_t window); 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) { fmpz_mat_concat_horizontal(res->mat, mat1->mat, mat2->mat); } 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) { fmpz_mat_concat_vertical(res->mat, mat1->mat, mat2->mat); } /* Input/output */ FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_print_pretty(const fmpz_mod_mat_t mat) { fmpz_mat_print_pretty(mat->mat); } /* Comparison */ FMPZ_MOD_MAT_INLINE int fmpz_mod_mat_equal(const fmpz_mod_mat_t mat1, const fmpz_mod_mat_t mat2) { return fmpz_equal(mat1->mod, mat2->mod) && fmpz_mat_equal(mat1->mat, mat2->mat); } FMPZ_MOD_MAT_INLINE int fmpz_mod_mat_is_zero(const fmpz_mod_mat_t mat) { return fmpz_mat_is_zero(mat->mat); } /* Set and transpose */ FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_set(fmpz_mod_mat_t B, const fmpz_mod_mat_t A) { fmpz_set(B->mod, A->mod); fmpz_mat_set(B->mat, A->mat); } FMPZ_MOD_MAT_INLINE void fmpz_mod_mat_transpose(fmpz_mod_mat_t B, const fmpz_mod_mat_t A) { fmpz_mat_transpose(B->mat, A->mat); } /* Conversions */ FLINT_DLL void fmpz_mod_mat_set_fmpz_mat(fmpz_mod_mat_t A, const fmpz_mat_t B); FLINT_DLL void fmpz_mod_mat_get_fmpz_mat(fmpz_mat_t A, const fmpz_mod_mat_t B); /* Addition and subtraction */ FLINT_DLL void fmpz_mod_mat_add(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B); FLINT_DLL void fmpz_mod_mat_sub(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B); FLINT_DLL void fmpz_mod_mat_neg(fmpz_mod_mat_t B, const fmpz_mod_mat_t A); /* Matrix-scalar arithmetic */ FLINT_DLL void fmpz_mod_mat_scalar_mul_si(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, slong c); FLINT_DLL void fmpz_mod_mat_scalar_mul_ui(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, ulong c); FLINT_DLL void fmpz_mod_mat_scalar_mul_fmpz(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, fmpz_t c); /* Matrix multiplication */ FLINT_DLL void fmpz_mod_mat_mul(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B); FLINT_DLL 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); FLINT_DLL void fmpz_mod_mat_mul_classical_threaded(fmpz_mod_mat_t C, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B); FLINT_DLL void fmpz_mod_mat_sqr(fmpz_mod_mat_t B, const fmpz_mod_mat_t A); FLINT_DLL void fmpz_mod_mat_mul_fmpz_vec(fmpz * c, const fmpz_mod_mat_t A, const fmpz * b, slong blen); FLINT_DLL void fmpz_mod_mat_mul_fmpz_vec_ptr(fmpz * const * c, const fmpz_mod_mat_t A, const fmpz * const * b, slong blen); FLINT_DLL void fmpz_mod_mat_fmpz_vec_mul(fmpz * c, const fmpz * a, slong alen, const fmpz_mod_mat_t B); FLINT_DLL void fmpz_mod_mat_fmpz_vec_mul_ptr(fmpz * const * c, const fmpz * const * a, slong alen, const fmpz_mod_mat_t B); /* Trace */ FLINT_DLL void fmpz_mod_mat_trace(fmpz_t trace, const fmpz_mod_mat_t mat); /* Gaussian elimination *********************************************/ FLINT_DLL slong fmpz_mod_mat_rref(slong * perm, fmpz_mod_mat_t mat); /* Howell and strong echelon form ***********************************/ FLINT_DLL slong fmpz_mod_mat_howell_form(fmpz_mod_mat_t mat); FLINT_DLL void fmpz_mod_mat_strong_echelon_form(fmpz_mod_mat_t mat); /* Inlines *******************************************************************/ FLINT_DLL void fmpz_mod_mat_get_entry(fmpz_t x, const fmpz_mod_mat_t mat, slong i, slong j); #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpz_mod_mat/000077500000000000000000000000001414523752600154105ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_mat/add.c000066400000000000000000000010711414523752600163030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { fmpz_mat_add(C->mat, A->mat, B->mat); _fmpz_mod_mat_reduce(C); } flint2-2.8.4/fmpz_mod_mat/clear.c000066400000000000000000000007761414523752600166540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_clear(fmpz_mod_mat_t mat) { fmpz_mat_clear(mat->mat); fmpz_clear(mat->mod); } flint2-2.8.4/fmpz_mod_mat/fmpz_vec_mul.c000066400000000000000000000013131414523752600202400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { slong i; fmpz_mat_fmpz_vec_mul(c, a, alen, B->mat); for (i = fmpz_mod_mat_ncols(B) - 1; i >= 0; i--) fmpz_mod(c + i, c + i, B->mod); } flint2-2.8.4/fmpz_mod_mat/fmpz_vec_mul_ptr.c000066400000000000000000000012741414523752600211330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { slong i; fmpz_mat_fmpz_vec_mul_ptr(c, a, alen, B->mat); for (i = fmpz_mod_mat_ncols(B) - 1; i >= 0; i--) fmpz_mod(c[i], c[i], B->mod); } flint2-2.8.4/fmpz_mod_mat/get_fmpz_mat.c000066400000000000000000000007751414523752600202410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_get_fmpz_mat(fmpz_mat_t A, const fmpz_mod_mat_t B) { fmpz_mat_set(A, B->mat); } flint2-2.8.4/fmpz_mod_mat/howell_form.c000066400000000000000000000010101414523752600200610ustar00rootroot00000000000000/* 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 2.1 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) { return fmpz_mat_howell_form_mod(mat->mat, mat->mod); } flint2-2.8.4/fmpz_mod_mat/init.c000066400000000000000000000011221414523752600165130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_init(fmpz_mod_mat_t mat, slong rows, slong cols, const fmpz_t n) { fmpz_mat_init(mat->mat, rows, cols); fmpz_init(mat->mod); _fmpz_mod_mat_set_mod(mat, n); } flint2-2.8.4/fmpz_mod_mat/init_set.c000066400000000000000000000010651414523752600173740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_init_set(fmpz_mod_mat_t mat, const fmpz_mod_mat_t src) { fmpz_mat_init_set(mat->mat, src->mat); fmpz_init_set(mat->mod, src->mod); } flint2-2.8.4/fmpz_mod_mat/inlines.c000066400000000000000000000014161414523752600172170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_MOD_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mod_mat.h" void fmpz_mod_mat_get_entry(fmpz_t x, const fmpz_mod_mat_t mat, slong i, slong j) { fmpz_set(x, fmpz_mod_mat_entry(mat, i, j)); } flint2-2.8.4/fmpz_mod_mat/mul.c000066400000000000000000000012041414523752600163460ustar00rootroot00000000000000/* 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 2.1 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) { /* N.B. don't call classical_threaded, instead, thread fmpz_mat_mul */ fmpz_mat_mul(C->mat, A->mat, B->mat); _fmpz_mod_mat_reduce(C); } flint2-2.8.4/fmpz_mod_mat/mul_classical_threaded.c000066400000000000000000000153401414523752600222320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_mod_mat.h" #include "fmpz_vec.h" #include "thread_support.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_mod_mat_addmul_basic_op(fmpz ** D, fmpz ** const C, fmpz ** const A, fmpz ** const B, slong m, slong k, slong n, int op, fmpz_t p) { 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(D[i] + j, c, p); } } 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; fmpz * p; #if FLINT_USES_PTHREAD pthread_mutex_t * mutex; #endif int op; } 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; fmpz * p = arg.p; int op = arg.op; 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); if (op == 1) fmpz_add(c, C[i] + j, c); else if (op == -1) fmpz_sub(c, C[i] + j, c); fmpz_mod(D[i] + j, c, p); } } } } 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, fmpz_t p, thread_pool_handle * threads, slong num_threads) { 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(p); /* 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; args[i].p = p; #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, _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) { slong m, k, n; m = A->mat->r; k = A->mat->c; n = B->mat->c; _fmpz_mod_mat_addmul_transpose_threaded_pool_op(D->mat->rows, (op == 0) ? NULL : C->mat->rows, A->mat->rows, B->mat->rows, m, k, n, op, D->mod, threads, num_threads); } 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) { thread_pool_handle * threads; slong num_threads; if (A->mat->c == 0) { if (op == 0) fmpz_mod_mat_zero(D); else fmpz_mod_mat_set(D, C); return; } if (A->mat->r < FMPZ_MOD_MAT_MUL_TRANSPOSE_CUTOFF || A->mat->c < FMPZ_MOD_MAT_MUL_TRANSPOSE_CUTOFF || B->mat->c < FMPZ_MOD_MAT_MUL_TRANSPOSE_CUTOFF) { _fmpz_mod_mat_addmul_basic_op(D->mat->rows, (op == 0) ? NULL : C->mat->rows, A->mat->rows, B->mat->rows, A->mat->r, A->mat->c, B->mat->c, op, D->mod); 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); 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) { fmpz_mod_mat_mul_classical_threaded_op(C, NULL, A, B, 0); } flint2-2.8.4/fmpz_mod_mat/mul_fmpz_vec.c000066400000000000000000000013061414523752600202420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { slong i; fmpz_mat_mul_fmpz_vec(c, A->mat, b, blen); for (i = fmpz_mod_mat_nrows(A) - 1; i >= 0; i--) fmpz_mod(c + i, c + i, A->mod); } flint2-2.8.4/fmpz_mod_mat/mul_fmpz_vec_ptr.c000066400000000000000000000012741414523752600211330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { slong i; fmpz_mat_mul_fmpz_vec_ptr(c, A->mat, b, blen); for (i = fmpz_mod_mat_nrows(A) - 1; i >= 0; i--) fmpz_mod(c[i], c[i], A->mod); } flint2-2.8.4/fmpz_mod_mat/neg.c000066400000000000000000000010311414523752600163200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_neg(fmpz_mod_mat_t B, const fmpz_mod_mat_t A) { fmpz_mat_neg(B->mat, A->mat); _fmpz_mod_mat_reduce(B); } flint2-2.8.4/fmpz_mod_mat/randtest.c000066400000000000000000000010711414523752600173770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_randtest(fmpz_mod_mat_t mat, flint_rand_t state) { fmpz_mat_randtest(mat->mat, state, fmpz_bits(mat->mod)); _fmpz_mod_mat_reduce(mat); } flint2-2.8.4/fmpz_mod_mat/reduce.c000066400000000000000000000043771414523752600170360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" typedef struct { slong startrow; slong stoprow; fmpz_mod_mat_struct * M; } _worker_arg; static void _red_worker(void * varg) { _worker_arg * arg = (_worker_arg *) varg; slong startrow = arg->startrow; slong stoprow = arg->stoprow; fmpz_mod_mat_struct * M = arg->M; slong c = fmpz_mod_mat_ncols(M); slong i; for (i = startrow; i < stoprow; i++) _fmpz_vec_scalar_mod_fmpz(M->mat->rows[i], M->mat->rows[i], c, M->mod); } void _fmpz_mod_mat_reduce(fmpz_mod_mat_t M) { slong i, r = fmpz_mod_mat_nrows(M); thread_pool_handle * handles; slong num_workers; _worker_arg mainarg; _worker_arg * args; slong limit; /* limit on threads */ limit = fmpz_size(M->mod) + r + fmpz_mod_mat_ncols(M); limit = limit < 64 ? 0 : (limit - 64)/64; limit = FLINT_MIN(limit, r); mainarg.startrow = 0; mainarg.stoprow = r; mainarg.M = M; if (limit < 2) { use_one_thread: _red_worker(&mainarg); 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].startrow = (i + 0)*r/(num_workers + 1); args[i].stoprow = (i + 1)*r/(num_workers + 1); args[i].M = M; } i = num_workers; mainarg.startrow = (i + 0)*r/(num_workers + 1); mainarg.stoprow = (i + 1)*r/(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]); flint_give_back_threads(handles, num_workers); flint_free(args); return; } flint2-2.8.4/fmpz_mod_mat/rref.c000066400000000000000000000010161414523752600165100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" slong fmpz_mod_mat_rref(slong * perm, fmpz_mod_mat_t mat) { return fmpz_mat_rref_mod(perm, mat->mat, mat->mod); } flint2-2.8.4/fmpz_mod_mat/scalar_mul_fmpz.c000066400000000000000000000012161414523752600207320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { fmpz_t d; fmpz_init(d); fmpz_mod(d, c, A->mod); fmpz_mat_scalar_mul_fmpz(B->mat, A->mat, d); _fmpz_mod_mat_reduce(B); fmpz_clear(d); } flint2-2.8.4/fmpz_mod_mat/scalar_mul_si.c000066400000000000000000000010711414523752600203700ustar00rootroot00000000000000/* 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 2.1 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) { fmpz_mat_scalar_mul_si(B->mat, A->mat, c); _fmpz_mod_mat_reduce(B); } flint2-2.8.4/fmpz_mod_mat/scalar_mul_ui.c000066400000000000000000000010711414523752600203720ustar00rootroot00000000000000/* 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 2.1 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) { fmpz_mat_scalar_mul_ui(B->mat, A->mat, c); _fmpz_mod_mat_reduce(B); } flint2-2.8.4/fmpz_mod_mat/set_fmpz_mat.c000066400000000000000000000010321414523752600202400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_set_fmpz_mat(fmpz_mod_mat_t A, const fmpz_mat_t B) { fmpz_mat_set(A->mat, B); _fmpz_mod_mat_reduce(A); } flint2-2.8.4/fmpz_mod_mat/sqr.c000066400000000000000000000010311414523752600163540ustar00rootroot00000000000000/* 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 2.1 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) { fmpz_mat_sqr(B->mat, A->mat); _fmpz_mod_mat_reduce(B); } flint2-2.8.4/fmpz_mod_mat/strong_echelon_form.c000066400000000000000000000010201414523752600216010ustar00rootroot00000000000000/* 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 2.1 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) { fmpz_mat_strong_echelon_form_mod(mat->mat, mat->mod); } flint2-2.8.4/fmpz_mod_mat/sub.c000066400000000000000000000010711414523752600163440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { fmpz_mat_sub(C->mat, A->mat, B->mat); _fmpz_mod_mat_reduce(C); } flint2-2.8.4/fmpz_mod_mat/test/000077500000000000000000000000001414523752600163675ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_mat/test/t-add_sub.c000066400000000000000000000030301414523752600203710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" int main(void) { slong m, n, rep; FLINT_TEST_INIT(state); flint_printf("add/sub/neg...."); fflush(stdout); for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_mod_mat_t A; fmpz_mod_mat_t B; fmpz_mod_mat_t C; fmpz_t mod; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_init(mod); fmpz_randtest_not_zero(mod, state, 200); fmpz_abs(mod, mod); fmpz_mod_mat_init(A, m, n, mod); fmpz_mod_mat_init(B, m, n, mod); fmpz_mod_mat_init(C, m, n, mod); fmpz_mod_mat_randtest(A, state); fmpz_mod_mat_randtest(B, state); fmpz_mod_mat_neg(C, A); fmpz_mod_mat_add(A, A, B); fmpz_mod_mat_sub(A, A, B); fmpz_mod_mat_neg(A, A); if (!fmpz_mod_mat_equal(A, C)) { flint_printf("FAIL: matrices not equal!\n"); abort(); } fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); fmpz_mod_mat_clear(C); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-fmpz_vec_mul.c000066400000000000000000000055261414523752600214720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("fmpz_vec_mul...."); fflush(stdout); 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_t mod; fmpz_init(mod); fmpz_randtest_not_zero(mod, state, 200); fmpz_abs(mod, mod); m = n_randint(state, 50); n = n_randint(state, 50); alen = n_randint(state, 50); fmpz_mod_mat_init(C, 1, n, mod); fmpz_mod_mat_init(A, 1, m, mod); fmpz_mod_mat_init(B, m, n, mod); c = _fmpz_vec_init(n); a = _fmpz_vec_init(alen); fmpz_mod_mat_randtest(B, state); _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); fmpz_mod_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_mod(fmpz_mod_mat_entry(A, 0, j), a + j, mod); fmpz_mod_mat_mul(C, A, B); 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"); flint_abort(); } } fmpz_clear(mod); fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); fmpz_mod_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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-get_set_fmpz_mat.c000066400000000000000000000027031414523752600223250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" int main(void) { slong m, n, rep; FLINT_TEST_INIT(state); flint_printf("get/set_fmpz_mat...."); fflush(stdout); for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_mod_mat_t A; fmpz_mod_mat_t B; fmpz_t mod; fmpz_mat_t C; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_init(mod); fmpz_randtest_not_zero(mod, state, 200); fmpz_abs(mod, mod); fmpz_mod_mat_init(A, m, n, mod); fmpz_mod_mat_init(B, m, n, mod); fmpz_mat_init(C, m, n); fmpz_mod_mat_randtest(A, state); fmpz_mod_mat_get_fmpz_mat(C, A); fmpz_mod_mat_set_fmpz_mat(B, C); if (!fmpz_mod_mat_equal(A, B)) { flint_printf("FAIL: matrices not equal!\n"); abort(); } fmpz_mat_clear(C); fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-howell_form.c000066400000000000000000000162421414523752600213160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_mat.h" #include "fmpz_mod_mat.h" #include "perm.h" int fmpz_mod_mat_is_in_howell_form(const fmpz_mod_mat_t A) { 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)) return 1; pivots = flint_malloc(A->mat->r * sizeof(slong)); if (!fmpz_mat_is_zero_row(A->mat, 0)) { for (j = 0; j < A->mat->c; j++) { if (!fmpz_is_zero(fmpz_mod_mat_entry(A, 0, j))) { if (!fmpz_divisible(A->mod, 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->mat->r; i++) { if (!fmpz_mat_is_zero_row(A->mat, i)) { if (prevrowzero) { flint_free(pivots); return 0; } for (j = 0; j < A->mat->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(A->mod, fmpz_mod_mat_entry(A, i, j))) { flint_free(pivots); return 0; } pivots[numberpivots] = j; numberpivots++; j = A->mat->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->mat->c); fmpz_init(g); for (i = 0; i < numberpivots; i++) { fmpz_gcd(g, A->mod, fmpz_mod_mat_entry(A, i, pivots[i])); fmpz_divexact(g, A->mod, g); _fmpz_vec_scalar_mul_fmpz(extra_row, A->mat->rows[i], A->mat->c, g); _fmpz_vec_scalar_mod_fmpz(extra_row, extra_row, A->mat->c, A->mod); for ( j = pivots[i] + 1; j < A->mat->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->mat->rows[r], A->mat->c, g); } } } } } _fmpz_vec_scalar_mod_fmpz(extra_row, extra_row, A->mat->c, A->mod); if (!_fmpz_vec_is_zero(extra_row, A->mat->c)) { _fmpz_vec_clear(extra_row, A->mat->c); flint_free(pivots); fmpz_clear(g); return 0; } } _fmpz_vec_clear(extra_row, A->mat->c); flint_free(pivots); fmpz_clear(g); return 1; } int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("howell_form...."); for (i = 0; i < 10000*flint_test_multiplier(); i++) { fmpz_mod_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_mod_mat_init(A, m, n, mod); fmpz_mod_mat_init(D, 2*m, n, mod); fmpz_mod_mat_randtest(A, state); fmpz_mod_mat_init_set(B, A); r1 = fmpz_mod_mat_howell_form(B); if (!fmpz_mod_mat_is_in_howell_form(B)) { flint_printf("FAIL (malformed Howell form)\n"); fmpz_mod_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(B); flint_printf("\n\n"); flint_printf("Modulus: "); fmpz_print(mod); flint_printf("\n\n"); 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_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, mod); fmpz_gcd(t, c, mod); 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); r2 = fmpz_mod_mat_howell_form(D); 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); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(B); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(D); flint_printf("\n\n"); flint_printf("Modulus: "); fmpz_print(mod); abort(); } _perm_clear(perm); fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); fmpz_mod_mat_clear(D); fmpz_clear(mod); fmpz_clear(t); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-init_clear.c000066400000000000000000000023631414523752600211110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); for (i = 0; i < 1000 * 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_t mod; fmpz_init(mod); fmpz_randtest_not_zero(mod, state, 200); fmpz_abs(mod, mod); fmpz_mod_mat_init(a, rows, cols, mod); 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); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-mul.c000066400000000000000000000104051414523752600175710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod_mat.h" #include "ulong_extras.h" int main(void) { fmpz_mod_mat_t A, B, B1, B2, C, C1, C2, D; slong max_threads = 5; slong i; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); /* test A*(B1+B1) = A*B1 + A*B2 */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong m, n, k; fmpz_t mod; fmpz_init(mod); fmpz_randtest_not_zero(mod, state, 200); fmpz_abs(mod, mod); 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, mod); fmpz_mod_mat_init(B, n, k, mod); fmpz_mod_mat_init(B1, n, k, mod); fmpz_mod_mat_init(B2, n, k, mod); fmpz_mod_mat_init(C, m, k, mod); fmpz_mod_mat_init(C1, m, k, mod); fmpz_mod_mat_init(C2, m, k, mod); fmpz_mod_mat_init(D, m, k, mod); fmpz_mod_mat_randtest(A, state); fmpz_mod_mat_randtest(B1, state); fmpz_mod_mat_randtest(B2, state); /* Make sure noise in the output is ok */ fmpz_mod_mat_randtest(C, state); fmpz_mod_mat_randtest(C1, state); fmpz_mod_mat_randtest(C2, state); fmpz_mod_mat_mul(C1, A, B1); fmpz_mod_mat_mul(C2, A, B2); fmpz_mod_mat_add(B, B1, B2); fmpz_mod_mat_mul(C, A, B); fmpz_mod_mat_add(D, C1, C2); if (!fmpz_mod_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n\n"); fmpz_mod_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(B1); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(B2); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(C); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(D); flint_printf("\n\n"); flint_abort(); } if (n == k) { fmpz_mod_mat_mul(A, A, B); if (!fmpz_mod_mat_equal(A, C)) { flint_printf("FAIL: aliasing failed\n"); flint_abort(); } } fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); fmpz_mod_mat_clear(B1); fmpz_mod_mat_clear(B2); fmpz_mod_mat_clear(C); fmpz_mod_mat_clear(C1); fmpz_mod_mat_clear(C2); fmpz_mod_mat_clear(D); fmpz_clear(mod); } /* Test aliasing with windows */ { fmpz_mod_mat_t A, B, A_window; fmpz_t p; fmpz_init_set_ui(p, 3); fmpz_mod_mat_init(A, 2, 2, p); fmpz_mod_mat_init(B, 2, 2, p); fmpz_mod_mat_window_init(A_window, A, 0, 0, 2, 2); fmpz_mod_mat_one(A); fmpz_mod_mat_one(B); 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); if (!fmpz_mod_mat_equal(A, B)) { flint_printf("FAIL: window aliasing failed\n"); fmpz_mod_mat_print_pretty(A); flint_printf("\n\n"); fmpz_mod_mat_print_pretty(B); flint_printf("\n\n"); flint_abort(); } fmpz_clear(p); fmpz_mod_mat_window_clear(A_window); fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-mul_classical_threaded.c000077500000000000000000000047121414523752600234560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz_mod_mat.h" #include "ulong_extras.h" #include "thread_support.h" int main(void) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) slong i, max_threads = 5; slong tmul = 1000; #ifdef _WIN32 tmul = 50; #endif #endif FLINT_TEST_INIT(state); flint_printf("mul_classical_threaded...."); fflush(stdout); #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mat_t A, B, C, D; fmpz_t mod; slong m, k, n; fmpz_init(mod); 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_randtest_not_zero(mod, state, 100); fmpz_mod_mat_init(A, m, n, mod); fmpz_mod_mat_init(B, n, k, mod); fmpz_mod_mat_init(C, m, k, mod); fmpz_mod_mat_init(D, m, k, mod); fmpz_mod_mat_randtest(A, state); fmpz_mod_mat_randtest(B, state); fmpz_mod_mat_randtest(C, state); /* make sure noise in the output is ok */ fmpz_mod_mat_mul_classical_threaded(C, A, B); fmpz_mod_mat_mul(D, A, B); if (!fmpz_mod_mat_equal(C, D)) { flint_printf("FAIL: results not equal\n"); fmpz_mod_mat_print_pretty(A); fmpz_mod_mat_print_pretty(B); fmpz_mod_mat_print_pretty(C); fmpz_mod_mat_print_pretty(D); abort(); } fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); fmpz_mod_mat_clear(C); fmpz_mod_mat_clear(D); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); #else FLINT_TEST_CLEANUP(state); flint_printf("SKIPPED\n"); #endif return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-mul_fmpz_vec.c000066400000000000000000000055261414523752600214720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mul_fmpz_vec...."); fflush(stdout); 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_t mod; fmpz_init(mod); fmpz_randtest_not_zero(mod, state, 200); fmpz_abs(mod, mod); m = n_randint(state, 50); n = n_randint(state, 50); blen = n_randint(state, 50); fmpz_mod_mat_init(C, m, 1, mod); fmpz_mod_mat_init(A, m, n, mod); fmpz_mod_mat_init(B, n, 1, mod); c = _fmpz_vec_init(m); b = _fmpz_vec_init(blen); fmpz_mod_mat_randtest(A, state); _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); fmpz_mod_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_mod(fmpz_mod_mat_entry(B, j, 0), b + j, mod); fmpz_mod_mat_mul(C, A, B); 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"); flint_abort(); } } fmpz_clear(mod); fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); fmpz_mod_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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-rref.c000066400000000000000000000076651414523752600177500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "fmpz_mod_mat.h" #include "ulong_extras.h" void fmpz_mod_mat_randrank(fmpz_mod_mat_t mat, flint_rand_t state, slong rank) { slong i; fmpz * diag; if (rank < 0 || rank > mat->mat->r || rank > mat->mat->c) { flint_printf("Exception (fmpz_mod_mat_randrank). Impossible rank.\n"); flint_abort(); } diag = _fmpz_vec_init(rank); for (i = 0; i < rank; i++) { fmpz_randtest_mod(&diag[i], state, mat->mod); while (fmpz_is_zero(&diag[i])) { fmpz_randtest_mod(&diag[i], state, mat->mod); } } fmpz_mat_randpermdiag(mat->mat, state, diag, rank); _fmpz_vec_clear(diag, rank); } 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->mat->r; i++) { for (j = 0; j < A->mat->c; j++) { /* Found nonzero entry */ if (!fmpz_is_zero(A->mat->rows[i] + j)) { if (prev_row_zero) { flint_printf("nonzero row after zero row\n"); abort(); } if (j <= prev_pivot) { flint_printf("pivot not strictly to the right of previous\n"); abort(); } prev_pivot = j; break; } prev_row_zero = (j + 1 == A->mat->c); } } } int main(void) { fmpz_mod_mat_t A; fmpz_t p; slong i, m, n, d, r, rank; slong *perm; FLINT_TEST_INIT(state); flint_printf("rref...."); fflush(stdout); /* Maximally sparse matrices of given rank */ for (i = 0; i < 10000; i++) { m = n_randint(state, 10); n = n_randint(state, 10); perm = flint_malloc(FLINT_MAX(1, m) * sizeof(slong)); fmpz_init_set_ui(p, n_randtest_prime(state, 0)); for (r = 0; r <= FLINT_MIN(m, n); r++) { fmpz_mod_mat_init(A, m, n, p); fmpz_mod_mat_randrank(A, state, r); rank = fmpz_mod_mat_rref(perm, A); if (r < rank) { fmpz_mod_mat_print_pretty(A); flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); abort(); } check_rref(A); fmpz_mod_mat_clear(A); } fmpz_clear(p); flint_free(perm); } /* Dense */ for (i = 0; i < 10000; i++) { m = n_randint(state, 5); n = n_randint(state, 4); perm = flint_malloc(FLINT_MAX(1, m) * sizeof(slong)); fmpz_init_set_ui(p, n_randtest_prime(state, 0)); for (r = 0; r <= FLINT_MIN(m, n); r++) { d = n_randint(state, 2 * m * n + 1); fmpz_mod_mat_init(A, m, n, p); fmpz_mod_mat_randrank(A, state, r); fmpz_mat_randops(A->mat, state, d); _fmpz_mod_mat_reduce(A); rank = fmpz_mod_mat_rref(perm, A); if (r < rank) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); abort(); } check_rref(A); fmpz_mod_mat_clear(A); } fmpz_clear(p); flint_free(perm); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-scalar_mul_fmpz.c000066400000000000000000000040701414523752600221530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz_mod_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep; FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpz...."); fflush(stdout); for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_mod_mat_t A, B, C, D; fmpz_t mod, c, c1; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_init(c); fmpz_init(c1); fmpz_init(mod); fmpz_randtest_not_zero(mod, state, 200); fmpz_abs(mod, mod); fmpz_randtest(c, state, 200); fmpz_mod_mat_init(A, m, n, mod); fmpz_mod_mat_init(B, m, n, mod); fmpz_mod_mat_init(C, m, n, mod); fmpz_mod_mat_init(D, m, n, mod); fmpz_mod_mat_randtest(A, state); fmpz_mod_mat_randtest(B, state); fmpz_mod_mat_scalar_mul_fmpz(C, A, c); fmpz_set(c1, c); fmpz_sub_ui(c1, c1, 1); fmpz_mod_mat_scalar_mul_fmpz(D, A, c1); /* c*A - (c-1)*A == A */ fmpz_mod_mat_sub(D, C, D); if (!fmpz_mod_mat_equal(A, D)) { flint_printf("FAIL\n"); abort(); } /* Aliasing */ fmpz_mod_mat_scalar_mul_fmpz(C, A, c); fmpz_mod_mat_scalar_mul_fmpz(A, A, c); if (!fmpz_mod_mat_equal(A, C)) { flint_printf("FAIL\n"); abort(); } fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); fmpz_mod_mat_clear(C); fmpz_mod_mat_clear(D); fmpz_clear(mod); fmpz_clear(c1); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-scalar_mul_si.c000066400000000000000000000042041414523752600216110ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz_mod_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep; FLINT_TEST_INIT(state); flint_printf("scalar_mul_si...."); fflush(stdout); for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_mod_mat_t A, B, C, D; slong c; fmpz_t mod, c1; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_init(c1); fmpz_init(mod); fmpz_randtest_not_zero(mod, state, 200); fmpz_abs(mod, mod); c = (slong) n_randbits(state, n_randint(state, FLINT_BITS)); if (n_randint(state, 2) == 0) c = -c; fmpz_mod_mat_init(A, m, n, mod); fmpz_mod_mat_init(B, m, n, mod); fmpz_mod_mat_init(C, m, n, mod); fmpz_mod_mat_init(D, m, n, mod); fmpz_mod_mat_randtest(A, state); fmpz_mod_mat_randtest(B, state); fmpz_mod_mat_scalar_mul_si(C, A, c); fmpz_set_si(c1, c); fmpz_sub_ui(c1, c1, 1); fmpz_mod(c1, c1, A->mod); fmpz_mod_mat_scalar_mul_fmpz(D, A, c1); /* c*A - (c-1)*A == A */ fmpz_mod_mat_sub(D, C, D); if (!fmpz_mod_mat_equal(A, D)) { flint_printf("FAIL\n"); abort(); } /* Aliasing */ fmpz_mod_mat_scalar_mul_si(C, A, c); fmpz_mod_mat_scalar_mul_si(A, A, c); if (!fmpz_mod_mat_equal(A, C)) { flint_printf("FAIL\n"); abort(); } fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); fmpz_mod_mat_clear(C); fmpz_mod_mat_clear(D); fmpz_clear(mod); fmpz_clear(c1); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-scalar_mul_ui.c000066400000000000000000000041151414523752600216140ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz_mod_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep; FLINT_TEST_INIT(state); flint_printf("scalar_mul_ui...."); fflush(stdout); for (rep = 0; rep < 1000 * flint_test_multiplier(); rep++) { fmpz_mod_mat_t A, B, C, D; ulong c; fmpz_t mod, c1; m = n_randint(state, 20); n = n_randint(state, 20); fmpz_init(c1); fmpz_init(mod); fmpz_randtest_not_zero(mod, state, 200); fmpz_abs(mod, mod); c = n_randbits(state, n_randint(state, FLINT_BITS)); fmpz_mod_mat_init(A, m, n, mod); fmpz_mod_mat_init(B, m, n, mod); fmpz_mod_mat_init(C, m, n, mod); fmpz_mod_mat_init(D, m, n, mod); fmpz_mod_mat_randtest(A, state); fmpz_mod_mat_randtest(B, state); fmpz_mod_mat_scalar_mul_ui(C, A, c); fmpz_set_ui(c1, c); fmpz_sub_ui(c1, c1, 1); fmpz_mod(c1, c1, A->mod); fmpz_mod_mat_scalar_mul_fmpz(D, A, c1); /* c*A - (c-1)*A == A */ fmpz_mod_mat_sub(D, C, D); if (!fmpz_mod_mat_equal(A, D)) { flint_printf("FAIL\n"); abort(); } /* Aliasing */ fmpz_mod_mat_scalar_mul_ui(C, A, c); fmpz_mod_mat_scalar_mul_ui(A, A, c); if (!fmpz_mod_mat_equal(A, C)) { flint_printf("FAIL\n"); abort(); } fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); fmpz_mod_mat_clear(C); fmpz_mod_mat_clear(D); fmpz_clear(mod); fmpz_clear(c1); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-sqr.c000066400000000000000000000034061414523752600176040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("sqr...."); fflush(stdout); for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mod_mat_t A, B, C; slong n; fmpz_t mod; n = n_randint(state, 20); fmpz_init(mod); fmpz_randtest_not_zero(mod, state, 200); fmpz_abs(mod, mod); fmpz_mod_mat_init(A, n, n, mod); fmpz_mod_mat_init(B, n, n, mod); fmpz_mod_mat_init(C, n, n, mod); fmpz_mod_mat_randtest(A, state); fmpz_mod_mat_randtest(B, state); /* Make sure noise in the output is ok */ fmpz_mod_mat_randtest(B, state); fmpz_mod_mat_sqr(B, A); fmpz_mod_mat_mul(C, A, A); if (!fmpz_mod_mat_equal(C, B)) { flint_printf("FAIL: results not equal\n"); abort(); } fmpz_mod_mat_sqr(A, A); if (!fmpz_mod_mat_equal(A, B)) { flint_printf("FAIL: aliasing failed\n"); abort(); } fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); fmpz_mod_mat_clear(C); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-trace.c000066400000000000000000000041551414523752600200770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("trace...."); fflush(stdout); /* Test trace(AB) = trace(BA) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_mat_t A, B, AB, BA; fmpz_t trab, trba, mod; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); fmpz_init(mod); fmpz_randtest_not_zero(mod, state, 100); fmpz_abs(mod, mod); fmpz_mod_mat_init(A, m, n, mod); fmpz_mod_mat_init(B, n, m, mod); fmpz_mod_mat_init(AB, m, m, mod); fmpz_mod_mat_init(BA, n, n, mod); fmpz_init(trab); fmpz_init(trba); fmpz_mod_mat_randtest(A, state); fmpz_mod_mat_randtest(B, state); fmpz_mod_mat_mul(AB, A, B); fmpz_mod_mat_mul(BA, B, A); fmpz_mod_mat_trace(trab, AB); fmpz_mod_mat_trace(trba, BA); if (!fmpz_equal(trab, trba)) { flint_printf("FAIL:\n"); fmpz_mod_mat_print_pretty(A), flint_printf("\n"); fmpz_mod_mat_print_pretty(B), flint_printf("\n"); fmpz_mod_mat_print_pretty(AB), flint_printf("\n"); fmpz_mod_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"); abort(); } fmpz_mod_mat_clear(A); fmpz_mod_mat_clear(B); fmpz_mod_mat_clear(AB); fmpz_mod_mat_clear(BA); fmpz_clear(trab); fmpz_clear(trba); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/test/t-window_init_clear.c000066400000000000000000000031251414523752600224750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("window_init/clear...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t mod; 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_init(mod); fmpz_randtest_not_zero(mod, state, 100); fmpz_abs(mod, mod); fmpz_mod_mat_init(a, rows, cols, mod); fmpz_mod_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; fmpz_mod_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_mod_mat_entry(w, j, k)); fmpz_mod_mat_window_clear(w); fmpz_mod_mat_clear(a); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mat/trace.c000066400000000000000000000010451414523752600166520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_trace(fmpz_t trace, const fmpz_mod_mat_t mat) { fmpz_mat_trace(trace, mat->mat); fmpz_mod(trace, trace, mat->mod); } flint2-2.8.4/fmpz_mod_mat/window_clear.c000066400000000000000000000010251414523752600202270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mat.h" void fmpz_mod_mat_window_clear(fmpz_mod_mat_t window) { fmpz_mat_window_clear(window->mat); fmpz_clear(window->mod); } flint2-2.8.4/fmpz_mod_mat/window_init.c000066400000000000000000000012321414523752600201040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { fmpz_mat_window_init(window->mat, mat->mat, r1, c1, r2, c2); fmpz_init_set(window->mod, mat->mod); } flint2-2.8.4/fmpz_mod_mpoly.h000066400000000000000000001310041414523752600161370ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPZ_MOD_MPOLY_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_mod.h" #include "fmpz_mpoly.h" #include "mpoly.h" #include "n_poly.h" #ifdef __cplusplus extern "C" { #endif /* type definitions **********************************************************/ 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]; /* fmpz_mod_mpoly_t sparse multivariates with fmpz_mod coeffs */ 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]; /* 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 ************************************************************/ FLINT_DLL void fmpz_mod_mpoly_ctx_init(fmpz_mod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, const fmpz_t modulus); FLINT_DLL void fmpz_mod_mpoly_ctx_init_rand(fmpz_mod_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars, const fmpz_t modulus); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 fmpz_mod_ctx_modulus(ctx->ffinfo); } 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; } FLINT_DLL void fmpz_mod_mpoly_clear(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_init2(fmpz_mod_mpoly_t A, slong alloc, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_init3(fmpz_mod_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_realloc(fmpz_mod_mpoly_t A, slong alloc, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_fit_length(fmpz_mod_mpoly_t A, slong length, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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 **************************************************************/ FLINT_DLL 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); FLINT_DLL char * fmpz_mod_mpoly_get_str_pretty(const fmpz_mod_mpoly_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mod_mpoly_fprint_pretty(FILE * file, const fmpz_mod_mpoly_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE 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); } /* Basic manipulation *******************************************************/ FLINT_DLL void fmpz_mod_mpoly_gen(fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mod_mpoly_is_gen(const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_set(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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) { fmpz_mod_mpoly_struct t = *A; *A = *B; *B = t; } /* Constants *****************************************************************/ FLINT_DLL int fmpz_mod_mpoly_is_fmpz(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_get_fmpz(fmpz_t c, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_set_fmpz_mod(fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_set_fmpz(fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_set_ui(fmpz_mod_mpoly_t A, slong c, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL int fmpz_mod_mpoly_equal_fmpz(const fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mod_mpoly_equal_ui(const fmpz_mod_mpoly_t A, ulong c, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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 *******************************************************************/ FMPZ_MOD_MPOLY_INLINE 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); } FMPZ_MOD_MPOLY_INLINE 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); } FMPZ_MOD_MPOLY_INLINE 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); } FMPZ_MOD_MPOLY_INLINE void fmpz_mod_mpoly_degree_fmpz(fmpz_t deg, const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) { mpoly_degree_fmpz(deg, A->exps, A->length, A->bits, var, ctx->minfo); } FMPZ_MOD_MPOLY_INLINE slong fmpz_mod_mpoly_degree_si(const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx) { return mpoly_degree_si(A->exps, A->length, A->bits, var, ctx->minfo); } FMPZ_MOD_MPOLY_INLINE 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); } FMPZ_MOD_MPOLY_INLINE 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); } FMPZ_MOD_MPOLY_INLINE 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); } FMPZ_MOD_MPOLY_INLINE 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); } /* Coefficients **************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ****************************************************************/ FLINT_DLL int fmpz_mod_mpoly_is_fmpz_mod_poly(const fmpz_mod_mpoly_t A, slong var, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ****************************************************************/ FLINT_DLL 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 ******************************************************/ FLINT_DLL 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; } FLINT_DLL void fmpz_mod_mpoly_resize(fmpz_mod_mpoly_t A, slong new_length, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mod_mpoly_set_term_coeff_ui(fmpz_mod_mpoly_t A, slong i, ulong c, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_set_term_coeff_si(fmpz_mod_mpoly_t A, slong i, slong c, const fmpz_mod_mpoly_ctx_t ctx); FMPZ_MOD_MPOLY_INLINE 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); } FMPZ_MOD_MPOLY_INLINE 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_DLL 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mod_mpoly_sort_terms(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_combine_like_terms(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_reverse(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_assert_canonical(const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void _fmpz_mod_mpoly_radix_sort1(fmpz *, ulong *, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask); FLINT_DLL void _fmpz_mod_mpoly_radix_sort(fmpz *, ulong *, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask); FLINT_DLL void _fmpz_mod_mpoly_push_exp_ffmpz(fmpz_mod_mpoly_t A, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void _fmpz_mod_mpoly_push_exp_pfmpz(fmpz_mod_mpoly_t A, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void _fmpz_mod_mpoly_push_exp_ui(fmpz_mod_mpoly_t A, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx); /* Random generation *********************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ******************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 *********************************************************/ FLINT_DLL void fmpz_mod_mpoly_neg(fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_t B, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ************************************************************/ FLINT_DLL 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 ****************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ******************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ******************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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"); } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ***************************************************************/ FLINT_DLL 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; } FLINT_DLL 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 ***********************************************************************/ FLINT_DLL void fmpz_mod_mpoly_term_content(fmpz_mod_mpoly_t M, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mod_mpoly_deflation(fmpz * shift, fmpz * stride, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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 ***************************************************************/ FLINT_DLL void fmpz_mod_mpoly_univar_init(fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_univar_clear(fmpz_mod_mpoly_univar_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_univar_fit_length(fmpz_mod_mpoly_univar_t A, slong length, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_univar_print_pretty(const fmpz_mod_mpoly_univar_t A, const char ** x, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL 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); FLINT_DLL 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_DLL 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); FLINT_DLL 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) { fmpz_mod_mpoly_univar_struct t = *A; *A = *B; *B = t; } 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); } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); } FLINT_DLL 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); FLINT_DLL 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]; FLINT_DLL void fmpz_mod_mpoly_geobucket_init(fmpz_mod_mpoly_geobucket_t B, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_geobucket_clear(fmpz_mod_mpoly_geobucket_t B, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_geobucket_empty(fmpz_mod_mpoly_t p, fmpz_mod_mpoly_geobucket_t B, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_geobucket_fit_length(fmpz_mod_mpoly_geobucket_t B, slong i, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_geobucket_set(fmpz_mod_mpoly_geobucket_t B, fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_geobucket_add(fmpz_mod_mpoly_geobucket_t B, fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_geobucket_sub(fmpz_mod_mpoly_geobucket_t B, fmpz_mod_mpoly_t p, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int fmpz_mod_mpoly_repack_bits_inplace(fmpz_mod_mpoly_t A, flint_bitcnt_t Abits, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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 ******************************************************************************/ /* test that r is a valid remainder upon division by g this means that no monomial of r is divisible by lm(g) */ FMPZ_MOD_MPOLY_INLINE 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); mask = (bits <= FLINT_BITS) ? mpoly_overflow_mask_sp(bits) : 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_printf("fmpz_mod_mpoly_remainder_strongtest FAILED i = %wd\n", i); flint_printf("rem ");fmpz_mod_mpoly_print_pretty(r, NULL, ctx); printf("\n\n"); flint_printf("den ");fmpz_mod_mpoly_print_pretty(g, NULL, ctx); printf("\n\n"); flint_abort(); } } flint_free(rexp); flint_free(gexp); } #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpz_mod_mpoly/000077500000000000000000000000001414523752600157675ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_mpoly/add.c000066400000000000000000000076721414523752600166770ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/add_fmpz.c000066400000000000000000000055661414523752600177330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/clear.c000066400000000000000000000012761414523752600172270ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_mod_mpoly/cmp.c000066400000000000000000000021351414523752600167130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } return 0; } flint2-2.8.4/fmpz_mod_mpoly/combine_like_terms.c000066400000000000000000000027631414523752600217750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/compose_fmpz_mod_mpoly.c000066400000000000000000000035521414523752600227200ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/compose_fmpz_mod_mpoly_geobucket.c000066400000000000000000000036221414523752600247460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/compose_mat.c000066400000000000000000000041311414523752600204400ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_vec(v, M, u); 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; } flint2-2.8.4/fmpz_mod_mpoly/content_vars.c000066400000000000000000000130001414523752600206320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/ctx_clear.c000066400000000000000000000010361414523752600200770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/ctx_init.c000066400000000000000000000012151414523752600177530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/ctx_init_rand.c000066400000000000000000000034071414523752600207640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" 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); } 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); } flint2-2.8.4/fmpz_mod_mpoly/deflate.c000066400000000000000000000031071414523752600175400ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/deflation.c000066400000000000000000000013041414523752600200760ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/derivative.c000066400000000000000000000061531414523752600203020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/discriminant.c000066400000000000000000000015101414523752600206140ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_mod_mpoly/div.c000066400000000000000000000011531414523752600167150ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_mod_mpoly/div_monagan_pearce.c000066400000000000000000000260341414523752600217410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 indicies */ 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 cofficient 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) { /* optimation: 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 neccesary */ 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); } flint2-2.8.4/fmpz_mod_mpoly/divides.c000066400000000000000000000064321414523752600175670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" #include "ulong_extras.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 > 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; } flint2-2.8.4/fmpz_mod_mpoly/divides_dense.c000066400000000000000000000204551414523752600207460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" #include "long_extras.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(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) { 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; } flint2-2.8.4/fmpz_mod_mpoly/divides_monagan_pearce.c000066400000000000000000000505471414523752600226140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 indicies */ 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 neccesary */ 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 indicies */ 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; } flint2-2.8.4/fmpz_mod_mpoly/divrem.c000066400000000000000000000012061414523752600174200ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpz_mod_mpoly/divrem_ideal.c000066400000000000000000000012671414523752600205650ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_mod_mpoly/divrem_ideal_monagan_pearce.c000066400000000000000000000311031414523752600235740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; slong ** hinds; 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); /* TODO figure out how to avoid TMP_ALLOC in a loop */ chains = TMP_ARRAY_ALLOC(Blen, mpoly_nheap_t *); hinds = TMP_ARRAY_ALLOC(Blen, slong *); len3 = 0; for (w = 0; w < Blen; w++) { chains[w] = TMP_ARRAY_ALLOC(Bs[w]->length, mpoly_nheap_t); hinds[w] = TMP_ARRAY_ALLOC(Bs[w]->length, 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_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 = 1; 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; } flint2-2.8.4/fmpz_mod_mpoly/divrem_monagan_pearce.c000066400000000000000000000577261414523752600224610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 indicies */ 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 neccesary */ 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 indicies */ 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 neccesary */ 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); } flint2-2.8.4/fmpz_mod_mpoly/equal.c000066400000000000000000000015261414523752600172460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/equal_fmpz.c000066400000000000000000000033371414523752600203040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 0; 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); } flint2-2.8.4/fmpz_mod_mpoly/evaluate_all_fmpz.c000066400000000000000000000056261414523752600216360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/evaluate_one.c000066400000000000000000000130261414523752600206040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/fit_length.c000066400000000000000000000013031414523752600202530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/fit_length_fit_bits.c000066400000000000000000000033301414523752600221400ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } } } flint2-2.8.4/fmpz_mod_mpoly/fit_length_reset_bits.c000066400000000000000000000013671414523752600225100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/fprint_pretty.c000066400000000000000000000013351414523752600210460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" #include "fmpz_mpoly.h" 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); } flint2-2.8.4/fmpz_mod_mpoly/gcd.c000066400000000000000000000017651414523752600167010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/gcd_brown.c000066400000000000000000000014521414523752600201010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/gcd_cofactors.c000066400000000000000000000040451414523752600207360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.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); } flint2-2.8.4/fmpz_mod_mpoly/gcd_hensel.c000066400000000000000000000014521414523752600202300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/gcd_subresultant.c000066400000000000000000000014601414523752600215040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/gcd_zippel.c000066400000000000000000000014531414523752600202560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/gcd_zippel2.c000066400000000000000000000014551414523752600203420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/gen.c000066400000000000000000000017661414523752600167160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/geobuckets.c000066400000000000000000000077271414523752600203030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/get_coeff_fmpz_fmpz.c000066400000000000000000000015731414523752600221520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mod_mpoly/get_coeff_fmpz_monomial.c000066400000000000000000000017761414523752600230160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mod_mpoly/get_coeff_fmpz_ui.c000066400000000000000000000015661414523752600216150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mod_mpoly/get_coeff_vars_ui.c000066400000000000000000000076551414523752600216210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/get_fmpz.c000066400000000000000000000016551414523752600177550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/get_set_is_fmpz_mod_poly.c000066400000000000000000000067511414523752600232270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.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); } flint2-2.8.4/fmpz_mod_mpoly/get_set_nmod_mpoly.c000066400000000000000000000025321414523752600220240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/get_str_pretty.c000066400000000000000000000013171414523752600212130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" #include "fmpz_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); } flint2-2.8.4/fmpz_mod_mpoly/get_term.c000066400000000000000000000017211414523752600177420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/get_term_coeff_fmpz.c000066400000000000000000000013551414523752600221430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpz_mod_mpoly/get_term_exp_fmpz.c000066400000000000000000000014741414523752600216570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/get_term_exp_si.c000066400000000000000000000014611414523752600213120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/get_term_exp_ui.c000066400000000000000000000014611414523752600213140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/get_term_monomial.c000066400000000000000000000016761414523752600216460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/get_term_var_exp_si.c000066400000000000000000000015041414523752600221600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/get_term_var_exp_ui.c000066400000000000000000000015101414523752600221570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/inflate.c000066400000000000000000000047101414523752600175570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/init.c000066400000000000000000000023041414523752600170750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/is_canonical.c000066400000000000000000000044701414523752600205620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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"); } } flint2-2.8.4/fmpz_mod_mpoly/is_fmpz.c000066400000000000000000000013061414523752600176020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/lead_coeff_vars.c000066400000000000000000000035721414523752600212440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/fmpz_mod_mpoly/make_monic.c000066400000000000000000000014521414523752600202370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/mul.c000066400000000000000000000056601414523752600167370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" #include "long_extras.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; 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; } flint2-2.8.4/fmpz_mod_mpoly/mul_dense.c000066400000000000000000000165041414523752600201140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" #include "long_extras.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(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) { 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; } flint2-2.8.4/fmpz_mod_mpoly/mul_johnson.c000066400000000000000000000371371414523752600205010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" #include "mpn_extras.h" 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); 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); 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; } flint2-2.8.4/fmpz_mod_mpoly/neg.c000066400000000000000000000016651414523752600167140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.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); } flint2-2.8.4/fmpz_mod_mpoly/pow_fmpz.c000066400000000000000000000037031414523752600177770ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/pow_rmul.c000066400000000000000000000017151414523752600200030ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_mod_mpoly/pow_ui.c000066400000000000000000000035641414523752600174450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/profile/000077500000000000000000000000001414523752600174275ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_mpoly/profile/p-gcd.c000066400000000000000000000274121414523752600205730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" #include "profiler.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() { 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; } flint2-2.8.4/fmpz_mod_mpoly/push_term_fmpz_fmpz.c000066400000000000000000000043751414523752600222420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/push_term_fmpz_ui.c000066400000000000000000000032621414523752600216750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/quadratic_root.c000066400000000000000000000044071414523752600211600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/fmpz_mod_mpoly/randtest_bits.c000066400000000000000000000026021414523752600210000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/randtest_bound.c000066400000000000000000000023151414523752600211470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/randtest_bounds.c000066400000000000000000000023221414523752600213300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/repack_bits.c000066400000000000000000000040431414523752600204220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/resize.c000066400000000000000000000023331414523752600174350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/resultant.c000066400000000000000000000017141414523752600201570ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_mod_mpoly/scalar_addmul_fmpz.c000066400000000000000000000136321414523752600217670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/scalar_mul_fmpz.c000066400000000000000000000062011414523752600213100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.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); } flint2-2.8.4/fmpz_mod_mpoly/set.c000066400000000000000000000015241414523752600167300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/set_coeff_fmpz_fmpz.c000066400000000000000000000063611414523752600221660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 = (fmpz *) TMP_ALLOC(nvars*sizeof(fmpz)); for (i = 0; i < nvars; i++) newexp[i] = *exp[i]; _fmpz_mod_mpoly_set_coeff_fmpz_fmpz(A, c, newexp, ctx); 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); } flint2-2.8.4/fmpz_mod_mpoly/set_coeff_fmpz_monomial.c000066400000000000000000000021341414523752600230170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/set_coeff_fmpz_ui.c000066400000000000000000000026441414523752600216270ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_mod_mpoly/set_fmpz.c000066400000000000000000000035031414523752600177630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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, 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_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); } flint2-2.8.4/fmpz_mod_mpoly/set_str_pretty.c000066400000000000000000000024341414523752600212300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/fmpz_mod_mpoly/set_term_coeff_fmpz.c000066400000000000000000000025421414523752600221560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/set_term_exp_fmpz.c000066400000000000000000000020071414523752600216640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/set_term_exp_ui.c000066400000000000000000000017731414523752600213360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/sort_terms.c000066400000000000000000000133661414523752600203450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); ULONG_SWAP(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); ULONG_SWAP(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; } flint2-2.8.4/fmpz_mod_mpoly/sqrt_heap.c000066400000000000000000000516411414523752600201300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" /* 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 cofficient 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 cofficient 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; } flint2-2.8.4/fmpz_mod_mpoly/sub.c000066400000000000000000000077511414523752600167360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/sub_fmpz.c000066400000000000000000000025371414523752600177670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/term_content.c000066400000000000000000000032441414523752600206370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly/test/000077500000000000000000000000001414523752600167465ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_mpoly/test/t-add_sub.c000066400000000000000000000267461414523752600207730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("add_sub...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-add_sub_fmpz.c000066400000000000000000000053531414523752600220160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("add_sub_fmpz...."); fflush(stdout); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-add_sub_si.c000066400000000000000000000053051414523752600214520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" #include "long_extras.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("add_sub_si...."); fflush(stdout); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-cmp.c000066400000000000000000000130551414523752600201360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" int main(void) { int result; slong i, j1, j2; FLINT_TEST_INIT(state); flint_printf("cmp...."); fflush(stdout); /* 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-degree.c000066400000000000000000000107051414523752600206110ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("degree...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-degrees_term_exp_fits_ui_si.c000066400000000000000000000206231414523752600251140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("degrees_term_exp_fits_ui_si...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); flint_abort(); } } else { flint_printf("FAIL\nFLINT_BITS is not 64 or 32\n"); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-derivative.c000066400000000000000000000141021414523752600215130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j; slong tmul = 5; FLINT_TEST_INIT(state); flint_printf("derivative...."); fflush(stdout); /* 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); 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); flint_abort(); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-div_monagan_pearce.c000066400000000000000000000146701414523752600231640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("div_monagan_pearce...."); fflush(stdout); /* 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); 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); 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); 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; 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; exp_bound = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 50/ctx->minfo->nvars) + 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-divides.c000066400000000000000000000334431414523752600210110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j, result, ret, max_threads = 5, tmul = 25; FLINT_TEST_INIT(state); flint_printf("divides...."); fflush(stdout); /* 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); 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); 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; 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); max_bound = 1 + 150/ctx->minfo->nvars/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)); 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); 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; 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); max_bound = 1 + 20/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++) { 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-divides_dense.c000066400000000000000000000246401414523752600221660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j; int result, ret; FLINT_TEST_INIT(state); flint_printf("divides_dense...."); fflush(stdout); /* 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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; 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); max_bound = 1 + 20/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)); 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-divides_monagan_pearce.c000066400000000000000000000335751414523752600240360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j, result, ret, max_threads = 5, tmul = 25; FLINT_TEST_INIT(state); flint_printf("divides_monagan_pearce...."); fflush(stdout); /* 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); 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); 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; 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); max_bound = 1 + 150/ctx->minfo->nvars/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)); 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); 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; 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); max_bound = 1 + 20/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++) { 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-divrem.c000066400000000000000000000334641414523752600206530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("divrem...."); fflush(stdout); /* 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, FLINT_BITS - 2) + 1; exp_bits1 = n_randint(state, FLINT_BITS - 2) + 1; exp_bits2 = n_randint(state, FLINT_BITS - 2) + 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); 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; 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; exp_bound = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 50/ctx->minfo->nvars) + 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); 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; 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; exp_bound = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 50/ctx->minfo->nvars) + 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); 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; 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; exp_bound = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 50/ctx->minfo->nvars) + 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); 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; 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; exp_bound = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 50/ctx->minfo->nvars) + 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); 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; 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; exp_bound = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 50/ctx->minfo->nvars) + 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-divrem_ideal_monagan_pearce.c000066400000000000000000000216041414523752600250210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j, w; FLINT_TEST_INIT(state); flint_printf("divrem_ideal_monagan_pearce...."); fflush(stdout); /* 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); 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]; 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; exp_bound = n_randint(state, 10/ctx->minfo->nvars + 1) + 2; exp_bound1 = n_randint(state, 25/ctx->minfo->nvars + 1) + 2; exp_bound2 = n_randint(state, 20/ctx->minfo->nvars + 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); 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]; 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; exp_bound = n_randint(state, 10/ctx->minfo->nvars + 1) + 2; exp_bound1 = n_randint(state, 25/ctx->minfo->nvars + 1) + 2; exp_bound2 = n_randint(state, 20/ctx->minfo->nvars + 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); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-evaluate.c000066400000000000000000000160741414523752600211710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j, v; int tmul = 20; FLINT_TEST_INIT(state); flint_printf("evaluate...."); fflush(stdout); /* 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); SLONG_SWAP(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); 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); 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); 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); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-gcd_brown.c000066400000000000000000000130621414523752600213210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; slong tmul = 5; slong max_threads = 6; FLINT_TEST_INIT(state); flint_printf("gcd_brown...."); fflush(stdout); 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/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 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); degbound = 1 + 60/ctx->minfo->nvars/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"); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-gcd_cofactors.c000066400000000000000000001043241414523752600221570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); } int main(void) { const slong max_threads = 5; slong i, j, k, tmul = 2; fmpz_t p; FLINT_TEST_INIT(state); flint_printf("gcd_cofactors...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-gcd_hensel.c000066400000000000000000000122511414523752600214470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_hensel...."); fflush(stdout); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-gcd_subresultant.c000066400000000000000000000100701414523752600227210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; slong tmul = 10; FLINT_TEST_INIT(state); flint_printf("gcd_subresultant...."); fflush(stdout); 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/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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-gcd_zippel.c000066400000000000000000000117141414523752600214770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_zippel...."); fflush(stdout); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-gcd_zippel2.c000066400000000000000000000117171414523752600215640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_zippel2...."); fflush(stdout); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-get_coeff_vars_ui.c000066400000000000000000000124531414523752600230310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j1, j2; FLINT_TEST_INIT(state); flint_printf("get_coeff_vars_ui...."); fflush(stdout); { 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"); 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); 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); 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; again: 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); goto again; } 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-get_set_coeff_fmpz_fmpz.c000066400000000000000000000045401414523752600242420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("get_set_coeff_fmpz_fmpz...."); fflush(stdout); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-get_set_coeff_fmpz_monomial.c000066400000000000000000000074631414523752600251100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("get_set_coeff_fmpz_monomial...."); fflush(stdout); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-get_set_coeff_fmpz_ui.c000066400000000000000000000037461414523752600237120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("get_set_coeff_fmpz_ui...."); fflush(stdout); 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 = (ulong *) flint_malloc(ctx->minfo->nvars*sizeof(ulong)); fmpz_randtest_unsigned(c, state, 200); for (k = 0; k < fmpz_mod_mpoly_ctx_nvars(ctx); 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); flint_abort(); } flint_free(exp); } fmpz_mod_mpoly_clear(f, ctx); fmpz_clear(c); fmpz_clear(d); fmpz_mod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-get_set_is_fmpz.c000066400000000000000000000040751414523752600225420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("get_set_is_fmpz...."); fflush(stdout); /* 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"); 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"); 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"); flint_abort(); } fmpz_clear(c); fmpz_clear(d); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-get_set_term_coeff_fmpz.c000066400000000000000000000042751414523752600242420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("get_set_term_coeff_fmpz...."); fflush(stdout); /* 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); 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); flint_abort(); } } } fmpz_mod_mpoly_clear(f, ctx); fmpz_clear(c); fmpz_clear(d); fmpz_mod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-get_set_term_exp_fmpz.c000066400000000000000000000056001414523752600237450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get_set_term_exp_fmpz...."); fflush(stdout); 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-get_set_term_exp_si.c000066400000000000000000000053271414523752600234120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get_set_term_exp_si...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-get_set_term_exp_ui.c000066400000000000000000000053131414523752600234070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get_set_term_exp_ui...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-get_term.c000066400000000000000000000041561414523752600211670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("get_term...."); fflush(stdout); /* 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-get_term_monomial.c000066400000000000000000000050241414523752600230550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("get_term_monomial...."); fflush(stdout); /* 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-mul.c000066400000000000000000000130721414523752600201530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j, max_threads = 5; slong tmul = 10; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); 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); 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, nvars; flint_bitcnt_t exp_bound, exp_bound1, exp_bound2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 4, 200); nvars = 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/nvars/nvars); exp_bound1 = 3 + n_randint(state, 1 + 100/nvars/nvars); exp_bound2 = 3 + n_randint(state, 1 + 100/nvars/nvars); len = exp_bound + 1; len1 = exp_bound1 + 1; len2 = exp_bound2 + 1; for (j = n_randint(state, nvars) + 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-mul_dense.c000066400000000000000000000134201414523752600213260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("mul_dense...."); fflush(stdout); /* 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-mul_johnson.c000066400000000000000000000131721414523752600217120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j, max_threads = 5; slong tmul = 10; FLINT_TEST_INIT(state); flint_printf("mul_johnson...."); fflush(stdout); 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); 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, nvars; flint_bitcnt_t exp_bound, exp_bound1, exp_bound2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 4, 200); nvars = 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/nvars/nvars); exp_bound1 = 3 + n_randint(state, 1 + 100/nvars/nvars); exp_bound2 = 3 + n_randint(state, 1 + 100/nvars/nvars); len = exp_bound + 1; len1 = exp_bound1 + 1; len2 = exp_bound2 + 1; for (j = n_randint(state, nvars) + 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-print_parse.c000066400000000000000000000033301414523752600217000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("get_set_str_pretty...."); fflush(stdout); { 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"); flint_abort(); } } fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_clear(f1, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-push_term_fmpz_fmpz.c000066400000000000000000000075601414523752600234610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("push_term_fmpz_fmpz...."); fflush(stdout); /* 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; fmpz ** 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 = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); exp2 = (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]); } 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); /* 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 */ fmpz_mod_mpoly_push_term_fmpz_fmpz(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_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); 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); 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 pushed polynomial matches add\n"); flint_printf("i = %wd\n", i); 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); for (k = 0; k < nvars; k++) { fmpz_clear(exp2[k]); flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(exp2); flint_free(exp); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-push_term_fmpz_ui.c000066400000000000000000000066141414523752600231210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("push_term_fmpz_ui...."); fflush(stdout); /* 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-quadratic_root.c000066400000000000000000000067171414523752600224060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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"); 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"); 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"); 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"); flint_abort(); } fmpz_mod_mpoly_clear(s, ctx); fmpz_mod_mpoly_clear(t, ctx); } int main(void) { slong i, j, tmul = 20; FLINT_TEST_INIT(state); flint_printf("quadratic_root...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-resultant_discriminant.c000066400000000000000000000207471414523752600241520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("resultant_discriminant...."); fflush(stdout); /* 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"); flint_abort(); } if (!fmpz_mod_mpoly_equal(d, d1, ctx)) { flint_printf("FAIL: Check quadratic polynomial\n"); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-scalar_addmul_fmpz.c000066400000000000000000000074701414523752600232120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("scalar_addmul_fmpz...."); fflush(stdout); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-scalar_mul_fmpz.c000066400000000000000000000071561414523752600225420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpz...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-sqrt.c000066400000000000000000000126461414523752600203550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("sqrt...."); fflush(stdout); /* 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"); 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); 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); flint_abort(); } } else if (!fmpz_mod_mpoly_is_zero(g, ctx)) { flint_printf("FAIL: Check nonsquare returns 0 sqrt\n"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-total_degree.c000066400000000000000000000117321414523752600220150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("total_degree...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-univar_resultant.c000066400000000000000000000134601414523752600227640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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"); 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); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("univar_resultant...."); fflush(stdout); { 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"); 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"); 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"); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/test/t-used_vars.c000066400000000000000000000043201414523752600213450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("used_vars...."); fflush(stdout); 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"); flint_abort(); } } } flint_free(used); fmpz_clear(one); fmpz_clear(fdeg); fmpz_mod_mpoly_clear(f, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly/to_from_nmod_poly.c000066400000000000000000000071741414523752600216710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly/univar.c000066400000000000000000000443401414523752600174440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } SLONG_SWAP(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; } flint2-2.8.4/fmpz_mod_mpoly/void_ring.c000066400000000000000000000075301414523752600201200ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_mod_mpoly_factor.h000066400000000000000000001322141414523752600175010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define FMPZ_MOD_MPOLY_FACTOR_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "n_poly.h" #include "nmod_mpoly_factor.h" #include "fmpz_mod_mpoly.h" #ifdef __cplusplus extern "C" { #endif /* type definitions **********************************************************/ 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]; 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; } FLINT_DLL void fmpz_mod_mpoly_factor_init2(fmpz_mod_mpoly_factor_t f, slong alloc, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_factor_realloc(fmpz_mod_mpoly_factor_t f, slong alloc, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_factor_fit_length(fmpz_mod_mpoly_factor_t f, slong len, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL 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); FLINT_DLL void fmpz_mod_mpoly_factor_print_pretty(const fmpz_mod_mpoly_factor_t f, const char ** vars, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int fmpz_mod_mpoly_factor(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpoly_factor_sort(fmpz_mod_mpoly_factor_t f, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 *******************************************************/ FLINT_DLL int fmpz_mod_mat_is_reduced(const fmpz_mod_mat_t N); FLINT_DLL 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]; /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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; } FLINT_DLL void _fmpz_mod_mpoly_get_lead0( fmpz_mod_mpoly_t c, const fmpz_mod_mpoly_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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]; FLINT_DLL void fmpz_mod_poly_stack_init(fmpz_mod_poly_stack_t S); FLINT_DLL void fmpz_mod_poly_stack_clear(fmpz_mod_poly_stack_t S); FLINT_DLL 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; } FLINT_DLL void fmpz_mod_bpoly_stack_init(fmpz_mod_bpoly_stack_t S); FLINT_DLL void fmpz_mod_bpoly_stack_clear(fmpz_mod_bpoly_stack_t S); FLINT_DLL 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; } FLINT_DLL void fmpz_mod_polyun_stack_init(fmpz_mod_polyun_stack_t S); FLINT_DLL void fmpz_mod_polyun_stack_clear(fmpz_mod_polyun_stack_t S); FLINT_DLL 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; } FLINT_DLL void fmpz_mod_mpolyn_stack_init(fmpz_mod_mpolyn_stack_t S, flint_bitcnt_t bits, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpolyn_stack_clear(fmpz_mod_mpolyn_stack_t S, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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 ******************************************************************/ FLINT_DLL slong _fmpz_mod_poly_vec_max_degree(const fmpz_mod_poly_struct * A, slong Alen, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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; } FLINT_DLL 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; } FLINT_DLL void fmpz_mod_polyun_clear(fmpz_mod_polyun_t A, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_polyun_realloc(fmpz_mod_polyun_t A, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int fmpz_mod_polyun_equal(fmpz_mod_polyun_t A, const fmpz_mod_polyun_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_polyun_set(fmpz_mod_polyun_t A, const fmpz_mod_polyun_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); } FLINT_DLL void fmpz_mod_polyun_one(fmpz_mod_polyun_t A, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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 ********************************************************************/ FLINT_DLL 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; } FLINT_DLL 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; } FLINT_DLL int fmpz_mod_mpolyn_is_canonical(const fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL slong fmpz_mod_mpolyn_lastdeg(const fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpolyn_clear(fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpolyn_one(fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpolyn_scalar_mul_fmpz_mod(fmpz_mod_mpolyn_t A, const fmpz_t c, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mod_mpolyn_equal(const fmpz_mod_mpolyn_t A, const fmpz_mod_mpolyn_t B, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpolyn_print_pretty(const fmpz_mod_mpolyn_t poly, const char ** x, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mod_mpolyn_set( fmpz_mod_mpolyn_t A, const fmpz_mod_mpolyn_t B, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mod_mpolyn_is_nonzero_fmpz( const fmpz_mod_mpolyn_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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 ********************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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; } FLINT_DLL void fmpz_mod_polyu_init(fmpz_mod_polyu_t A); FLINT_DLL void fmpz_mod_polyu_clear(fmpz_mod_polyu_t A); FLINT_DLL 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); } FLINT_DLL void fmpz_mod_polyu3_degrees( slong * deg0, slong * deg1, slong * deg2, const fmpz_mod_polyu_t A); FLINT_DLL 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 ********************************************************************/ FLINT_DLL int fmpz_mod_mpolyu_is_canonical(const fmpz_mod_mpolyu_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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 *********************************************************************/ FLINT_DLL 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; } FLINT_DLL 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--; } FLINT_DLL int fmpz_mod_bpoly_equal( const fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_bpoly_set( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_bpoly_set_poly_gen1( fmpz_mod_bpoly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_bpoly_set_poly_gen0( fmpz_mod_bpoly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL slong fmpz_mod_bpoly_degree1(const fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_bpoly_print_pretty(const fmpz_mod_bpoly_t A, const char * xvar, const char * yvar, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_bpoly_fit_length(fmpz_mod_bpoly_t A, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fmpz_mod_bpoly_zero(fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_bpoly_reverse_vars(fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mod_bpoly_make_primitive( fmpz_mod_poly_t g, fmpz_mod_bpoly_t A, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mod_bpoly_taylor_shift_gen0( fmpz_mod_bpoly_t A, const fmpz_t alpha, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_bpoly_derivative_gen0( fmpz_mod_bpoly_t A, const fmpz_mod_bpoly_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL void fmpz_mod_tpoly_fit_length(fmpz_mod_tpoly_t A, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_tpoly_clear(fmpz_mod_tpoly_t A, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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; } FLINT_DLL void fmpz_mod_mpolyv_clear(fmpz_mod_mpolyv_t A, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpolyv_print_pretty(const fmpz_mod_mpolyv_t poly, const char ** x, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mod_mpolyv_fit_length(fmpz_mod_mpolyv_t A, slong length, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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]; FLINT_DLL 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); FLINT_DLL void fmpz_mod_mpoly_pfrac_clear(fmpz_mod_mpoly_pfrac_t I, const fmpz_mod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ***********************************************************************/ FLINT_DLL 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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_DLL 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); FLINT_DLL 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 */ FLINT_DLL void fmpz_mod_pow_cache_start(const fmpz_t b, fmpz_mod_poly_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL 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 */ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL slong fmpz_mod_polyun_product_roots( fmpz_mod_polyun_t M, const fmpz_mod_polyun_t H, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 flint2-2.8.4/fmpz_mod_mpoly_factor/000077500000000000000000000000001414523752600173255ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_mpoly_factor/bpoly_factor_smprime.c000066400000000000000000001251231414523752600237140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.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); SLONG_SWAP(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); SLONG_SWAP(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); 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)); FLINT_ASSERT(fmpz_mod_mat_is_reduced(N)); /* 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); fmpz_mod_mat_init(N, L->r, L->r, fmpz_mod_ctx_modulus(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); 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, fmpz_mod_ctx_modulus(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->mat->rows[i], r, ctx); } fmpz_mod_mat_init_nullspace_tr(T1, M, ctx); fmpz_mod_mat_init(T2, fmpz_mod_mat_nrows(T1), fmpz_mod_mat_ncols(N), fmpz_mod_ctx_modulus(ctx)); fmpz_mod_mat_mul(T2, T1, N); fmpz_mod_mat_swap(T2, N); fmpz_mod_mat_rref(NULL, N); fmpz_mod_mat_clear(M); fmpz_mod_mat_clear(T1); fmpz_mod_mat_clear(T2); } _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); 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)); FLINT_ASSERT(fmpz_mod_mat_is_reduced(N)); FLINT_ASSERT(fmpz_mod_mat_ncols(N) == 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, fmpz_mod_ctx_modulus(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 */ local_fac_tmp->num = 0; 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); fmpz_mod_mat_init(N, r, r, fmpz_mod_ctx_modulus(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) < 2) goto irreducible_shift; if (!fmpz_mod_mat_is_reduced(N)) goto increase; if (fmpz_mod_mat_nrows(N) < fmpz_mod_mat_ncols(N)/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)); while (fmpz_mod_mat_nrows(N) > 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) < 2) goto irreducible_shift; if (!fmpz_mod_mat_is_reduced(N)) goto increase; if (fmpz_mod_mat_nrows(N) < fmpz_mod_mat_ncols(N)/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) < 2) goto irreducible_shift; if (!fmpz_mod_mat_is_reduced(N)) goto increase; if (fmpz_mod_mat_nrows(N) < fmpz_mod_mat_ncols(N)/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); 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; } flint2-2.8.4/fmpz_mod_mpoly_factor/bpoly_hlift.c000066400000000000000000000264601414523752600220140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly_factor/clear.c000066400000000000000000000014611414523752600205610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpz_mod_mpoly_factor/cmp.c000066400000000000000000000017621414523752600202560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpz_mod_mpoly_factor/compression.c000066400000000000000000000062161414523752600220370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_mpoly_factor/eval.c000066400000000000000000000142101414523752600204160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly_factor/expand.c000066400000000000000000000020241414523752600207460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpz_mod_mpoly_factor/factor.c000066400000000000000000000512411414523752600207520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" #include "long_extras.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); } flint2-2.8.4/fmpz_mod_mpoly_factor/factor_content.c000066400000000000000000000123321414523752600225020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 primitve 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--) SLONG_SWAP(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; } flint2-2.8.4/fmpz_mod_mpoly_factor/factor_squarefree.c000066400000000000000000000117501414523752600231750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" #include "nmod_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); } flint2-2.8.4/fmpz_mod_mpoly_factor/fit_length.c000066400000000000000000000013721414523752600216170ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fmpz_mod_mpoly_factor/fmpz_mod_bpoly.c000066400000000000000000000510751414523752600225210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.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_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_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); } flint2-2.8.4/fmpz_mod_mpoly_factor/fmpz_mod_mat_extras.c000066400000000000000000000044211414523752600235340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" int fmpz_mod_mat_is_reduced(const fmpz_mod_mat_t N) { slong i, j, k = 0; slong r = fmpz_mod_mat_ncols(N); slong d = fmpz_mod_mat_nrows(N); 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); n = fmpz_mod_mat_ncols(tmp); p = FLINT_ARRAY_ALLOC(FLINT_MAX(m, n), slong); rank = fmpz_mod_mat_rref(NULL, tmp); nullity = n - rank; fmpz_mod_mat_init(X, nullity, n, fmpz_mod_ctx_modulus(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); } flint2-2.8.4/fmpz_mod_mpoly_factor/fmpz_mod_poly_extras.c000066400000000000000000000113001414523752600237300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" #include "fmpz_mod_mpoly.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); } flint2-2.8.4/fmpz_mod_mpoly_factor/fmpz_mod_poly_vec.c000066400000000000000000000047351414523752600232150ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_mod_mpoly_factor/fmpz_mod_pow_cache.c000066400000000000000000000026431414523752600233210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly_factor/gcd_algo.c000066400000000000000000001575711414523752600212500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" #include "fmpz_mod_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); } flint2-2.8.4/fmpz_mod_mpoly_factor/gcd_brown.c000066400000000000000000000602541414523752600214440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly_factor/gcd_hensel.c000066400000000000000000000302011414523752600215600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly_factor/gcd_zippel.c000066400000000000000000000661241414523752600216220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.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->mat->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, fmpz_mod_ctx_modulus(ctx->ffinfo)); fmpz_mod_mat_init(MF, 0, l, fmpz_mod_ctx_modulus(ctx->ffinfo)); fmpz_mod_mat_init(Msol, l, 1, fmpz_mod_ctx_modulus(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); fmpz_mod_mat_init(Msol, 1, l, fmpz_mod_ctx_modulus(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); fmpz_mod_mat_init(Msol, 0, l, fmpz_mod_ctx_modulus(ctx->ffinfo)); fmpz_mod_mat_clear(MF); fmpz_mod_mat_init(MF, 0, l, fmpz_mod_ctx_modulus(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) != l || fmpz_mod_mat_ncols(ML + s) != l + n) { fmpz_mod_mat_clear(ML + s); fmpz_mod_mat_init(ML + s, l, l + n, fmpz_mod_ctx_modulus(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(NULL, ML + s); 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); while (i > 1 && _fmpz_vec_is_zero(fmpz_mod_mat_row_ref(MF, i - 1), l)) i--; if (i < fmpz_mod_mat_nrows(MF)) { fmpz_mod_mat_window_init(Mwindow, MF, 0, 0, i, l); fmpz_mod_mat_init(MFtemp, i, l, fmpz_mod_ctx_modulus(ctx->ffinfo)); fmpz_mod_mat_set(MFtemp, Mwindow); fmpz_mod_mat_swap(MF, MFtemp); fmpz_mod_mat_clear(MFtemp); fmpz_mod_mat_window_clear(Mwindow); } /* appends rows to MF */ fmpz_mod_mat_window_init(Mwindow, ML + s, n, n, l, n + l); fmpz_mod_mat_init(MFtemp, i + l - n, l, fmpz_mod_ctx_modulus(ctx->ffinfo)); fmpz_mod_mat_concat_vertical(MFtemp, MF, Mwindow); fmpz_mod_mat_swap(MF, MFtemp); fmpz_mod_mat_clear(MFtemp); fmpz_mod_mat_window_clear(Mwindow); fmpz_mod_mat_clear(Msol); fmpz_mod_mat_init_nullspace_tr(Msol, MF, ctx->ffinfo); if (fmpz_mod_mat_nrows(Msol) < 1) { success = 0; goto cleanup; } if (fmpz_mod_mat_nrows(Msol) == 1) break; } if (fmpz_mod_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++) { _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); flint_free(ML); fmpz_mod_mat_clear(MF); fmpz_mod_mat_clear(Msol); 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--) SLONG_SWAP(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; } flint2-2.8.4/fmpz_mod_mpoly_factor/gcd_zippel2.c000066400000000000000000001302061414523752600216750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" #include "fmpz_mod_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; } flint2-2.8.4/fmpz_mod_mpoly_factor/get_set_lead0.c000066400000000000000000000023241414523752600221710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpz_mod_mpoly_factor/interp.c000066400000000000000000001062331414523752600207770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly_factor/irred_smprime_wang.c000066400000000000000000000223261414523752600233530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly_factor/irred_smprime_zassenhaus.c000066400000000000000000000263261414523752600246070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly_factor/irred_smprime_zippel.c000066400000000000000000000232041414523752600237160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly_factor/lcc_wang.c000066400000000000000000000107451414523752600212550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "n_poly.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; } flint2-2.8.4/fmpz_mod_mpoly_factor/mpoly_hlift.c000066400000000000000000000336321414523752600220260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpz_mod_mpoly_factor/mpoly_hlift_zippel.c000066400000000000000000000663661414523752600234230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_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_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_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_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 comming 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); ULONG_SWAP(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; } flint2-2.8.4/fmpz_mod_mpoly_factor/mpoly_pfrac.c000066400000000000000000000233321414523752600220070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpz_mod_mpoly_factor/mpolyn.c000066400000000000000000000302741414523752600210150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_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; } 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); } flint2-2.8.4/fmpz_mod_mpoly_factor/mpolyn_divides.c000066400000000000000000000170311414523752600225200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" #include "long_extras.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; } flint2-2.8.4/fmpz_mod_mpoly_factor/mpolyu.c000066400000000000000000000073211414523752600210210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly.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)); } flint2-2.8.4/fmpz_mod_mpoly_factor/mpolyv.c000066400000000000000000000107071414523752600210240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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_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); } flint2-2.8.4/fmpz_mod_mpoly_factor/polyu3_mod_hlift.c000066400000000000000000000531341414523752600227570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); ULONG_SWAP(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; } flint2-2.8.4/fmpz_mod_mpoly_factor/polyun.c000066400000000000000000000147171414523752600210310ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" #include "mpn_extras.h" #include "fmpz_vec.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; } 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"); } 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_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_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)); } flint2-2.8.4/fmpz_mod_mpoly_factor/print_pretty.c000066400000000000000000000014351414523752600222370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" 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); } } flint2-2.8.4/fmpz_mod_mpoly_factor/realloc.c000066400000000000000000000032771414523752600211230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpz_mod_mpoly_factor/set_nmod_mpoly_factor.c000066400000000000000000000016141414523752600240610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fmpz_mod_mpoly_factor/sort.c000066400000000000000000000034501414523752600204620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_mpoly_factor/stack.c000066400000000000000000000113341414523752600206000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpz_mod_mpoly_factor/test/000077500000000000000000000000001414523752600203045ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_mpoly_factor/test/t-factor.c000066400000000000000000000117011414523752600221670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" /* 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, const char * s) { 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 (!fmpz_mod_mpoly_factor(g, p, ctx)) { flint_printf("FAIL: %s\ncheck factorization could be computed\n", s); 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: %s\nfactorization is not unit normal\n", s); 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: %s\nfactorization has wrong number of factors\n", s); flint_abort(); } fmpz_mod_mpoly_factor_expand(q, g, ctx); if (!fmpz_mod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL: %s\nfactorization does not match\n", s); 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: %s\nfactor is reducible\n", s); 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); } int main(void) { slong i, j, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor...."); fflush(stdout); 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, "bivariate"); 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 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); nfacs = 1 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 3 + 100/nfacs/ctx->minfo->nvars/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, "multivariate"); fmpz_mod_mpoly_clear(t, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly_factor/test/t-factor_squarefree.c000066400000000000000000000067501414523752600244210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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"); 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"); 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"); 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"); 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); } int main(void) { slong i, j, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_squarefree...."); fflush(stdout); for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; fmpz_mod_mpoly_t a, t; slong 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); nfacs = 1 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); expbound = 3 + 25/nfacs/ctx->minfo->nvars/powbound; fmpz_mod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 80/powbound/ctx->minfo->nvars); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly_factor/test/t-factor_wang.c000066400000000000000000000077011414523752600232100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" /* 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) { 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 (!fmpz_mod_mpoly_factor_wang(g, p, ctx)) { flint_printf("FAIL:\nfactorization 1 could be computed\n"); flint_abort(); } if (!fmpz_mod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\nfactorization 2 could be computed\n"); 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"); 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"); 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"); flint_abort(); } 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"); 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"); 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); } int main(void) { slong i, j, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_wang...."); fflush(stdout); 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; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 7, 100); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(t, ctx); nfacs = 1 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 3 + 20/nfacs/ctx->minfo->nvars/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_clear(t, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly_factor/test/t-factor_zassenhaus.c000066400000000000000000000076701414523752600244450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" /* 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) { 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 (!fmpz_mod_mpoly_factor_zassenhaus(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization 1 could be computed\n"); flint_abort(); } if (!fmpz_mod_mpoly_factor(h, p, ctx)) { flint_printf("check factorization 2 could be computed\n"); 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"); 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"); 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"); flint_abort(); } 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("factorizations do not match\n"); 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"); 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); } int main(void) { slong i, j, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_zassenhaus...."); fflush(stdout); 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; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 5, 200); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(t, ctx); nfacs = 1 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 3 + 15/nfacs/ctx->minfo->nvars/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_clear(t, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly_factor/test/t-factor_zippel.c000066400000000000000000000076711414523752600235650ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" /* 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) { 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 (!fmpz_mod_mpoly_factor_zippel(g, p, ctx)) { flint_printf("FAIL:\nfactorization could be computed\n"); flint_abort(); } if (!fmpz_mod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\nfactorization 2 could be computed\n"); 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"); 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"); 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"); flint_abort(); } 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"); 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"); 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); } int main(void) { slong i, j, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_zippel...."); fflush(stdout); 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; fmpz_mod_mpoly_ctx_init_rand_bits_prime(ctx, state, 10, 200); fmpz_mod_mpoly_init(a, ctx); fmpz_mod_mpoly_init(t, ctx); nfacs = 1 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 2 + 80/nfacs/ctx->minfo->nvars/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_clear(t, ctx); fmpz_mod_mpoly_clear(a, ctx); fmpz_mod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_mpoly_factor/test/t-gcd_brown.c000066400000000000000000000160571414523752600226660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" 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; } 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 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(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); 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); 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); 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); 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); flint_abort(); } res = compute_gcd(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); 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); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 5; FLINT_TEST_INIT(state); flint_printf("gcd_brown...."); fflush(stdout); 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, 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); degbound = 1 + 50/ctx->minfo->nvars/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"); } 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly_factor/test/t-gcd_hensel.c000066400000000000000000000201611414523752600230040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" 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"); 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; } 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 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(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); 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); 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); 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); 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); flint_abort(); } res = compute_gcd(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); 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); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("gcd_hensel...."); fflush(stdout); 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"); } 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly_factor/test/t-gcd_subresultant.c000066400000000000000000000166071414523752600242730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" 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; } 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 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(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); 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); 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); 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); 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); flint_abort(); } res = compute_gcd(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); 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); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("gcd_subresultant...."); fflush(stdout); 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, 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"); } 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly_factor/test/t-gcd_zippel.c000066400000000000000000000366501414523752600230430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" 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"); 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; } 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 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(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); 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); 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); 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); 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); flint_abort(); } res = compute_gcd(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); 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); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("gcd_zippel...."); fflush(stdout); { 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"); 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"); 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"); 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"); } 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly_factor/test/t-gcd_zippel2.c000066400000000000000000000367461414523752600231330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" 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"); 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; } 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 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(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); 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); 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); 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); 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); flint_abort(); } res = compute_gcd(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); 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); flint_abort(); } cleanup: fmpz_mod_mpoly_clear(ca, ctx); fmpz_mod_mpoly_clear(cb, ctx); fmpz_mod_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("gcd_zippel2...."); fflush(stdout); { 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"); 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"); 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"); } 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mod_mpoly_factor/zip_helpers.c000066400000000000000000000212771414523752600220260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_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); } } flint2-2.8.4/fmpz_mod_poly.h000066400000000000000000001650651414523752600160000ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPZ_MOD_POLY_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod.h" #include "fmpz_mat.h" #include "fmpz_mod_mat.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 */ /* Type definitions *********************************************************/ 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_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; } FLINT_DLL void fmpz_mod_poly_init2(fmpz_mod_poly_t poly, slong alloc, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_clear(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_realloc(fmpz_mod_poly_t poly, slong alloc, const fmpz_mod_ctx_t ctx); FLINT_DLL 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; } FMPZ_MOD_POLY_INLINE 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; } FMPZ_MOD_POLY_INLINE 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_DLL 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); FLINT_DLL int fmpz_mod_poly_is_canonical(const fmpz_mod_poly_t A, const fmpz_mod_ctx_t ctx); /* Randomisation ************************************************************/ FLINT_DLL void fmpz_mod_poly_randtest(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_randtest_irreducible(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_randtest_not_zero(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_randtest_monic(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_randtest_monic_irreducible(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_randtest_monic_primitive(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_randtest_trinomial(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fmpz_mod_poly_randtest_pentomial(fmpz_mod_poly_t f, flint_rand_t state, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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_degree(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { return poly->length - 1; } 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 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 && fmpz_is_one(f->coeffs + f->length - 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 && fmpz_is_one(poly->coeffs + 0); } 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)); } /* Deprecated */ #define fmpz_mod_poly_is_x fmpz_mod_poly_is_gen /* Assignment and basic manipulation ****************************************/ FLINT_DLL 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) { fmpz_mod_poly_struct t = *poly2; *poly2 = *poly1; *poly1 = t; } FLINT_DLL void _fmpz_mod_poly_reverse(fmpz * res, const fmpz * poly, slong len, slong n); FLINT_DLL 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); } FMPZ_MOD_POLY_INLINE 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_DLL void fmpz_mod_poly_gen(fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_zero_coeffs(fmpz_mod_poly_t poly, slong i, slong j, const fmpz_mod_ctx_t ctx); /* Conversion ***************************************************************/ FMPZ_MOD_POLY_INLINE 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_DLL void fmpz_mod_poly_set_fmpz(fmpz_mod_poly_t poly, const fmpz_t c, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_set_fmpz_poly(fmpz_mod_poly_t f, const fmpz_poly_t g, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_get_fmpz_poly(fmpz_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_get_nmod_poly(nmod_poly_t f, const fmpz_mod_poly_t g); FLINT_DLL void fmpz_mod_poly_set_nmod_poly(fmpz_mod_poly_t f, const nmod_poly_t g); /* Comparison ***************************************************************/ FMPZ_MOD_POLY_INLINE 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); } FMPZ_MOD_POLY_INLINE 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); } FMPZ_MOD_POLY_INLINE int fmpz_mod_poly_is_zero(const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) { return poly->length == 0; } /* Getting and setting coefficients *****************************************/ FLINT_DLL void fmpz_mod_poly_set_coeff_fmpz(fmpz_mod_poly_t poly, slong n, const fmpz_t x, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_set_coeff_ui(fmpz_mod_poly_t poly, slong n, ulong x, const fmpz_mod_ctx_t ctx); FLINT_DLL 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_INLINE 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); } FMPZ_MOD_POLY_INLINE void fmpz_mod_poly_set_coeff_mpz(fmpz_mod_poly_t poly, slong n, const mpz_t x, const fmpz_mod_ctx_t ctx) { fmpz_t t; fmpz_init_set_readonly(t, x); fmpz_mod_poly_set_coeff_fmpz(poly, n, t, ctx); fmpz_clear_readonly(t); } FMPZ_MOD_POLY_INLINE void fmpz_mod_poly_get_coeff_mpz(mpz_t x, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx) { fmpz_t t; fmpz_init(t); fmpz_mod_poly_get_coeff_fmpz(t, poly, n, ctx); fmpz_get_mpz(x, t); fmpz_clear(t); } /* Shifting *****************************************************************/ FLINT_DLL void _fmpz_mod_poly_shift_left(fmpz * res, const fmpz * poly, slong len, slong n); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_shift_right(fmpz * res, const fmpz * poly, slong len, slong n); FLINT_DLL 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 *************************************************/ FLINT_DLL void _fmpz_mod_poly_add(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_sub(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_neg(fmpz *res, const fmpz *poly, slong len, const fmpz_t p); FLINT_DLL 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); FLINT_DLL void fmpz_mod_poly_neg(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); /* Scalar multiplication ****************************************************/ FLINT_DLL void _fmpz_mod_poly_scalar_mul_fmpz(fmpz *res, const fmpz *poly, slong len, const fmpz_t x, const fmpz_t p); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_scalar_mul_ui(fmpz *res, const fmpz *poly, slong len, ulong x, const fmpz_t p); FLINT_DLL 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); /* Scalar division ****************************************************/ FLINT_DLL void _fmpz_mod_poly_scalar_div_fmpz(fmpz *res, const fmpz *poly, slong len, const fmpz_t x, const fmpz_t p); FLINT_DLL 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 ***********************************************************/ FLINT_DLL void _fmpz_mod_poly_mul(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_mullow(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p, slong n); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_sqr(fmpz *res, const fmpz *poly, slong len, const fmpz_t p); FLINT_DLL void fmpz_mod_poly_sqr(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_poly_mulmod(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz * f, slong lenf, const fmpz_t p); FLINT_DLL 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); FLINT_DLL 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_t p); FLINT_DLL 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 *****************************************************************/ FLINT_DLL void _fmpz_mod_poly_pow(fmpz *rop, const fmpz *op, slong len, ulong e, const fmpz_t p); FLINT_DLL void fmpz_mod_poly_pow(fmpz_mod_poly_t rop, const fmpz_mod_poly_t op, ulong e, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_poly_pow_trunc(fmpz * res, const fmpz * poly, ulong e, slong trunc, const fmpz_t p); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_pow_trunc_binexp(fmpz * res, const fmpz * poly, ulong e, slong trunc, const fmpz_t p); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_powmod_ui_binexp(fmpz * res, const fmpz * poly, ulong e, const fmpz * f, slong lenf, const fmpz_t p); FLINT_DLL 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); FLINT_DLL 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_t p); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_powmod_fmpz_binexp(fmpz * res, const fmpz * poly, const fmpz_t e, const fmpz * f, slong lenf, const fmpz_t p); FLINT_DLL 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); FLINT_DLL 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_t p); FLINT_DLL 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); FLINT_DLL 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_t p); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_t p); FLINT_DLL 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); FLINT_DLL 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_t p, thread_pool_handle * threads, slong num_threads); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mod_poly_frobenius_powers_2exp_clear( fmpz_mod_poly_frobenius_powers_2exp_t pow, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mod_poly_frobenius_powers_clear( fmpz_mod_poly_frobenius_powers_t pow, const fmpz_mod_ctx_t ctx); /* Division *****************************************************************/ FLINT_DLL 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_t p); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_div_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_t p); FLINT_DLL void fmpz_mod_poly_div_basecase(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL 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_t mod); FLINT_DLL 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); FLINT_DLL 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_t mod); FLINT_DLL 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); FLINT_DLL ulong fmpz_mod_poly_remove(fmpz_mod_poly_t f, const fmpz_mod_poly_t p, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_poly_rem_basecase(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_t p); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_divrem_divconquer_recursive(fmpz * Q, fmpz * BQ, fmpz * W, const fmpz * A, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_t p); FLINT_DLL void _fmpz_mod_poly_divrem_divconquer(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_t p); FLINT_DLL void fmpz_mod_poly_divrem_divconquer(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); FMPZ_MOD_POLY_INLINE 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_t p) { if (lenB < 8) _fmpz_mod_poly_divrem_basecase(Q, R, A, lenA, B, lenB, invB, p); else _fmpz_mod_poly_divrem_divconquer(Q, R, A, lenA, B, lenB, invB, p); } FMPZ_MOD_POLY_INLINE 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) { fmpz_mod_poly_divrem_divconquer(Q, R, A, B, ctx); } FLINT_DLL 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_t p); FLINT_DLL 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); FMPZ_MOD_POLY_INLINE void _fmpz_mod_poly_rem(fmpz *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p) { fmpz *Q = _fmpz_vec_init(lenA - lenB + 1); fmpz *T = _fmpz_vec_init(lenA); if (lenA < lenB) { _fmpz_vec_set(R, A, lenA); _fmpz_vec_zero(R + lenA, lenB - 1 - lenA); } else { _fmpz_mod_poly_divrem_divconquer(Q, T, A, lenA, B, lenB, invB, p); _fmpz_vec_set(R, T, lenB - 1); } _fmpz_vec_clear(T, lenA); _fmpz_vec_clear(Q, lenA - lenB + 1); } FMPZ_MOD_POLY_INLINE 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); } FMPZ_MOD_POLY_INLINE void _fmpz_mod_poly_div(fmpz *Q, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p) { fmpz * R = (fmpz *) _fmpz_vec_init(lenA); _fmpz_mod_poly_divrem(Q, R, A, lenA, B, lenB, invB, p); _fmpz_vec_clear(R, lenA); } FMPZ_MOD_POLY_INLINE 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) { fmpz_mod_poly_t R; fmpz_mod_poly_init(R, ctx); fmpz_mod_poly_divrem(Q, R, A, B, ctx); fmpz_mod_poly_clear(R, ctx); } FMPZ_MOD_POLY_INLINE 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); } /* Divisibility testing ******************************************************/ FLINT_DLL int _fmpz_mod_poly_divides_classical(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_poly_divides_classical(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, fmpz_mod_ctx_t ctx); FLINT_DLL int _fmpz_mod_poly_divides(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_poly_divides(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, fmpz_mod_ctx_t ctx); /* Power series inversion ***************************************************/ FLINT_DLL void _fmpz_mod_poly_inv_series_newton(fmpz * Qinv, const fmpz * Q, slong n, const fmpz_t cinv, const fmpz_t p); FLINT_DLL void fmpz_mod_poly_inv_series_newton(fmpz_mod_poly_t Qinv, const fmpz_mod_poly_t Q, slong n, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_inv_series_newton_f(fmpz_t f, fmpz_mod_poly_t Qinv, const fmpz_mod_poly_t Q, slong n, const fmpz_mod_ctx_t ctx); FMPZ_MOD_POLY_INLINE void _fmpz_mod_poly_inv_series(fmpz * Qinv, const fmpz * Q, slong n, const fmpz_t cinv, const fmpz_t p) { _fmpz_mod_poly_inv_series_newton(Qinv, Q, n, cinv, p); } FMPZ_MOD_POLY_INLINE 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) { fmpz_mod_poly_inv_series_newton(Qinv, Q, n, ctx); } FMPZ_MOD_POLY_INLINE 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) { fmpz_mod_poly_inv_series_newton_f(f, Qinv, Q, n, ctx); } /* Power series division ***************************************************/ FLINT_DLL void _fmpz_mod_poly_div_series(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, const fmpz_t p, slong n); FLINT_DLL 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 **************************************************/ FLINT_DLL void fmpz_mod_poly_make_monic(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL slong _fmpz_mod_poly_gcd_euclidean(fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p); FLINT_DLL void fmpz_mod_poly_gcd_euclidean(fmpz_mod_poly_t G, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL slong _fmpz_mod_poly_gcd_euclidean_f(fmpz_t f, fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t p); FLINT_DLL 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_t p) { return _fmpz_mod_poly_gcd_euclidean_f(f, G, A, lenA, B, lenB, p); } 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); } FLINT_DLL slong _fmpz_mod_poly_hgcd_recursive(fmpz **M, slong *lenM, fmpz *A, slong *lenA, fmpz *B, slong *lenB, const fmpz *a, slong lena, const fmpz *b, slong lenb, fmpz *P, const fmpz_t mod, int flag, fmpz_mod_poly_res_t res); FLINT_DLL 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_t mod); FLINT_DLL slong _fmpz_mod_poly_gcd_hgcd(fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t mod); FLINT_DLL void fmpz_mod_poly_gcd_hgcd(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(fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p) { if (FLINT_MIN(lenA, lenB) < FMPZ_MOD_POLY_GCD_CUTOFF) return _fmpz_mod_poly_gcd_euclidean(G, A, lenA, B, lenB, invB, p); else return _fmpz_mod_poly_gcd_hgcd(G, A, lenA, B, lenB, p); } FMPZ_MOD_POLY_INLINE 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 (FLINT_MIN(A->length, B->length) < FMPZ_MOD_POLY_GCD_CUTOFF) fmpz_mod_poly_gcd_euclidean(G, A, B, ctx); else fmpz_mod_poly_gcd_hgcd(G, A, B, ctx); } FLINT_DLL slong _fmpz_mod_poly_xgcd_euclidean(fmpz *G, fmpz *S, fmpz *T, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p); FLINT_DLL 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_t p); FLINT_DLL void fmpz_mod_poly_xgcd_euclidean(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); FLINT_DLL 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); FLINT_DLL slong _fmpz_mod_poly_xgcd_hgcd(fmpz *G, fmpz *S, fmpz *T, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t mod); FLINT_DLL void fmpz_mod_poly_xgcd_hgcd(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(fmpz *G, fmpz *S, fmpz *T, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p) { if (FLINT_MIN(lenA, lenB) < FMPZ_MOD_POLY_GCD_CUTOFF) return _fmpz_mod_poly_xgcd_euclidean(G, S, T, A, lenA, B, lenB, invB, p); else return _fmpz_mod_poly_xgcd_hgcd(G, S, T, A, lenA, B, lenB, p); } 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_t p) { return _fmpz_mod_poly_xgcd_euclidean_f(f, G, S, T, A, lenA, B, lenB, invB, p); } FMPZ_MOD_POLY_INLINE 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 (FLINT_MIN(A->length, B->length) < FMPZ_MOD_POLY_GCD_CUTOFF) fmpz_mod_poly_xgcd_euclidean(G, S, T, A, B, ctx); else fmpz_mod_poly_xgcd_hgcd(G, S, T, A, B, 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); } FLINT_DLL 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_t p); FLINT_DLL 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); FLINT_DLL 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_t p); FLINT_DLL 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); FLINT_DLL slong _fmpz_mod_poly_gcdinv(fmpz *G, fmpz *S, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t p); FLINT_DLL 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); FLINT_DLL 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_t p); FLINT_DLL 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); FLINT_DLL int _fmpz_mod_poly_invmod(fmpz *A, const fmpz *B, slong lenB, const fmpz *P, slong lenP, const fmpz_t p); FLINT_DLL int _fmpz_mod_poly_invmod_f(fmpz_t f, fmpz *A, const fmpz *B, slong lenB, const fmpz *P, slong lenP, const fmpz_t p); FLINT_DLL 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); FLINT_DLL 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); /* Minpoly *****************************************************************/ FLINT_DLL slong _fmpz_mod_poly_minpoly_bm(fmpz* poly, const fmpz* seq, slong len, const fmpz_t p); FMPZ_MOD_POLY_INLINE 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, fmpz_mod_ctx_modulus(ctx)); } FLINT_DLL slong _fmpz_mod_poly_minpoly_hgcd(fmpz* poly, const fmpz* seq, slong len, const fmpz_t p); FMPZ_MOD_POLY_INLINE 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, fmpz_mod_ctx_modulus(ctx)); } FMPZ_MOD_POLY_INLINE slong _fmpz_mod_poly_minpoly(fmpz* poly, const fmpz* seq, slong len, const fmpz_t p) { if (len < FLINT_MAX(200, 530-22*fmpz_size(p))) { return _fmpz_mod_poly_minpoly_bm(poly, seq, len, p); } else return _fmpz_mod_poly_minpoly_hgcd(poly, seq, len, p); } FMPZ_MOD_POLY_INLINE 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, fmpz_mod_ctx_modulus(ctx)); } /* Resultant ***************************************************************/ FLINT_DLL void _fmpz_mod_poly_resultant_euclidean(fmpz_t res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t mod); FLINT_DLL void fmpz_mod_poly_resultant_euclidean(fmpz_t r, const fmpz_mod_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_poly_resultant_hgcd(fmpz_t res, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t mod); FLINT_DLL void fmpz_mod_poly_resultant_hgcd(fmpz_t res, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx); FMPZ_MOD_POLY_INLINE void _fmpz_mod_poly_resultant(fmpz_t res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t mod) { if (len1 < FMPZ_MOD_POLY_GCD_CUTOFF) _fmpz_mod_poly_resultant_euclidean(res, poly1, len1, poly2, len2, mod); else _fmpz_mod_poly_resultant_hgcd(res, poly1, len1, poly2, len2, mod); } FMPZ_MOD_POLY_INLINE 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) { if (FLINT_MAX(f->length, g->length) < FMPZ_MOD_POLY_GCD_CUTOFF) fmpz_mod_poly_resultant_euclidean(res, f, g, ctx); else fmpz_mod_poly_resultant_hgcd(res, f, g, ctx); } /* Discriminant ************************************************************/ FLINT_DLL void _fmpz_mod_poly_discriminant(fmpz_t d, const fmpz *poly, slong len, const fmpz_t mod); FLINT_DLL void fmpz_mod_poly_discriminant(fmpz_t d, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); /* Derivative **************************************************************/ FLINT_DLL void _fmpz_mod_poly_derivative(fmpz *res, const fmpz *poly, slong len, const fmpz_t p); FLINT_DLL void fmpz_mod_poly_derivative(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); /* Evaluation **************************************************************/ FLINT_DLL void _fmpz_mod_poly_evaluate_fmpz(fmpz_t res, const fmpz *poly, slong len, const fmpz_t a, const fmpz_t p); FLINT_DLL 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); FLINT_DLL fmpz_poly_struct ** _fmpz_mod_poly_tree_alloc(slong len); FLINT_DLL void _fmpz_mod_poly_tree_free(fmpz_poly_struct ** tree, slong len); FLINT_DLL void _fmpz_mod_poly_tree_build(fmpz_poly_struct ** tree, const fmpz * roots, slong len, const fmpz_t mod); FLINT_DLL void _fmpz_mod_poly_evaluate_fmpz_vec_iter(fmpz * ys, const fmpz * coeffs, slong len, const fmpz * xs, slong n, const fmpz_t mod); FLINT_DLL 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); FLINT_DLL 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_t mod); FLINT_DLL void _fmpz_mod_poly_evaluate_fmpz_vec_fast(fmpz * ys, const fmpz * poly, slong plen, const fmpz * xs, slong n, const fmpz_t mod); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_evaluate_fmpz_vec(fmpz * ys, const fmpz * coeffs, slong len, const fmpz * xs, slong n, const fmpz_t mod); FLINT_DLL 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 *************************************************************/ FLINT_DLL void _fmpz_mod_poly_compose_horner(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p); FLINT_DLL void fmpz_mod_poly_compose_horner(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_poly_compose_divconquer(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p); FLINT_DLL void fmpz_mod_poly_compose_divconquer(fmpz_mod_poly_t res, const 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_compose(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p) { _fmpz_mod_poly_compose_divconquer(res, poly1, len1, poly2, len2, p); } FMPZ_MOD_POLY_INLINE 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) { fmpz_mod_poly_compose_divconquer(res, poly1, poly2, ctx); } /* Modular composition ******************************************************/ FLINT_DLL void _fmpz_mod_poly_compose_mod(fmpz * res, const fmpz * f, slong lenf, const fmpz * g, const fmpz * h, slong lenh, const fmpz_t p); FLINT_DLL 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); FLINT_DLL 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_t p); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_t p); FLINT_DLL void _fmpz_mod_poly_precompute_matrix_worker(void * arg_ptr); FLINT_DLL 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); FLINT_DLL 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_t p); FLINT_DLL void _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker(void * arg_ptr); FLINT_DLL 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); FLINT_DLL 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_t p); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_poly_compose_mod_horner(fmpz * res, const fmpz * f, slong lenf, const fmpz * g, const fmpz * h, slong lenh, const fmpz_t p); FLINT_DLL 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); FLINT_DLL 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_t p); FLINT_DLL 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); FLINT_DLL 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_t p, thread_pool_handle * threads, slong num_threads); FLINT_DLL 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); FLINT_DLL 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); /* 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]; FLINT_DLL void _fmpz_mod_poly_radix_init(fmpz **Rpow, fmpz **Rinv, const fmpz *R, slong lenR, slong k, const fmpz_t invL, const fmpz_t p); FLINT_DLL 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); FLINT_DLL void fmpz_mod_poly_radix_clear(fmpz_mod_poly_radix_t D); FLINT_DLL void _fmpz_mod_poly_radix(fmpz **B, const fmpz *F, fmpz **Rpow, fmpz **Rinv, slong degR, slong k, slong i, fmpz *W, const fmpz_t p); FLINT_DLL 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 *********************************************************/ FLINT_DLL int _fmpz_mod_poly_fprint(FILE * file, const fmpz *poly, slong len, const fmpz_t p); FLINT_DLL int fmpz_mod_poly_fprint(FILE * file, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_poly_fread(FILE * file, fmpz_mod_poly_t poly, fmpz_mod_ctx_t ctx); FMPZ_MOD_POLY_INLINE 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); } FMPZ_MOD_POLY_INLINE int _fmpz_mod_poly_print(const fmpz *poly, slong len, const fmpz_t p) { return _fmpz_mod_poly_fprint(stdout, poly, len, p); } FMPZ_MOD_POLY_INLINE 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); } FMPZ_MOD_POLY_INLINE 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); } /* Products *****************************************************************/ FLINT_DLL void _fmpz_mod_poly_product_roots_fmpz_vec(fmpz * poly, const fmpz * xs, slong n, const fmpz_t mod); FLINT_DLL void fmpz_mod_poly_product_roots_fmpz_vec(fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_poly_find_distinct_nonzero_roots(fmpz * roots, const fmpz_mod_poly_t P, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); /* 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]; FLINT_DLL void fmpz_mod_berlekamp_massey_init( fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_berlekamp_massey_start_over( fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_berlekamp_massey_clear(fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_berlekamp_massey_print( const fmpz_mod_berlekamp_massey_t B, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_berlekamp_massey_add_points( fmpz_mod_berlekamp_massey_t B, const fmpz * a, slong count, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_berlekamp_massey_add_zeros( fmpz_mod_berlekamp_massey_t B, slong count, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_berlekamp_massey_add_point( fmpz_mod_berlekamp_massey_t B, const fmpz_t a, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_berlekamp_massey_add_point_ui( fmpz_mod_berlekamp_massey_t B, ulong a, const fmpz_mod_ctx_t ctx); FLINT_DLL 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 *******************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); #ifdef __cplusplus } #endif #include "fmpz_mod_poly_factor.h" #endif flint2-2.8.4/fmpz_mod_poly/000077500000000000000000000000001414523752600156125ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_poly/add.c000066400000000000000000000025551414523752600165150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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_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); } } 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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, max); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/add_series.c000066400000000000000000000023161414523752600200620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, max); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/berlekamp_massey.c000066400000000000000000000200631414523752600213020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" /* 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; } flint2-2.8.4/fmpz_mod_poly/clear.c000066400000000000000000000014071414523752600170460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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 */ } flint2-2.8.4/fmpz_mod_poly/compose_divconquer.c000066400000000000000000000107511414523752600216660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_mod_poly.h" /* Let i be such that 2^{i} < len1 <= 2^{i+1}. Note that the jth step of the recursion requires temporary space of size no more than (len2 - 1)(2^j - 1) + 1. Note the smallest step j=0 doesn't require any temporary space and the largest step has j = i, and hence the sum is sum_{j=1}^i [(len2 - 1) (2^j - 1) + 1] = (len2 - 1)(2^{i+1} - 2) - (len2 - 2) i */ void _fmpz_mod_poly_compose_divconquer_recursive(fmpz *res, const fmpz *poly1, slong len1, fmpz **pow2, slong len2, fmpz *v, const fmpz_t p) { if (len1 == 1) { fmpz_set(res, poly1); } else if (len1 == 2) { _fmpz_mod_poly_scalar_mul_fmpz(res, pow2[0], len2, poly1 + 1, p); fmpz_add(res, res, poly1); if (fmpz_cmpabs(res, p) >= 0) fmpz_sub(res, res, p); } else { const slong i = FLINT_BIT_COUNT(len1 - 1) - 1; fmpz *w = v + ((WORD(1) << i) - 1) * (len2 - 1) + 1; _fmpz_mod_poly_compose_divconquer_recursive(v, poly1 + (WORD(1) << i), len1 - (WORD(1) << i), pow2, len2, w, p); _fmpz_mod_poly_mul(res, pow2[i], (len2 - 1) * (WORD(1) << i) + 1, v, (len2 - 1) * (len1 - (WORD(1) << i) - 1) + 1, p); _fmpz_mod_poly_compose_divconquer_recursive(v, poly1, WORD(1) << i, pow2, len2, w, p); _fmpz_mod_poly_add(res, res, (len2 - 1) * ((WORD(1) << i) - 1) + 1, v, (len2 - 1) * ((WORD(1) << i) - 1) + 1, p); } } void _fmpz_mod_poly_compose_divconquer(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p) { if (len1 == 1 || len2 == 0) { fmpz_set(res, poly1); } else { const slong k = FLINT_BIT_COUNT(len1 - 1); const slong lenV = len2 * ((WORD(1) << k) - 1) + k; const slong lenW = (len2 - 1) * ((WORD(1) << k) - 2) - (len2 - 2) * (k-1); slong i; fmpz *v, *w, **pow2; v = _fmpz_vec_init(lenV + lenW); w = v + lenV; pow2 = flint_malloc(k * sizeof(fmpz *)); for (i = 0; i < k; i++) { pow2[i] = v + (len2 * ((WORD(1) << i) - 1) + i); } _fmpz_vec_set(pow2[0], poly2, len2); for (i = 1; i < k; i++) { _fmpz_mod_poly_sqr(pow2[i], pow2[i-1], (len2 - 1) * (WORD(1) << (i - 1)) + 1, p); } _fmpz_mod_poly_compose_divconquer_recursive(res, poly1, len1, pow2, len2, w, p); _fmpz_vec_clear(v, lenV + lenW); flint_free(pow2); } } void fmpz_mod_poly_compose_divconquer(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_divconquer(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, fmpz_mod_ctx_modulus(ctx)); } else { fmpz *t = _fmpz_vec_init(lenr); _fmpz_mod_poly_compose_divconquer(t, poly1->coeffs, len1, poly2->coeffs, len2, fmpz_mod_ctx_modulus(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); } } flint2-2.8.4/fmpz_mod_poly/compose_horner.c000066400000000000000000000053601414523752600210040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_compose_horner(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p) { if (len1 == 1 || len2 == 0) { fmpz_set(res, poly1); } else { const slong alloc = (len1 - 1) * (len2 - 1) + 1; slong i = len1 - 1, lenr = len2; fmpz * t = _fmpz_vec_init(alloc); /* Perform the first two steps as one, "res = a(m) * poly2 + a(m-1)". */ { _fmpz_mod_poly_scalar_mul_fmpz(res, poly2, len2, poly1 + i, p); i--; fmpz_add(res, res, poly1 + i); if (fmpz_cmpabs(res, p) >= 0) fmpz_sub(res, res, p); } while (i > 0) { i--; _fmpz_mod_poly_mul(t, res, lenr, poly2, len2, p); lenr += len2 - 1; _fmpz_mod_poly_add(res, t, lenr, poly1 + i, 1, p); } _fmpz_vec_clear(t, alloc); } } void fmpz_mod_poly_compose_horner(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_horner(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, fmpz_mod_ctx_modulus(ctx)); } else { fmpz *t = _fmpz_vec_init(lenr); _fmpz_mod_poly_compose_horner(t, poly1->coeffs, len1, poly2->coeffs, len2, fmpz_mod_ctx_modulus(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); } } flint2-2.8.4/fmpz_mod_poly/compose_mod.c000066400000000000000000000052611414523752600202660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" void _fmpz_mod_poly_compose_mod(fmpz * res, const fmpz * f, slong lenf, const fmpz * g, const fmpz * h, slong lenh, const fmpz_t p) { if (lenh < 12 || lenf >= lenh) _fmpz_mod_poly_compose_mod_horner(res, f, lenf, g, h, lenh, p); else _fmpz_mod_poly_compose_mod_brent_kung(res, f, lenf, g, h, lenh, p); } 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_printf("Exception (fmpz_mod_poly_compose_mod)." "Division by zero.\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_normalise(res); _fmpz_vec_clear(ptr2, vec_len); } flint2-2.8.4/fmpz_mod_poly/compose_mod_brent_kung.c000066400000000000000000000107371414523752600225100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "fmpz_mat.h" #include "ulong_extras.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_t p) { fmpz_mat_t A, B, C; fmpz * t, * h, * tmp; slong i, j, 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, p); 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, p); _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++) for (j = 0; j < n; j++) fmpz_mod(C->rows[i] + j, C->rows[i] + j, p); /* 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, p); for (i = m - 2; i >= 0; i--) { _fmpz_mod_poly_mulmod(t, res, n, h, n, poly3, len3, p); _fmpz_mod_poly_add(res, t, n, C->rows[i], n, p); } _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_printf("Exception (fmpz_mod_poly_compose_mod_brent_kung)." "Division by zero in\n"); flint_abort(); } if (len1 >= len3) { flint_printf("Exception (fmpz_mod_poly_compose_brent_kung). the degree of the" " first polynomial must be smaller than that of the modulus\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_normalise(res); _fmpz_vec_clear(ptr2, vec_len); } flint2-2.8.4/fmpz_mod_poly/compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000151431414523752600256140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "fmpz_mat.h" #include "ulong_extras.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, fmpz_mod_ctx_modulus(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_t p) { /* 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, p); } 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_printf("Exception (fmpz_mod_poly_precompute_matrix)." "Division by zero.\n"); flint_abort(); } if (A->r != m || A->c != len) { flint_printf("Exception (fmpz_mod_poly_precompute_matrix)." " Wrong dimensions.\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(ctx)); fmpz_clear(inv2); } _fmpz_mod_poly_precompute_matrix (A, ptr, poly2->coeffs, len2, poly2inv->coeffs, poly2inv->length, fmpz_mod_ctx_modulus(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_t p) { fmpz_mat_t B, C; fmpz * t, * h; slong i, j, 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], p); 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++) for (j = 0; j < n; j++) fmpz_mod(C->rows[i] + j, C->rows[i] + j, p); /* 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, p); for (i = m - 2; i >= 0; i--) { _fmpz_mod_poly_mulmod_preinv(t, res, n, h, n, poly3, len3, poly3inv, len3inv, p); _fmpz_mod_poly_add(res, t, n, C->rows[i], n, p); } _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_printf("Exception (fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv)." "Division by zero\n"); flint_abort(); } if (len1 >= len3) { flint_printf("Exception (fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv)." "The degree of the first polynomial must be smaller than that of the " " modulus\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/compose_mod_brent_kung_preinv.c000066400000000000000000000112421414523752600240630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "fmpz_mat.h" #include "ulong_extras.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_t p) { fmpz_mat_t A, B, C; fmpz * t, * h; slong i, j, 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, p); 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, p); fmpz_mat_mul(C, B, A); for (i = 0; i < m; i++) for (j = 0; j < n; j++) fmpz_mod(C->rows[i] + j, C->rows[i] + j, p); /* 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, p); for (i = m - 2; i >= 0; i--) { _fmpz_mod_poly_mulmod_preinv(t, res, n, h, n, poly3, len3, poly3inv, len3inv, p); _fmpz_mod_poly_add(res, t, n, C->rows[i], n, p); } _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_printf("Exception (fmpz_mod_poly_compose_mod_brent_kung preinv)." "Division by zero\n"); flint_abort(); } if (len1 >= len3) { flint_printf("Exception (fmpz_mod_poly_compose_mod_brent_kung_preinv)." "The degree of the first polynomial must be smaller than that of the " " modulus\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_normalise(res); _fmpz_vec_clear(ptr2, len); } flint2-2.8.4/fmpz_mod_poly/compose_mod_brent_kung_vec_preinv.c000066400000000000000000000123031414523752600247170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "fmpz_mat.h" #include "ulong_extras.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_t p) { 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, p); fmpz_mat_mul(C, B, A); for (i = 0; i < k * len2; i++) for (j = 0; j < n; j++) fmpz_mod(C->rows[i] + j, C->rows[i] + j, p); /* Evaluate block composition using the Horner scheme */ if (n == 1) { fmpz_mul(h + 0, A->rows[m - 1] + 0, A->rows[1] + 0); fmpz_mod(h + 0, h + 0, p); } else { _fmpz_mod_poly_mulmod_preinv(h, A->rows[m - 1], n, A->rows[1], n, poly, len, polyinv, leninv, p); } 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_mul(t + 0, res[j].coeffs + 0, h + 0); fmpz_add(res[j].coeffs + 0, t + 0, C->rows[(j + 1)*k - i] + 0); fmpz_mod(res[j].coeffs + 0, res[j].coeffs + 0, p); } } else { for (i = 2; i <= k; i++) { _fmpz_mod_poly_mulmod_preinv(t, res[j].coeffs, n, h, n, poly, len, polyinv, leninv, p); _fmpz_mod_poly_add(res[j].coeffs, t, n, C->rows[(j + 1)*k - i], n, p); } } } _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_printf ("Exception (fmpz_mod_poly_compose_mod_brent_kung_vec_preinv)." "The degree of the first polynomial must be smaller than that of the " " modulus\n"); flint_abort(); } } if (n > len1) { flint_printf ("Exception (fmpz_mod_poly_compose_mod_brent_kung_vec_preinv)." "n is larger than the length of polys\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(ctx)); for (i = 0; i < n; i++) _fmpz_mod_poly_normalise(res + i); } flint2-2.8.4/fmpz_mod_poly/compose_mod_brent_kung_vec_preinv_threaded.c000066400000000000000000000246501414523752600265670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_mat.h" #include "ulong_extras.h" #include "thread_support.h" typedef struct { fmpz_mod_poly_struct * res; fmpz_mod_mat_struct * C; const fmpz * h; const fmpz * poly; const fmpz * polyinv; const fmpz * p; 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->mat; const fmpz * 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; _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_mul(t + 0, res[j].coeffs + 0, h + 0); fmpz_add(res[j].coeffs + 0, t + 0, C->rows[(j + 1)*k - i] + 0); fmpz_mod(res[j].coeffs + 0, res[j].coeffs + 0, p); } } else { for (i = 2; i <= k; i++) { _fmpz_mod_poly_mulmod_preinv(t, res[j].coeffs, n, h, n, poly, len, polyinv, leninv, p); _fmpz_mod_poly_add(res[j].coeffs, t, n, C->rows[(j + 1)*k - i], n, p); } } } } 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_t p, 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, p); fmpz_mod_mat_init(B, k*len2, m, p); fmpz_mod_mat_init(C, k*len2, n, p); /* 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->mat->rows[i + j*k], polys[j].coeffs + i*m, m); _fmpz_vec_set(B->mat->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->mat->rows, g, glen, m, poly, len, polyinv, leninv, p, threads, num_threads); _fmpz_mod_mat_mul_classical_threaded_pool_op(C, NULL, B, A, 0, threads, num_threads); /* Evaluate block composition using the Horner scheme */ if (n == 1) { fmpz_mul(h + 0, A->mat->rows[m - 1] + 0, A->mat->rows[1] + 0); fmpz_mod(h + 0, h + 0, p); } else { _fmpz_mod_poly_mulmod_preinv(h, A->mat->rows[m - 1], n, A->mat->rows[1], n, poly, len, polyinv, leninv, p); } 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].p = p; 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); fmpz_mod_mat_clear(B); fmpz_mod_mat_clear(C); } 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, fmpz_mod_ctx_modulus(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_printf ("Exception (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"); flint_abort(); } } if (n > len1) { flint_printf ("Exception (fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded)." "n is larger than the length of polys\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(ctx), threads, num_threads); flint_give_back_threads(threads, num_threads); for (i = 0; i < n; i++) _fmpz_mod_poly_normalise(res + i); } flint2-2.8.4/fmpz_mod_poly/compose_mod_horner.c000066400000000000000000000062441414523752600216450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.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_t p) { 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, p); 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, p); i--; if (i >= 0) { fmpz_add(res, res, f + i); fmpz_mod(res, res, p); } while (i > 0) { i--; _fmpz_mod_poly_mulmod(t, res, len, g, len, h, lenh, p); _fmpz_mod_poly_add(res, t, len, f + i, 1, p); } _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_printf("Exception (fmpz_mod_poly_compose_mod_horner). Division by zero \n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, len); _fmpz_mod_poly_normalise(res); _fmpz_vec_clear(ptr2, vec_len); } flint2-2.8.4/fmpz_mod_poly/derivative.c000066400000000000000000000030431414523752600201200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_derivative(fmpz *res, const fmpz *poly, slong len, const fmpz_t p) { 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_mul_ui(res + (j - 1), poly + j, k); fmpz_mod(res + (j - 1), res + (j - 1), p); } if (fmpz_equal_ui(p, ++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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, len - 1); _fmpz_mod_poly_normalise(res); } } flint2-2.8.4/fmpz_mod_poly/discriminant.c000066400000000000000000000031321414523752600204410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_discriminant(fmpz_t d, const fmpz *poly, slong len, const fmpz_t mod) { fmpz *der = _fmpz_vec_init(len - 1); slong dlen = len - 1, exp; fmpz_t pow; _fmpz_mod_poly_derivative(der, poly, len, mod); FMPZ_VEC_NORM(der, dlen); if (dlen == 0) { fmpz_zero(d); } else { fmpz_init(pow); _fmpz_mod_poly_resultant(d, poly, len, der, dlen, mod); exp = len - dlen - 2; if (exp >= 0) fmpz_powm_ui(pow, poly + len - 1, exp, mod); else fmpz_invmod(pow, poly + len - 1, mod); fmpz_mul(d, d, pow); fmpz_mod(d, d, mod); if ((len & 3) == 0 || (len & 3) == 3) /* degree is not 0, 1 mod 4 */ fmpz_negmod(d, d, mod); 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, fmpz_mod_ctx_modulus(ctx)); } flint2-2.8.4/fmpz_mod_poly/div_basecase.c000066400000000000000000000053461414523752600203760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_div_basecase(fmpz *Q, fmpz *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p) { const slong alloc = (R == NULL) ? lenA : 0; slong lenR = lenB - 1, iQ; TMP_INIT; TMP_START; if (alloc) FMPZ_VEC_TMP_INIT(R, alloc); if (R != A) _fmpz_vec_set(R + lenR, A + lenR, lenA - lenR); for (iQ = lenA - lenB; iQ >= 0; iQ--) { if (fmpz_is_zero(R + lenA - 1)) { fmpz_zero(Q + iQ); } else { fmpz_mul(Q + iQ, R + lenA - 1, invB); fmpz_mod(Q + iQ, Q + iQ, p); _fmpz_vec_scalar_submul_fmpz(R + lenA - lenR - 1, B, lenR, Q + iQ); } if (iQ > 0) fmpz_mod(R + lenA - 2, R + lenA - 2, p); if (lenR - 1 >= iQ) { B++; lenR--; } lenA--; } if (alloc) FMPZ_VEC_TMP_CLEAR(R, alloc); TMP_END; } void fmpz_mod_poly_div_basecase(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_printf("Exception (fmpz_mod_poly_div_basecase). Division by zero.\n"); flint_abort(); } } 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_basecase(q, NULL, A->coeffs, lenA, B->coeffs, lenB, invB, fmpz_mod_ctx_modulus(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); } flint2-2.8.4/fmpz_mod_poly/div_newton_n_preinv.c000066400000000000000000000052261414523752600220370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "fmpz_vec.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_t mod) { 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), mod, lenQ); _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_printf("Exception (fmpz_mod_poly_div_newton_n_preinv). Division by zero.\n"); flint_abort(); } } if (lenA < lenB) { fmpz_mod_poly_zero(Q, ctx); return; } if (lenA > 2 * lenB - 2) { flint_printf("Exception (fmpz_mod_poly_div_newton_n_preinv).\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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); } } flint2-2.8.4/fmpz_mod_poly/div_series.c000066400000000000000000000070721414523752600201200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_div_series(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, const fmpz_t p, slong n) { fmpz_t u, d; fmpz_init(d); fmpz_init(u); if (!fmpz_is_one(B + 0)) { fmpz_gcdinv(d, u, B + 0, p); if (!fmpz_is_one(d)) /* check for invertibility */ { printf("Exception (fmpz_mod_poly_div_series). Impossible inverse."); fmpz_clear(u); fmpz_clear(d); flint_abort(); } } else fmpz_set_ui(u, 1); 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, p); _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_mul(Q + 0, u, A + 0); fmpz_mod(Q + 0, Q + 0, p); } 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(Q + i, Q + i, p); } } else { fmpz * B2, * Binv = _fmpz_vec_init(n); if (n > Blen) { B2 = _fmpz_vec_init(n); _fmpz_vec_set(B2, B, Blen); } else B2 = (fmpz *) B; _fmpz_mod_poly_inv_series(Binv, B2, n, u, p); _fmpz_mod_poly_mullow(Q, Binv, n, A, Alen, p, n); _fmpz_vec_clear(Binv, n); if (n > Blen) _fmpz_vec_clear(B2, n); } 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_printf("Exception (fmpz_mod_poly_div_series). Division by zero.\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(ctx), n); 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, fmpz_mod_ctx_modulus(ctx), n); } _fmpz_mod_poly_set_length(Q, n); _fmpz_mod_poly_normalise(Q); } flint2-2.8.4/fmpz_mod_poly/divides.c000066400000000000000000000061671414523752600174170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" int _fmpz_mod_poly_divides(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, 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, p); while (offset < lenB - 1) { if (offset + 2*lenQ - 1 < lenB) { _fmpz_mod_poly_mul(P, B + offset, lenQ, Q, lenQ, p); _fmpz_mod_poly_add(R + offset, R + offset, 2*lenQ - 1, P, 2*lenQ - 1, p); } else { _fmpz_mod_poly_mullow(P, Q, lenQ, B + offset, lenQ, p, lenB - offset - 1); _fmpz_mod_poly_add(R + offset, R + offset, lenB - offset - 1, P, lenB - offset - 1, p); } 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, p); 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, 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; } flint2-2.8.4/fmpz_mod_poly/divides_classical.c000066400000000000000000000060231414523752600214240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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, 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, fmpz_mod_ctx_t ctx) { slong lenQ = lenA - lenB + 1; fmpz * W; int res; fmpz_t invB; W = _fmpz_vec_init(lenA); fmpz_init(invB); fmpz_invmod(invB, B + lenB - 1, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_div_basecase(Q, W, A, lenA, B, lenB, invB, fmpz_mod_ctx_modulus(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); _fmpz_vec_clear(W, lenA); 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, 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; } flint2-2.8.4/fmpz_mod_poly/divrem_basecase.c000066400000000000000000000063631414523752600211020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_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_t p) { 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(Q + iQ, Q + iQ, p); _fmpz_vec_scalar_submul_fmpz(W + iQ, B, lenB, Q + iQ); } if (iQ > 0) fmpz_mod(W + iR - 1, W + iR - 1, p); } _fmpz_vec_scalar_mod_fmpz(W, W, lenB - 1, p); 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_printf("Exception (fmpz_mod_poly_divrem_basecase). Division by zero.\n"); flint_abort(); } } 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, fmpz_mod_ctx_modulus(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); } flint2-2.8.4/fmpz_mod_poly/divrem_divconquer.c000066400000000000000000000124571414523752600215140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" static void __fmpz_mod_poly_divrem_divconquer(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_t p) { 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); _fmpz_mod_poly_divrem_divconquer_recursive(Q, d1q1, W, p1, d1, n1, invB, p); /* Compute d2q1 = Q d2, of length lenB - 1 */ if (n1 >= n2) _fmpz_mod_poly_mul(d2q1, Q, n1, d2, n2, p); else _fmpz_mod_poly_mul(d2q1, d2, n2, Q, n1, p); /* Compute BQ = d1q1 * x^n1 + d2q1, of length lenB - 1; then compute R = A - BQ */ _fmpz_vec_swap(R, d2q1, n2); _fmpz_mod_poly_add(R + n2, R + n2, n1 - 1, d2q1 + n2, n1 - 1, p); _fmpz_mod_poly_sub(R, A, lenA, R, lenA, p); _fmpz_vec_clear(W, (2 * n1 - 1) + lenB - 1); } else /* lenA = 2 * lenB - 1 */ { fmpz * W = _fmpz_vec_init(lenA); _fmpz_mod_poly_divrem_divconquer_recursive(Q, R, W, A, B, lenB, invB, p); _fmpz_mod_poly_sub(R, A, lenB - 1, R, lenB - 1, p); _fmpz_vec_clear(W, lenA); } } void _fmpz_mod_poly_divrem_divconquer(fmpz *Q, fmpz *R, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p) { if (lenA <= 2 * lenB - 1) { fmpz * W = _fmpz_vec_init(lenA); __fmpz_mod_poly_divrem_divconquer(Q, W, A, lenA, B, lenB, invB, p); _fmpz_vec_set(R, W, lenB - 1); _fmpz_vec_clear(W, lenA); } else /* lenA > 2 * lenB - 1 */ { slong shift, n = 2 * lenB - 1, len1; fmpz *QB, *W, *S; len1 = 2 * n + lenA; W = _fmpz_vec_init(len1); S = W + 2*n; _fmpz_vec_set(S, A, lenA); QB = W + n; while (lenA >= n) { shift = lenA - n; _fmpz_mod_poly_divrem_divconquer_recursive(Q + shift, QB, W, S + shift, B, lenB, invB, p); _fmpz_mod_poly_sub(S + shift, S + shift, n, QB, n, p); lenA -= lenB; } if (lenA >= lenB) { __fmpz_mod_poly_divrem_divconquer(Q, W, S, lenA, B, lenB, invB, p); _fmpz_vec_swap(W, S, lenA); } _fmpz_vec_set(R, S, lenB - 1); _fmpz_vec_clear(W, len1); } } void fmpz_mod_poly_divrem_divconquer(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_printf("Exception (fmpz_mod_poly_div_basecase). Division by zero.\n"); flint_abort(); } } 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_divconquer(q, r, A->coeffs, lenA, B->coeffs, lenB, invB, fmpz_mod_ctx_modulus(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); } flint2-2.8.4/fmpz_mod_poly/divrem_divconquer_recursive.c000066400000000000000000000072661414523752600236050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #define FMPZ_MOD_POLY_DIVREM_DIVCONQUER_CUTOFF 16 void _fmpz_mod_poly_divrem_divconquer_recursive(fmpz * Q, fmpz * BQ, fmpz * W, const fmpz * A, const fmpz * B, slong lenB, const fmpz_t invB, const fmpz_t p) { if (lenB <= FMPZ_MOD_POLY_DIVREM_DIVCONQUER_CUTOFF) { _fmpz_vec_zero(BQ, lenB - 1); _fmpz_vec_set(BQ + (lenB - 1), A + (lenB - 1), lenB); _fmpz_mod_poly_divrem_basecase(Q, BQ, BQ, 2 * lenB - 1, B, lenB, invB, p); _fmpz_mod_poly_neg(BQ, BQ, lenB - 1, p); _fmpz_vec_set(BQ + (lenB - 1), A + (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 */ _fmpz_mod_poly_divrem_divconquer_recursive(q1, d1q1, W1, p1, d1, n1, invB, p); /* Compute d2q1 = d2 q1, of length lenB - 1 */ d2q1 = W1; _fmpz_mod_poly_mul(d2q1, q1, n1, d2, n2, p); /* Compute dq1 = d1 q1 x^n2 + d2 q1, of length 2 n1 + n2 - 1 */ _fmpz_vec_swap(dq1, d2q1, n2); _fmpz_mod_poly_add(dq1 + n2, dq1 + n2, n1 - 1, d2q1 + n2, n1 - 1, p); /* 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_mod_poly_sub(t, A + n2 + (n1 - 1), n2, dq1 + (n1 - 1), n2, p); 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; _fmpz_mod_poly_divrem_divconquer_recursive(q2, d3q2, W2, p2, d3, n2, invB, p); /* Compute d4q2 = d4 q2, of length n1 + n2 - 1 = lenB - 1 */ d4q2 = W2; _fmpz_mod_poly_mul(d4q2, d4, n1, q2, n2, p); /* Compute dq2 = d3q2 x^n1 + d4q2, of length n1 + 2 n2 - 1 */ _fmpz_vec_swap(BQ, d4q2, n2); _fmpz_mod_poly_add(BQ + n2, BQ + n2, n1 - 1, d4q2 + n2, n1 - 1, p); _fmpz_mod_poly_add(BQ + n1, BQ + n1, 2 * n2 - 1, d3q2, 2 * n2 - 1, p); /* Note Q = q1 x^n2 + q2, and BQ = dq1 x^n2 + dq2 */ } } flint2-2.8.4/fmpz_mod_poly/divrem_f.c000066400000000000000000000051751414523752600175610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_vec.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_t p) { fmpz_t invB; fmpz_init(invB); fmpz_gcdinv(f, invB, B + lenB - 1, p); if (fmpz_is_one(f)) { _fmpz_mod_poly_divrem(Q, R, A, lenA, B, lenB, invB, p); } 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_printf("Exception (fmpz_mod_poly_divrem_f). Division by zero.\n"); flint_abort(); } 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_divconquer(q, r, A->coeffs, lenA, B->coeffs, lenB, invB, fmpz_mod_ctx_modulus(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); } flint2-2.8.4/fmpz_mod_poly/divrem_newton_n_preinv.c000066400000000000000000000065111414523752600225410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "fmpz_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_t mod) { const slong lenQ = lenA - lenB + 1; _fmpz_mod_poly_div_newton_n_preinv(Q, A, lenA, B, lenB, Binv, lenBinv, mod); if (lenB > 1) { if (lenQ >= lenB - 1) _fmpz_mod_poly_mullow(R, Q, lenQ, B, lenB - 1, mod, lenB - 1); else _fmpz_mod_poly_mullow(R, B, lenB - 1, Q, lenQ, mod, lenB - 1); _fmpz_vec_sub(R, A, R, lenB - 1); _fmpz_vec_scalar_mod_fmpz(R, R, lenB - 1, mod); } } 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_printf("Exception (fmpz_mod_poly_divrem_newton_n_preinv)." " Division by zero.\n"); flint_abort(); } } if (lenA < lenB) { fmpz_mod_poly_set(R, A, ctx); fmpz_mod_poly_zero(Q, ctx); return; } if (lenA > 2 * lenB - 2) { flint_printf("Exception (fmpz_mod_poly_divrem_newton_n_preinv).\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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); } flint2-2.8.4/fmpz_mod_poly/evaluate_fmpz.c000066400000000000000000000032341414523752600206220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_mod_poly.h" 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); } } 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, fmpz_mod_ctx_modulus(ctx)); fmpz_swap(res, t); fmpz_clear(t); } else { _fmpz_mod_poly_evaluate_fmpz(res, poly->coeffs, poly->length, a, fmpz_mod_ctx_modulus(ctx)); } } flint2-2.8.4/fmpz_mod_poly/evaluate_fmpz_vec.c000066400000000000000000000022531414523752600214570ustar00rootroot00000000000000/* 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 2.1 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 "fmpz_mod_poly.h" void _fmpz_mod_poly_evaluate_fmpz_vec(fmpz * ys, const fmpz * coeffs, slong len, const fmpz * xs, slong n, const fmpz_t mod) { if (len < 32) _fmpz_mod_poly_evaluate_fmpz_vec_iter(ys, coeffs, len, xs, n, mod); else _fmpz_mod_poly_evaluate_fmpz_vec_fast(ys, coeffs, len, xs, n, mod); } 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, fmpz_mod_ctx_modulus(ctx)); } flint2-2.8.4/fmpz_mod_poly/evaluate_fmpz_vec_fast.c000066400000000000000000000076061414523752600225030ustar00rootroot00000000000000/* Copyright (C) 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 2.1 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" #include "fmpz_mod_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_t mod) { 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_negmod(temp, tree[0]->coeffs, mod); _fmpz_mod_poly_evaluate_fmpz(vs, poly, plen, temp, mod); } 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_invmod(inv, pa->coeffs + pa->length - 1, mod); _fmpz_mod_poly_rem(t + i, poly, plen, pa->coeffs, pa->length, inv, mod); } 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_invmod(inv, pa->coeffs + pa->length - 1, mod); _fmpz_mod_poly_rem(pc, pb, 2 * pow, pa->coeffs, pa->length, inv, mod); pa++; fmpz_invmod(inv, pa->coeffs + pa->length - 1, mod); _fmpz_mod_poly_rem(pc + pow, pb, 2 * pow, pa->coeffs, pa->length, inv, mod); pa++; pb += 2 * pow; pc += 2 * pow; left -= 2 * pow; } if (left > pow) { fmpz_invmod(inv, pa->coeffs + pa->length - 1, mod); _fmpz_mod_poly_rem(pc, pb, left, pa->coeffs, pa->length, inv, mod); pa ++; fmpz_invmod(inv, pa->coeffs + pa->length - 1, mod); _fmpz_mod_poly_rem(pc + pow, pb, left, pa->coeffs, pa->length, inv, mod); } 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_t mod) { fmpz_poly_struct ** tree; tree = _fmpz_mod_poly_tree_alloc(n); _fmpz_mod_poly_tree_build(tree, xs, n, mod); _fmpz_mod_poly_evaluate_fmpz_vec_fast_precomp(ys, poly, plen, tree, n, mod); _fmpz_mod_poly_tree_free(tree, n); } 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, fmpz_mod_ctx_modulus(ctx)); } flint2-2.8.4/fmpz_mod_poly/evaluate_fmpz_vec_iter.c000066400000000000000000000021241414523752600224770ustar00rootroot00000000000000/* 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 2.1 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 "fmpz_mod_poly.h" void _fmpz_mod_poly_evaluate_fmpz_vec_iter(fmpz * ys, const fmpz * coeffs, slong len, const fmpz * xs, slong n, const fmpz_t mod) { slong i; for (i = 0; i < n; i++) _fmpz_mod_poly_evaluate_fmpz(ys + i, coeffs, len, xs + i, mod); } 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, fmpz_mod_ctx_modulus(ctx)); } flint2-2.8.4/fmpz_mod_poly/find_distinct_nonzero_roots.c000066400000000000000000000153641414523752600236100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_mod.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_newton(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_newton(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; } flint2-2.8.4/fmpz_mod_poly/fit_length.c000066400000000000000000000014741414523752600201070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #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; } } flint2-2.8.4/fmpz_mod_poly/fprint.c000066400000000000000000000025541414523752600172660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz.h" #include "fmpz_mod_poly.h" 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)); } flint2-2.8.4/fmpz_mod_poly/fread.c000066400000000000000000000024031414523752600170360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_mod_poly.h" #include "fmpz.h" 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; } flint2-2.8.4/fmpz_mod_poly/frobenius_power.c000066400000000000000000000036161414523752600211740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #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); } } flint2-2.8.4/fmpz_mod_poly/frobenius_powers_2exp_clear.c000066400000000000000000000013741414523752600234620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #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); } flint2-2.8.4/fmpz_mod_poly/frobenius_powers_2exp_precomp.c000066400000000000000000000024751414523752600240440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.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); } flint2-2.8.4/fmpz_mod_poly/frobenius_powers_clear.c000066400000000000000000000014101414523752600225130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #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); } flint2-2.8.4/fmpz_mod_poly/frobenius_powers_precomp.c000066400000000000000000000027721414523752600231060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.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); } flint2-2.8.4/fmpz_mod_poly/gcd_euclidean.c000066400000000000000000000073551414523752600205360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_vec.h" #include "fmpz_mod_poly.h" slong _fmpz_mod_poly_gcd_euclidean(fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p) { if (lenB == 1) { fmpz_one(G); return 1; } else /* lenA >= lenB > 1 */ { const slong lenW = FLINT_MAX(lenA - lenB + 1, lenB) + lenA + 2 * lenB; fmpz_t invR3; 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(Q, R1, A, lenA, B, lenB, invB, p); lenR3 = lenB - 1; FMPZ_VEC_NORM(R1, lenR3); if (lenR3 == 0) { _fmpz_vec_set(G, B, lenB); FMPZ_VEC_TMP_CLEAR(W, lenW); TMP_END; return lenB; } fmpz_init(invR3); T = R3; R3 = R1; R1 = T; _fmpz_vec_set(R2, B, lenB); lenR2 = lenB; do { fmpz_invmod(invR3, R3 + (lenR3 - 1), p); _fmpz_mod_poly_divrem_basecase(Q, R2, R2, lenR2, R3, lenR3, invR3, p); lenR2 = lenR3 - 1; FMPZ_VEC_NORM(R2, lenR2); FMPZ_VEC_SWAP(R2, lenR2, R3, lenR3); } while (lenR3 > 0); _fmpz_vec_set(G, R2, lenR2); FMPZ_VEC_TMP_CLEAR(W, lenW); fmpz_clear(invR3); TMP_END; return lenR2; } } void fmpz_mod_poly_gcd_euclidean(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(G, B, A, ctx); } else /* lenA >= lenB >= 0 */ { const fmpz * p = fmpz_mod_ctx_modulus(ctx); 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 */ { fmpz_t invB; 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; } fmpz_init(invB); fmpz_invmod(invB, fmpz_mod_poly_lead(B, ctx), p); lenG = _fmpz_mod_poly_gcd_euclidean(g, A->coeffs, lenA, B->coeffs, lenB, invB, p); fmpz_clear(invB); 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); } } } flint2-2.8.4/fmpz_mod_poly/gcd_euclidean_f.c000066400000000000000000000114001414523752600210250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_vec.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_t p) { slong lenG = 0; if (lenB == 1) { fmpz_t invB; fmpz_init(invB); fmpz_gcdinv(f, invB, B, p); 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, p); 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), p); if (!fmpz_is_one(f)) goto cleanup; _fmpz_mod_poly_divrem_basecase(Q, R2, R2, lenR2, R3, lenR3, inv, p); 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, fmpz_mod_ctx_modulus(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); } } } } } flint2-2.8.4/fmpz_mod_poly/gcd_hgcd.c000066400000000000000000000106701414523752600175040ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011, 2012 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.h" #include "fmpz_vec.h" #define __set(B, lenB, A, lenA) \ do { \ _fmpz_vec_set((B), (A), (lenA)); \ (lenB) = (lenA); \ } while (0) #define __rem(R, lenR, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ fmpz_invmod(invB, B + lenB - 1, mod); \ _fmpz_mod_poly_rem((R), (A), (lenA), (B), (lenB), invB, mod); \ (lenR) = (lenB) - 1; \ FMPZ_VEC_NORM((R), (lenR)); \ } \ else \ { \ _fmpz_vec_set((R), (A), (lenA)); \ (lenR) = (lenA); \ } \ } while (0) /* XXX: Incidentally, this implementation currently supports aliasing. But since this may change in the future, no function other than fmpz_mod_poly_gcd_hgcd() should rely on this. */ slong _fmpz_mod_poly_gcd_hgcd(fmpz *G, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t mod) { fmpz *J = _fmpz_vec_init(2 * lenB); fmpz *R = J + lenB; fmpz_t invB; slong lenG, lenJ, lenR; fmpz_init(invB); __rem(R, lenR, A, lenA, B, lenB); if (lenR == 0) { __set(G, lenG, B, lenB); } else { _fmpz_mod_poly_hgcd(NULL, NULL, G, &(lenG), J, &(lenJ), B, lenB, R, lenR, mod); while (lenJ != 0) { __rem(R, lenR, G, lenG, J, lenJ); if (lenR == 0) { __set(G, lenG, J, lenJ); break; } if (lenJ < FMPZ_MOD_POLY_GCD_CUTOFF) { fmpz_invmod(invB, R + lenR - 1, mod); lenG = _fmpz_mod_poly_gcd_euclidean(G, J, lenJ, R, lenR, invB, mod); break; } _fmpz_mod_poly_hgcd(NULL, NULL, G, &(lenG), J, &(lenJ), J, lenJ, R, lenR, mod); } } _fmpz_vec_clear(J, 2 * lenB); fmpz_clear(invB); return lenG; } void fmpz_mod_poly_gcd_hgcd(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_hgcd(G, B, A, ctx); } else /* lenA >= lenB >= 0 */ { slong lenA = A->length, lenB = B->length, lenG; fmpz_mod_poly_t tG; 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) { fmpz_mod_poly_init2(tG, FLINT_MIN(lenA, lenB), ctx); g = tG->coeffs; } else { fmpz_mod_poly_fit_length(G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } lenG = _fmpz_mod_poly_gcd_hgcd(g, A->coeffs, lenA, B->coeffs, lenB, fmpz_mod_ctx_modulus(ctx)); if (G == A || G == B) { fmpz_mod_poly_swap(tG, G, ctx); fmpz_mod_poly_clear(tG, ctx); } G->length = lenG; if (G->length == 1) fmpz_one(G->coeffs + 0); else fmpz_mod_poly_make_monic(G, G, ctx); } } } #undef __set #undef __rem flint2-2.8.4/fmpz_mod_poly/gcdinv.c000066400000000000000000000062621414523752600172360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_vec.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_t p) { fmpz *T; fmpz_t inv; slong ans; fmpz_init(inv); fmpz_invmod(inv, A + (lenA - 1), p); if (lenB < 16) { ans = _fmpz_mod_poly_gcdinv_euclidean(G, S, A, lenA, B, lenB, inv, p); } else { T = _fmpz_vec_init(lenA - 1); ans = _fmpz_mod_poly_xgcd(G, T, S, B, lenB, A, lenA, inv, p); _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_printf("Exception (fmpz_mod_poly_gcdinv). lenB < 2.\n"); flint_abort(); } 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, p); 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); } } } flint2-2.8.4/fmpz_mod_poly/gcdinv_euclidean.c000066400000000000000000000137221414523752600212460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_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_t p) { _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, p); 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_vec_neg(S, S, lenQ); for (i = 0; i < lenQ; i++) { if (fmpz_sgn(S + i) < 0) fmpz_add(S + i, S + i, p); } 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_vec_neg(U2, Q, lenQ); lenU2 = lenQ; lenV3 = 0; FMPZ_VEC_SWAP(V3, lenV3, R, lenR); do { fmpz_invmod(inv, V3 + (lenV3 - 1), p); _fmpz_mod_poly_divrem_basecase(Q, D, D, lenD, V3, lenV3, inv, p); 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, p); else _fmpz_mod_poly_mul(W, Q, lenQ, U2, lenU2, p); lenW = lenQ + lenU2 - 1; _fmpz_mod_poly_sub(U1, U1, lenU1, W, lenW, p); 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, p); } 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_printf("Exception (fmpz_mod_poly_gcdinv). lenB < 2.\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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); } } flint2-2.8.4/fmpz_mod_poly/gcdinv_euclidean_f.c000066400000000000000000000136621414523752600215560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_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_t p) { _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, p); 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_vec_neg(S, S, lenQ); 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_vec_neg(U2, Q, lenQ); lenU2 = lenQ; lenV3 = 0; FMPZ_VEC_SWAP(V3, lenV3, R, lenR); do { fmpz_gcdinv(f, inv, V3 + (lenV3 - 1), p); if (!fmpz_is_one(f)) goto cleanup; _fmpz_mod_poly_divrem_basecase(Q, D, D, lenD, V3, lenV3, inv, p); 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, p); else _fmpz_mod_poly_mul(W, Q, lenQ, U2, lenU2, p); lenW = lenQ + lenU2 - 1; _fmpz_mod_poly_sub(U1, U1, lenU1, W, lenW, p); 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_printf("Exception (fmpz_mod_poly_gcdinv_euclidean_f). lenB < 2.\n"); flint_abort(); } 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, p); 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); } } flint2-2.8.4/fmpz_mod_poly/gcdinv_f.c000066400000000000000000000070531414523752600175420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_vec.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_t p) { fmpz *T; fmpz_t inv; slong ans = 0; fmpz_init(inv); fmpz_gcdinv(f, inv, A + (lenA - 1), p); if (fmpz_is_one(f)) { if (lenB < 16) { ans = _fmpz_mod_poly_gcdinv_euclidean_f(f, G, S, A, lenA, B, lenB, inv, p); } else { T = _fmpz_vec_init(lenA - 1); ans = _fmpz_mod_poly_xgcd_f(f, G, T, S, B, lenB, A, lenA, inv, p); _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_printf("Exception (fmpz_mod_poly_gcdinv). lenB < 2.\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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); } } } } flint2-2.8.4/fmpz_mod_poly/gen.c000066400000000000000000000013311414523752600165250ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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))); } flint2-2.8.4/fmpz_mod_poly/get_fmpz_poly.c000066400000000000000000000013701414523752600206350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } flint2-2.8.4/fmpz_mod_poly/get_nmod_poly.c000066400000000000000000000013341414523752600206160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" 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); } flint2-2.8.4/fmpz_mod_poly/hgcd.c000066400000000000000000000511071414523752600166670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" /* We define a whole bunch of macros here which essentially provide the nmod_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) = (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 { \ _fmpz_vec_set((B), (A), (lenA)); \ (lenB) = (lenA); \ } while (0) #define __swap(A, lenA, B, lenB) \ do { \ slong __lenT; \ fmpz * __temp = (A); \ (A) = (B); \ (B) = __temp; \ __lenT = (lenA); \ (lenA) = (lenB); \ (lenB) = __lenT; \ } while (0) #define __add(C, lenC, A, lenA, B, lenB) \ do { \ _fmpz_mod_poly_add((C), (A), (lenA), (B), (lenB), mod); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ FMPZ_VEC_NORM((C), (lenC)); \ } while (0) #define __sub(C, lenC, A, lenA, B, lenB) \ do { \ _fmpz_mod_poly_sub((C), (A), (lenA), (B), (lenB), mod); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ FMPZ_VEC_NORM((C), (lenC)); \ } while (0) #define __mul(C, lenC, A, lenA, B, lenB) \ do { \ if ((lenA) != 0 && (lenB) != 0) \ { \ if ((lenA) >= (lenB)) \ _fmpz_mod_poly_mul((C), (A), (lenA), (B), (lenB), mod); \ else \ _fmpz_mod_poly_mul((C), (B), (lenB), (A), (lenA), mod); \ (lenC) = (lenA) + (lenB) - 1; \ } \ else \ { \ (lenC) = 0; \ } \ } while (0) #define __divrem(Q, lenQ, R, lenR, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ fmpz_invmod(invB, B + lenB - 1, mod); \ _fmpz_mod_poly_divrem((Q), (R), (A), (lenA), (B), (lenB), invB, mod); \ (lenQ) = (lenA) - (lenB) + 1; \ (lenR) = (lenB) - 1; \ FMPZ_VEC_NORM((R), (lenR)); \ } \ else \ { \ _fmpz_vec_set((R), (A), (lenA)); \ (lenQ) = 0; \ (lenR) = (lenA); \ } \ } while (0) static __inline__ void __mat_one(fmpz **M, slong *lenM) { fmpz_one(M[0] + 0); fmpz_one(M[3] + 0); lenM[0] = 1; lenM[1] = 0; lenM[2] = 0; lenM[3] = 1; } /* 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 void __mat_mul_classical(fmpz **C, slong *lenC, fmpz **A, slong *lenA, fmpz **B, slong *lenB, fmpz *T, const fmpz_t mod) { slong lenT; __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); } /* 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 void __mat_mul_strassen(fmpz **C, slong *lenC, fmpz **A, slong *lenA, fmpz **B, slong *lenB, fmpz *T0, fmpz *T1, const fmpz_t mod) { slong lenT0, lenT1; __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); } /* 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 void __mat_mul(fmpz **C, slong *lenC, fmpz **A, slong *lenA, fmpz **B, slong *lenB, fmpz *T0, fmpz *T1, const fmpz_t mod) { 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*FLINT_ABS(fmpz_size(mod)) < 20) { __mat_mul_classical(C, lenC, A, lenA, B, lenB, T0, mod); } else { __mat_mul_strassen(C, lenC, A, lenA, B, lenB, T0, T1, mod); } } /* 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. */ slong _fmpz_mod_poly_hgcd_recursive_iter(fmpz **M, slong *lenM, fmpz **A, slong *lenA, fmpz **B, slong *lenB, const fmpz *a, slong lena, const fmpz *b, slong lenb, fmpz *Q, fmpz **T, fmpz **t, const fmpz_t mod, fmpz_mod_poly_res_t res) { const slong m = lena / 2; slong sgn = 1; fmpz_t invB; fmpz_init(invB); __mat_one(M, lenM); __set(*A, *lenA, a, lena); __set(*B, *lenB, b, lenb); while (*lenB >= m + 1) { slong lenQ, lenT, lent; if (res) fmpz_set(res->lc, (*B) + *lenB - 1); __divrem(Q, lenQ, *T, lenT, *A, *lenA, *B, *lenB); if (res) { if (lenT >= m + 1) { if (lenT >= 1) { fmpz_powm_ui(res->lc, res->lc, *lenA - lenT, mod); fmpz_mul(res->res, res->res, res->lc); fmpz_mod(res->res, res->res, mod); if ((((*lenA + res->off) | (*lenB + res->off)) & 1) == 0) fmpz_negmod(res->res, res->res, mod); } else { if (*lenB == 1) { fmpz_powm_ui(res->lc, res->lc, *lenA - 1, mod); fmpz_mul(res->res, res->res, res->lc); fmpz_mod(res->res, res->res, mod); } else fmpz_zero(res->res); } } 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; } fmpz_clear(invB); return sgn; } /* 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. The res struct, if not NULL, passes information required to compute the sign changes and powers of leading terms used to compute the resultant. */ slong _fmpz_mod_poly_hgcd_recursive(fmpz **M, slong *lenM, fmpz *A, slong *lenA, fmpz *B, slong *lenB, const fmpz *a, slong lena, const fmpz *b, slong lenb, fmpz *P, const fmpz_t mod, int flag, fmpz_mod_poly_res_t res) { const slong m = lena / 2; if (lenb < m + 1) { if (flag) { __mat_one(M, lenM); } __set(A, *lenA, a, lena); __set(B, *lenB, b, lenb); return 1; } else { fmpz_t invB; /* Readonly pointers */ fmpz *a0, *b0, *s, *t, *a4, *b4, *c0, *d0; slong lena0, lenb0, lens, lent, lena4, lenb4, lenc0, lend0; /* Pointers to independently allocated memory */ fmpz *a2, *b2, *a3, *b3, *q, *d, *T0, *T1; slong lena2, lenb2, lena3, lenb3, lenq, lend, lenT0; fmpz *R[4], *S[4]; slong lenR[4], lenS[4]; slong sgnR, sgnS; a2 = P; b2 = a2 + lena; a3 = b2 + lena; b3 = a3 + lena; q = b3 + lena; d = q + (lena + 1)/2; T0 = d + lena; T1 = T0 + lena; R[0] = T1 + (lena + 1)/2; R[1] = R[0] + (lena + 1)/2; R[2] = R[1] + (lena + 1)/2; R[3] = R[2] + (lena + 1)/2; S[0] = R[3] + (lena + 1)/2; S[1] = S[0] + (lena + 1)/2; S[2] = S[1] + (lena + 1)/2; S[3] = S[2] + (lena + 1)/2; P += 6 * lena + 10 * (lena + 1)/2; fmpz_init(invB); __attach_shift(a0, lena0, (fmpz *) a, lena, m); __attach_shift(b0, lenb0, (fmpz *) b, lenb, m); if (res) { fmpz_set(res->lc, b + lenb - 1); res->len0 -= m; res->len1 -= m; res->off += m; } if (lena0 < NMOD_POLY_HGCD_CUTOFF) sgnR = _fmpz_mod_poly_hgcd_recursive_iter(R, lenR, &a3, &lena3, &b3, &lenb3, a0, lena0, b0, lenb0, q, &T0, &T1, mod, res); else sgnR = _fmpz_mod_poly_hgcd_recursive(R, lenR, a3, &lena3, b3, &lenb3, a0, lena0, b0, lenb0, P, mod, 1, res); if (res) { res->off -= m; res->len0 += m; res->len1 += m; } __attach_truncate(s, lens, (fmpz *) a, lena, m); __attach_truncate(t, lent, (fmpz *) 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); _fmpz_vec_zero(b2 + lenb2, m + lenb3 - lenb2); __attach_shift(b4, lenb4, b2, lenb2, m); __add(b4, lenb4, b4, lenb4, b3, lenb3); lenb2 = FLINT_MAX(m + lenb3, lenb2); FMPZ_VEC_NORM(b2, lenb2); __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); _fmpz_vec_zero(a2 + lena2, m + lena3 - lena2); __attach_shift(a4, lena4, a2, lena2, m); __add(a4, lena4, a4, lena4, a3, lena3); lena2 = FLINT_MAX(m + lena3, lena2); FMPZ_VEC_NORM(a2, lena2); 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]); } return sgnR; } else { slong k = 2 * m - lenb2 + 1; if (res) { if (lenb2 < lenb) /* ensure something happened */ { if (lenb2 >= 1) { fmpz_powm_ui(res->lc, res->lc, res->len0 - lenb2, mod); fmpz_mul(res->res, res->res, res->lc); fmpz_mod(res->res, res->res, mod); if ((((res->len0 + res->off) | (res->len1 + res->off)) & 1) == 0) fmpz_negmod(res->res, res->res, mod); } else { if (res->len1 == 1) { fmpz_powm_ui(res->lc, res->lc, res->len0 - 1, mod); fmpz_mul(res->res, res->res, res->lc); fmpz_mod(res->res, res->res, mod); } else fmpz_zero(res->res); } } fmpz_set(res->lc, b2 + lenb2 - 1); 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) { if (lend >= m + 1) { if (lend >= 1) { fmpz_powm_ui(res->lc, res->lc, lena2 - lend, mod); fmpz_mul(res->res, res->res, res->lc); fmpz_mod(res->res, res->res, mod); if ((((lena2 + res->off) | (lenb2 + res->off)) & 1) == 0) fmpz_negmod(res->res, res->res, mod); } else { if (lenb2 == 1) { fmpz_powm_ui(res->lc, res->lc, lena2 - 1, mod); fmpz_mul(res->res, res->res, res->lc); fmpz_mod(res->res, res->res, mod); } else fmpz_zero(res->res); } res->len0 = lenb2; res->len1 = lend; } res->len0 -= k; res->len1 -= k; res->off += k; } if (lenc0 < NMOD_POLY_HGCD_CUTOFF) sgnS = _fmpz_mod_poly_hgcd_recursive_iter(S, lenS, &a3, &lena3, &b3, &lenb3, c0, lenc0, d0, lend0, a2, &T0, &T1, mod, res); /* a2 as temp */ else sgnS = _fmpz_mod_poly_hgcd_recursive(S, lenS, a3, &lena3, b3, &lenb3, c0, lenc0, d0, lend0, P, mod, 1, res); if (res) { 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); _fmpz_vec_zero(B + *lenB, k + lenb3 - *lenB); __attach_shift(b4, lenb4, B, *lenB, k); __add(b4, lenb4, b4, lenb4, b3, lenb3); *lenB = FLINT_MAX(k + lenb3, *lenB); FMPZ_VEC_NORM(B, *lenB); __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); _fmpz_vec_zero(A + *lenA, k + lena3 - *lenA); __attach_shift(a4, lena4, A, *lenA, k); __add(a4, lena4, a4, lena4, a3, lena3); *lenA = FLINT_MAX(k + lena3, *lenA); FMPZ_VEC_NORM(A, *lenA); 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, mod); } fmpz_clear(invB); return - (sgnR * sgnS); } } } /* XXX: Currently supports aliasing between {A,a} and {B,b}. */ 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_t mod) { const slong lenW = 22 * lena + 16 * (FLINT_CLOG2(lena) + 1); slong sgnM; fmpz *W; W = _fmpz_vec_init(lenW); if (M == NULL) { sgnM = _fmpz_mod_poly_hgcd_recursive(NULL, NULL, A, lenA, B, lenB, a, lena, b, lenb, W, mod, 0, NULL); } else { sgnM = _fmpz_mod_poly_hgcd_recursive(M, lenM, A, lenA, B, lenB, a, lena, b, lenb, W, mod, 1, NULL); } _fmpz_vec_clear(W, lenW); return sgnM; } flint2-2.8.4/fmpz_mod_poly/init.c000066400000000000000000000015371414523752600167270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #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; } flint2-2.8.4/fmpz_mod_poly/inlines.c000066400000000000000000000124411414523752600174210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_MOD_POLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" 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); } flint2-2.8.4/fmpz_mod_poly/inv_series_newton.c000066400000000000000000000060121414523752600215150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_inv_series_newton(fmpz * Qinv, const fmpz * Q, slong n, const fmpz_t cinv, const fmpz_t p) { if (n == 1) /* {Q,1} * cinv == 1 mod (x) */ { fmpz_set(Qinv, cinv); } else { const slong alloc = FLINT_MAX(n, 3 * FMPZ_MOD_POLY_INV_NEWTON_CUTOFF); slong *a, i, m; fmpz *W; W = _fmpz_vec_init(alloc); for (i = 1; (WORD(1) << i) < n; i++) ; a = (slong *) flint_malloc(i * sizeof(slong)); a[i = 0] = n; while (n >= FMPZ_MOD_POLY_INV_NEWTON_CUTOFF) a[++i] = (n = (n + 1) / 2); /* Base case */ { fmpz *Qrev = W + 2 * FMPZ_MOD_POLY_INV_NEWTON_CUTOFF; _fmpz_poly_reverse(Qrev, Q, n, n); _fmpz_vec_zero(W, 2*n - 2); fmpz_one(W + (2*n - 2)); _fmpz_mod_poly_div_basecase(Qinv, W, W, 2*n - 1, Qrev, n, cinv, p); _fmpz_poly_reverse(Qinv, Qinv, n, n); } for (i--; i >= 0; i--) { m = n; n = a[i]; _fmpz_mod_poly_mullow(W, Q, n, Qinv, m, p, n); _fmpz_mod_poly_mullow(Qinv + m, Qinv, m, W + m, n - m, p, n - m); _fmpz_mod_poly_neg(Qinv + m, Qinv + m, n - m, p); } _fmpz_vec_clear(W, alloc); flint_free(a); } } void fmpz_mod_poly_inv_series_newton(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_invmod(cinv, Q->coeffs, p); if (Qinv != Q) { fmpz_mod_poly_fit_length(Qinv, n, ctx); _fmpz_mod_poly_inv_series_newton(Qinv->coeffs, Qcopy, n, cinv, p); } else { fmpz *t = _fmpz_vec_init(n); _fmpz_mod_poly_inv_series_newton(t, Qcopy, n, cinv, p); _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); if (Qalloc) flint_free(Qcopy); fmpz_clear(cinv); } flint2-2.8.4/fmpz_mod_poly/inv_series_newton_f.c000066400000000000000000000034021414523752600220220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_inv_series_newton_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); _fmpz_mod_poly_inv_series_newton(Qinv->coeffs, Qcopy, n, cinv, p); } else { fmpz *t = _fmpz_vec_init(n); _fmpz_mod_poly_inv_series_newton(t, Qcopy, n, cinv, p); _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); } flint2-2.8.4/fmpz_mod_poly/invmod.c000066400000000000000000000044051414523752600172550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.h" int _fmpz_mod_poly_invmod(fmpz *A, const fmpz *B, slong lenB, const fmpz *P, slong lenP, const fmpz_t p) { 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, p); if (lenG == 1 && !fmpz_is_one(G + 0)) { fmpz_t invG; fmpz_init(invG); fmpz_invmod(invG, G + 0, p); _fmpz_mod_poly_scalar_mul_fmpz(A, A, lenP - 1, invG, p); 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_printf("Exception (fmpz_mod_poly_invmod). lenP < 2.\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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; } flint2-2.8.4/fmpz_mod_poly/invmod_f.c000066400000000000000000000046441414523752600175670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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_t p) { 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, p); if (fmpz_is_one(f) && lenG == 1 && !fmpz_is_one(G + 0)) { fmpz_t invG; fmpz_init(invG); fmpz_gcdinv(f, invG, G + 0, p); _fmpz_mod_poly_scalar_mul_fmpz(A, A, lenP - 1, invG, p); 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_printf("Exception (fmpz_mod_poly_invmod). lenP < 2.\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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; } flint2-2.8.4/fmpz_mod_poly/is_canonical.c000066400000000000000000000014131414523752600203770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_poly/make_monic.c000066400000000000000000000021041414523752600200550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.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, fmpz_mod_ctx_modulus(ctx)); fmpz_clear(inv); } flint2-2.8.4/fmpz_mod_poly/make_monic_f.c000066400000000000000000000021111414523752600203600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.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, fmpz_mod_ctx_modulus(ctx)); fmpz_clear(inv); } flint2-2.8.4/fmpz_mod_poly/minpoly_bm.c000066400000000000000000000047221414523752600201300ustar00rootroot00000000000000/* This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_mod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" slong _fmpz_mod_poly_minpoly_bm(fmpz* poly, const fmpz* seq, slong len, const fmpz_t p) { 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(disc, disc, p); 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); } else { /* switching update */ slong pos = (i - m) - (curlen - prevlen); _fmpz_vec_scalar_mul_fmpz(prevpoly, prevpoly, prevlen, disc); _fmpz_poly_add(prevpoly + pos, prevpoly + pos, FLINT_MAX(0, prevlen - pos), curpoly, curlen); prevlen = curlen + pos; fmpz_sub(disc, p, disc); fmpz_invmod(disc, disc, p); _fmpz_mod_poly_scalar_mul_fmpz(curpoly, curpoly, curlen, disc, p); FMPZ_VEC_SWAP(curpoly, curlen, prevpoly, prevlen); m = i; } } /* make curpoly monic and copy to poly if necessary */ fmpz_invmod(disc, curpoly + (curlen - 1), p); _fmpz_mod_poly_scalar_mul_fmpz(poly, curpoly, curlen, disc, p); _fmpz_vec_clear(buf, len + 1); fmpz_clear(disc); return curlen; } flint2-2.8.4/fmpz_mod_poly/minpoly_hgcd.c000066400000000000000000000043371414523752600204410ustar00rootroot00000000000000/* This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_mod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" slong _fmpz_mod_poly_minpoly_hgcd(fmpz* poly, const fmpz* seq, slong len, const fmpz_t p) { 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); _fmpz_mod_poly_hgcd(M, lenM, A, &lenA, B, &lenB, f, len + 1, g, leng, p); len_poly = lenM[0]; /* one more step may be necessary */ if (len_poly <= lenB) { slong quo_len = lenA - lenB + 1; fmpz_invmod(buf, B + (lenB - 1), p); _fmpz_mod_poly_divrem(M[2], M[3], A, lenA, B, lenB, buf, p); if (len_poly >= quo_len) { _fmpz_mod_poly_mul(M[3], poly, len_poly, M[2], quo_len, p); } else { _fmpz_mod_poly_mul(M[3], M[2], quo_len, poly, len_poly, p); } len_poly += quo_len - 1; _fmpz_mod_poly_add(poly, M[3], len_poly, M[1], lenM[1], p); } /* make poly monic */ fmpz_invmod(buf, poly + (len_poly - 1), p); _fmpz_mod_poly_scalar_mul_fmpz(poly, poly, len_poly, buf, p); _fmpz_vec_clear(buf, buflen); return len_poly; } flint2-2.8.4/fmpz_mod_poly/mul.c000066400000000000000000000042261414523752600165570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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_t p) { _fmpz_poly_mul(res, poly1, len1, poly2, len2); _fmpz_vec_scalar_mod_fmpz(res, res, len1 + len2 - 1, p); } 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, fmpz_mod_ctx_modulus(ctx)); else _fmpz_mod_poly_mul(t, poly2->coeffs, len2, poly1->coeffs, len1, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(ctx)); else _fmpz_mod_poly_mul(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, lenr); } _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/mullow.c000066400000000000000000000043671414523752600173070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_mullow(fmpz *res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t p, slong n) { _fmpz_poly_mullow(res, poly1, len1, poly2, len2, n); _fmpz_vec_scalar_mod_fmpz(res, res, n, p); } 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, fmpz_mod_ctx_modulus(ctx), n); else _fmpz_mod_poly_mullow(t, poly2->coeffs, len2, poly1->coeffs, len1, fmpz_mod_ctx_modulus(ctx), n); _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, fmpz_mod_ctx_modulus(ctx), n); else _fmpz_mod_poly_mullow(res->coeffs, poly2->coeffs, len2, poly1->coeffs, len1, fmpz_mod_ctx_modulus(ctx), n); _fmpz_mod_poly_set_length(res, n); _fmpz_mod_poly_normalise(res); } } flint2-2.8.4/fmpz_mod_poly/mulmod.c000066400000000000000000000047311414523752600172600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_vec.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_t p) { 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, p); else _fmpz_mod_poly_mul(T, poly2, len2, poly1, len1, p); fmpz_init(invf); fmpz_invmod(invf, f + lenf - 1, p); _fmpz_mod_poly_divrem(Q, res, T, lenT, f, lenf, invf, p); _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_printf("Exception (fmpz_mod_poly_mulmod). Divide by zero\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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); } } flint2-2.8.4/fmpz_mod_poly/mulmod_preinv.c000066400000000000000000000055311414523752600206420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_vec.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_t p) { 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, p); else _fmpz_mod_poly_mul(T, poly2, len2, poly1, len1, p); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, lenT, f, lenf, finv, lenfinv, p); _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_printf("Exception (fmpz_mod_poly_mulmod_preinv). Divide by zero\n"); flint_abort(); } if (lenf <= len1 || lenf <= len2) { flint_printf("Exception (fmpz_mod_poly_mulmod_preinv). Input larger than modulus.\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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); } } flint2-2.8.4/fmpz_mod_poly/neg.c000066400000000000000000000022371414523752600165330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" 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); } } 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, fmpz_mod_ctx_modulus(ctx)); } flint2-2.8.4/fmpz_mod_poly/pow.c000066400000000000000000000071761414523752600165760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_pow(fmpz *res, const fmpz *poly, slong len, ulong e, const fmpz_t p) { 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, p); rlen = 2 * len - 1; if ((bit & e)) { _fmpz_mod_poly_mul(S, R, rlen, poly, len, p); rlen += len - 1; T = R; R = S; S = T; } while ((bit >>= 1)) { if ((bit & e)) { _fmpz_mod_poly_sqr(S, R, rlen, p); rlen += rlen - 1; _fmpz_mod_poly_mul(R, S, rlen, poly, len, p); rlen += len - 1; } else { _fmpz_mod_poly_sqr(S, R, rlen, p); 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_powm_ui(rop->coeffs, op->coeffs, e, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(rop, rlen); } else { fmpz *t = _fmpz_vec_init(rlen); _fmpz_mod_poly_pow(t, op->coeffs, len, e, fmpz_mod_ctx_modulus(ctx)); _fmpz_vec_clear(rop->coeffs, rop->alloc); rop->coeffs = t; rop->alloc = rlen; rop->length = rlen; } _fmpz_mod_poly_normalise(rop); } flint2-2.8.4/fmpz_mod_poly/pow_trunc.c000066400000000000000000000052071414523752600200020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_pow_trunc(fmpz * res, const fmpz * poly, ulong e, slong trunc, const fmpz_t p) { _fmpz_mod_poly_pow_trunc_binexp(res, poly, e, trunc, p); } 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, fmpz_mod_ctx_modulus(ctx)); } else { fmpz_mod_poly_t t; fmpz_mod_poly_init2(t, trunc, ctx); _fmpz_mod_poly_pow_trunc(t->coeffs, q, e, trunc, fmpz_mod_ctx_modulus(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); } flint2-2.8.4/fmpz_mod_poly/pow_trunc_binexp.c000066400000000000000000000102631414523752600213450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_pow_trunc_binexp(fmpz * res, const fmpz * poly, ulong e, slong trunc, const fmpz_t p) { 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, p, trunc); if ((bit & e)) { _fmpz_mod_poly_mullow(S, R, trunc, poly, trunc, p, trunc); T = R; R = S; S = T; } while ((bit >>= 1)) { if ((bit & e)) { _fmpz_mod_poly_mullow(S, R, trunc, R, trunc, p, trunc); _fmpz_mod_poly_mullow(R, S, trunc, poly, trunc, p, trunc); } else { _fmpz_mod_poly_mullow(S, R, trunc, R, trunc, p, trunc); 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, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(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); } flint2-2.8.4/fmpz_mod_poly/powers_mod_bsgs_threaded.c000077500000000000000000000147631414523752600230300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" typedef struct { volatile slong * j; slong k; slong n; slong glen; slong ginvlen; const fmpz * g; const fmpz * ginv; fmpz ** res; const fmpz * p; #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 * p = arg.p; 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_mul(res[i] + 0, res[j] + 0, res[i - j] + 0); fmpz_mod(res[i] + 0, res[i] + 0, p); } } 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, p); } } } /* 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_t p, 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, p); /* 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_mul(res[i] + 0, res[i - k] + 0, res[k] + 0); fmpz_mod(res[i] + 0, res[i] + 0, p); } } 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, p); } 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].p = p; #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_printf("Exception (fmpz_mod_poly_powers_mod_bsgs). Divide by zero.\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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); } flint2-2.8.4/fmpz_mod_poly/powers_mod_naive.c000077500000000000000000000075151414523752600213310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.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_t p) { 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_mul(res[i] + 0, res[i - 1] + 0, res[1] + 0); fmpz_mod(res[i] + 0, res[i] + 0, p); } } 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, p); } } 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_printf("Exception (fmpz_mod_poly_powers_mod_naive). Divide by zero.\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(ctx)); for (i = 0; i < n; i++) _fmpz_mod_poly_normalise(res + i); fmpz_mod_poly_clear(ginv, ctx); flint_free(res_arr); } flint2-2.8.4/fmpz_mod_poly/powmod_fmpz_binexp.c000066400000000000000000000102551414523752600216670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_vec.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_t p) { fmpz * T, * Q; fmpz_t invf; slong lenT, lenQ; slong i; if (lenf == 2) { fmpz_powm(res, poly, e, p); return; } lenT = 2 * lenf - 3; lenQ = lenT - lenf + 1; T = _fmpz_vec_init(lenT + lenQ); Q = T + lenT; fmpz_init(invf); fmpz_invmod(invf, f + lenf - 1, p); _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, p); _fmpz_mod_poly_divrem(Q, res, T, 2 * lenf - 3, f, lenf, invf, p); if (fmpz_tstbit(e, i)) { _fmpz_mod_poly_mul(T, res, lenf - 1, poly, lenf - 1, p); _fmpz_mod_poly_divrem(Q, res, T, 2 * lenf - 3, f, lenf, invf, p); } } 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_printf("Exception (fmpz_mod_poly_powmod_fmpz_binexp). Divide by zero\n"); flint_abort(); } if (lenf == 1) { fmpz_mod_poly_zero(res, ctx); return; } if (fmpz_sgn(e) < 0) { flint_printf("Exception (fmpz_mod_poly_powmod_fmpz_binexp). negative exp not implemented\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(ctx)); } if (qcopy) _fmpz_vec_clear(q, trunc); _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/powmod_fmpz_binexp_preinv.c000066400000000000000000000112321414523752600232460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_vec.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_t p) { fmpz * T, * Q; slong lenT, lenQ; slong i; if (lenf == 2) { fmpz_powm(res, poly, e, p); 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, p); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, p); if (fmpz_tstbit(e, i)) { _fmpz_mod_poly_mul(T, res, lenf - 1, poly, lenf - 1, p); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, p); } } _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_printf("Exception (fmpz_mod_poly_powmod_fmpz_binexp_preinv)." "Divide by zero.\n"); flint_abort(); } if (lenf == 1) { fmpz_mod_poly_zero(res, ctx); return; } if (fmpz_sgn(e) < 0) { flint_printf("Exception (fmpz_mod_poly_powmod_fmpz_binexp_preinv)." "Negative exp not implemented\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(ctx)); } if (qcopy) _fmpz_vec_clear(q, trunc); _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/powmod_linear_fmpz_preinv.c000066400000000000000000000066221414523752600232420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, fmpz_mod_ctx_modulus(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(res + j, t, fmpz_mod_ctx_modulus(ctx)); } fmpz_mul(t, a, res + j); fmpz_addmul(t, lcinv, f + j); fmpz_mod(res + j, t, fmpz_mod_ctx_modulus(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); } flint2-2.8.4/fmpz_mod_poly/powmod_ui_binexp.c000066400000000000000000000075451414523752600213400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" void _fmpz_mod_poly_powmod_ui_binexp(fmpz * res, const fmpz * poly, ulong e, const fmpz * f, slong lenf, const fmpz_t p) { fmpz * T, * Q; fmpz_t invf; slong lenT, lenQ; int i; if (lenf == 2) { fmpz_powm_ui(res, poly, e, p); 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_invmod(invf, f + lenf - 1, p); _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, p); _fmpz_mod_poly_divrem(Q, res, T, 2 * lenf - 3, f, lenf, invf, p); if (e & (UWORD(1) << i)) { _fmpz_mod_poly_mul(T, res, lenf - 1, poly, lenf - 1, p); _fmpz_mod_poly_divrem(Q, res, T, 2 * lenf - 3, f, lenf, invf, p); } } 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_printf("Exception (fmpz_mod_poly_powmod). Divide by zero\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(ctx)); } if (qcopy) _fmpz_vec_clear(q, trunc); _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/powmod_ui_binexp_preinv.c000066400000000000000000000104561414523752600227160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.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_t p) { fmpz * T, * Q; slong lenT, lenQ; int i; if (lenf == 2) { fmpz_powm_ui(res, poly, e, p); 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, p); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, p); if (e & (UWORD (1) << i)) { _fmpz_mod_poly_mul(T, res, lenf - 1, poly, lenf - 1, p); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, p); } } _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_printf("Exception (fmpz_mod_poly_powmod_ui_binexp_preinv)." "Divide by zero\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(ctx)); } if (qcopy) _fmpz_vec_clear(q, trunc); _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/powmod_x_fmpz_preinv.c000066400000000000000000000126001414523752600222300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "long_extras.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_t p) { 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, p); c = l + 1; window = WORD(0); } for (; i >= 0; i--) { _fmpz_mod_poly_sqr(T, res, lenf - 1, p); _fmpz_mod_poly_divrem_newton_n_preinv(Q, res, T, 2 * lenf - 3, f, lenf, finv, lenfinv, p); 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, p); 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_printf("Exception (fmpz_mod_poly_powmod_x_fmpz_preinv)." "Divide by zero\n"); flint_abort(); } if (fmpz_sgn(e) < 0) { flint_printf("Exception (fmpz_mod_poly_powmod_x_fmpz_preinv)." "Negative exp not implemented\n"); flint_abort(); } 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, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(ctx)); } _fmpz_mod_poly_set_length(res, trunc); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/product_roots_fmpz_vec.c000066400000000000000000000044051414523752600225600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" void _fmpz_mod_poly_product_roots_fmpz_vec(fmpz * poly, const fmpz * xs, slong n, const fmpz_t mod) { if (n == 0) { if (fmpz_is_one(mod)) fmpz_zero(poly); else fmpz_one(poly); } else if (n < 20) { slong i, j; if (fmpz_is_one(mod)) fmpz_zero(poly + n); else fmpz_one(poly + n); fmpz_negmod(poly + n - 1, xs, mod); for (i = 1; i < n; i++) { fmpz_mul(poly + n - i - 1, poly + n - i, xs + i); fmpz_mod(poly + n - i - 1, poly + n - i - 1, mod); fmpz_negmod(poly + n - i - 1, poly + n - i - 1, mod); for (j = 0; j < i - 1; j++) { fmpz_submul(poly + n - i + j, poly + n - i + j + 1, xs + i); fmpz_mod(poly + n - i + j, poly + n - i + j, mod); } fmpz_sub(poly + n - 1, poly + n - 1, xs + i); fmpz_mod(poly + n - 1, poly + n - 1, mod); } } 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, mod); _fmpz_mod_poly_product_roots_fmpz_vec(tmp + m + 1, xs + m, n - m, mod); _fmpz_mod_poly_mul(poly, tmp, m + 1, tmp + m + 1, n - m + 1, mod); _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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(poly, xlen + 1); } flint2-2.8.4/fmpz_mod_poly/profile/000077500000000000000000000000001414523752600172525ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_poly/profile/p-gcd.c000066400000000000000000000146711414523752600204210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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); timeit_stop(t[0]); timeit_start(t[1]); for (l = 0; l < loops; l++) fmpz_mod_poly_gcd_hgcd(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); } flint2-2.8.4/fmpz_mod_poly/profile/p-invert.c000066400000000000000000000037311414523752600211660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.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_newton(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); } flint2-2.8.4/fmpz_mod_poly/profile/p-minpoly.c000066400000000000000000000104401414523752600213410ustar00rootroot00000000000000/* This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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 #include #include #include "flint.h" #include "fmpz.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); } flint2-2.8.4/fmpz_mod_poly/profile/p-tree.c000066400000000000000000000033661414523752600206220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.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, N); _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); } flint2-2.8.4/fmpz_mod_poly/radix.c000066400000000000000000000140141414523752600170650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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_t p) { 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, p); } 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]; } _fmpz_mod_poly_inv_series_newton(Rinv[i], W, lenQ, invLP, p); /* invLP := inv{lead{R^{2^i}}} */ if (i != k - 1) { fmpz_mul(invLP, invLP, invLP); fmpz_mod(invLP, invLP, p); } } 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), fmpz_mod_ctx_modulus(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_t p) { 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, p, lenQ); _fmpz_poly_reverse(Q, Q, lenQ, lenQ); _fmpz_mod_poly_radix(B, Q, Rpow, Rinv, degR, k + (WORD(1) << i), i-1, W, p); _fmpz_mod_poly_mullow(S, Rpow[i], lenQ, Q, lenQ, p, lenQ); _fmpz_mod_poly_sub(S, F, lenQ, S, lenQ, p); _fmpz_mod_poly_radix(B, S, Rpow, Rinv, degR, k, i-1, W + lenQ, p); } } 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, fmpz_mod_ctx_modulus(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); } } } flint2-2.8.4/fmpz_mod_poly/randtest.c000066400000000000000000000152511414523752600176060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.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_printf("Exception (fmpz_mod_poly_randtest_irreducible). len == 0.\n"); flint_abort(); } 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_printf("Exception (fmpz_mod_poly_randtest_monic_irreducible). len == 0.\n"); flint_abort(); } 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_printf("Exception (fmpz_mod_poly_randtest_not_zero). len == 0.\n"); flint_abort(); } 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 = 3, attempts; while (i <= len/2) { attempts = 0; while (i == len/2 || attempts < 2*len) { fmpz_mod_poly_randtest_monic_sparse(poly, state, len, i, ctx); if (!fmpz_mod_poly_is_zero(poly, ctx) && fmpz_mod_poly_is_irreducible(poly, ctx)) { return; } attempts++; } i++; } } 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); } flint2-2.8.4/fmpz_mod_poly/randtest_monic_primitive.c000066400000000000000000000016771414523752600230720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #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); } } flint2-2.8.4/fmpz_mod_poly/realloc.c000066400000000000000000000024631414523752600174040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mod_poly/rem_basecase.c000066400000000000000000000045471414523752600204010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_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_t p) { 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(q, q, p); _fmpz_vec_scalar_submul_fmpz(W + (iR - lenB + 1), B, lenB, q); _fmpz_vec_scalar_mod_fmpz(W + (iR - lenB + 1), W + (iR - lenB + 1), lenB, p); } } 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, fmpz_mod_ctx_modulus(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); } flint2-2.8.4/fmpz_mod_poly/remove.c000066400000000000000000000021571414523752600172600ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_mod_poly/resultant_euclidean.c000066400000000000000000000067371414523752600220250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_resultant_euclidean(fmpz_t res, const fmpz *poly1, slong len1, const fmpz *poly2, slong len2, const fmpz_t mod) { if (poly1 == poly2) { fmpz_zero(res); } else if (len2 == 1) { if (len1 == 1) { fmpz_set_ui(res, 1); } else if (len1 == 2) { fmpz_set(res, poly2 + 0); } else { fmpz_powm_ui(res, poly2 + 0, len1 - 1, mod); } } else /* len1 >= len2 >= 2 */ { fmpz *u, *v, *r, *t, *w; slong l0, l1, l2; fmpz_t lc, invB; TMP_INIT; TMP_START; fmpz_init(lc); fmpz_init(invB); fmpz_set_ui(res, 1); FMPZ_VEC_TMP_INIT(w, 3*len1); u = w; v = w + len1; r = v + len1; _fmpz_vec_set(u, poly1, len1); _fmpz_vec_set(v, poly2, len2); l1 = len1; l2 = len2; do { l0 = l1; l1 = l2; fmpz_set(lc, v + l1 - 1); fmpz_invmod(invB, v + l1 - 1, mod); _fmpz_mod_poly_rem(r, u, l0, v, l1, invB, mod); l2 = l1 - 1; FMPZ_VEC_NORM(r, l2); { t = u; u = v; v = r; r = t; } if (l2 >= 1) { fmpz_powm_ui(lc, lc, l0 - l2, mod); fmpz_mul(res, res, lc); fmpz_mod(res, res, mod); if (((l0 | l1) & 1) == 0) { fmpz_negmod(res, res, mod); } } else { if (l1 == 1) { fmpz_powm_ui(lc, lc, l0 - 1, mod); fmpz_mul(res, res, lc); fmpz_mod(res, res, mod); } else { fmpz_zero(res); } } } while (l2 > 0); FMPZ_VEC_TMP_CLEAR(w, 3*len1); fmpz_clear(invB); fmpz_clear(lc); TMP_END; } } void fmpz_mod_poly_resultant_euclidean(fmpz_t r, const fmpz_mod_poly_t f, const fmpz_mod_poly_t g, const fmpz_mod_ctx_t ctx) { const slong len1 = f->length; const slong len2 = g->length; if (len1 == 0 || len2 == 0) { fmpz_zero(r); } else { if (len1 >= len2) { _fmpz_mod_poly_resultant_euclidean(r, f->coeffs, len1, g->coeffs, len2, fmpz_mod_ctx_modulus(ctx)); } else { _fmpz_mod_poly_resultant_euclidean(r, g->coeffs, len2, f->coeffs, len1, fmpz_mod_ctx_modulus(ctx)); if (((len1 | len2) & WORD(1)) == WORD(0)) fmpz_mod_neg(r, r, ctx); } } } flint2-2.8.4/fmpz_mod_poly/resultant_hgcd.c000066400000000000000000000154351414523752600207740ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011, 2012 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.h" #include "fmpz_vec.h" #define __set(B, lenB, A, lenA) \ do { \ _fmpz_vec_set((B), (A), (lenA)); \ (lenB) = (lenA); \ } while (0) #define __rem(R, lenR, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ fmpz_invmod(invB, B + lenB - 1, mod); \ _fmpz_mod_poly_rem((R), (A), (lenA), (B), (lenB), invB, mod); \ (lenR) = (lenB) - 1; \ FMPZ_VEC_NORM((R), (lenR)); \ } \ else \ { \ _fmpz_vec_set((R), (A), (lenA)); \ (lenR) = (lenA); \ } \ } while (0) /* XXX: Currently supports aliasing between {A,a} and {B,b}. */ slong _fmpz_mod_poly_hgcd_res(fmpz **M, slong *lenM, fmpz *A, slong *lenA, fmpz *B, slong *lenB, const fmpz *a, slong lena, const fmpz *b, slong lenb, const fmpz_t mod, fmpz_t r) { const slong lenW = 22 * lena + 16 * (FLINT_CLOG2(lena) + 1); slong sgnM; fmpz_mod_poly_res_t res; fmpz *W; fmpz_init(res->res); fmpz_init(res->lc); fmpz_set(res->res, r); fmpz_set(res->lc, b + lenb - 1); res->len0 = lena; res->len1 = lenb; res->off = 0; W = _fmpz_vec_init(lenW); if (M == NULL) { sgnM = _fmpz_mod_poly_hgcd_recursive(NULL, NULL, A, lenA, B, lenB, a, lena, b, lenb, W, mod, 0, res); } else { sgnM = _fmpz_mod_poly_hgcd_recursive(M, lenM, A, lenA, B, lenB, a, lena, b, lenb, W, mod, 1, res); } if (*lenB < lenb) /* make sure something happened */ { if (*lenB >= 1) { fmpz_powm_ui(res->lc, res->lc, res->len0 - *lenB, mod); fmpz_mul(res->res, res->res, res->lc); fmpz_mod(res->res, res->res, mod); if (((res->len0 | res->len1) & 1) == 0) fmpz_negmod(res->res, res->res, mod); } else { if (res->len1 == 1) { fmpz_powm_ui(res->lc, res->lc, res->len0 - 1, mod); fmpz_mul(res->res, res->res, res->lc); fmpz_mod(res->res, res->res, mod); } else fmpz_zero(res->res); } } fmpz_set(r, res->res); fmpz_clear(res->res); fmpz_clear(res->lc); _fmpz_vec_clear(W, lenW); return sgnM; } /* XXX: Incidentally, this implementation currently supports aliasing. But since this may change in the future, no function other than nmod_poly_resultant_hgcd() should rely on this. */ void _fmpz_mod_poly_resultant_hgcd(fmpz_t res, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t mod) { slong len1 = FLINT_MIN(lenA, lenB), len2 = 2 * lenB; fmpz *G = _fmpz_vec_init(len1); fmpz *J = _fmpz_vec_init(len2); fmpz *R = J + lenB; fmpz_t lc, invB; slong lenG, lenJ, lenR; fmpz_init(invB); fmpz_init(lc); fmpz_set_ui(res, 1); fmpz_set(lc, B + lenB - 1); __rem(R, lenR, A, lenA, B, lenB); if (lenR == 0) { if (lenB == 1) { fmpz_powm_ui(lc, lc, lenA - 1, mod); fmpz_mul(res, res, lc); fmpz_mod(res, res, mod); } else fmpz_zero(res); } else { fmpz_powm_ui(lc, lc, lenA - lenR, mod); fmpz_mul(res, res, lc); fmpz_mod(res, res, mod); if (((lenA | lenB) & 1) == 0) fmpz_negmod(res, res, mod); _fmpz_mod_poly_hgcd_res(NULL, NULL, G, &(lenG), J, &(lenJ), B, lenB, R, lenR, mod, res); while (lenJ != 0) { fmpz_set(lc, J + lenJ - 1); __rem(R, lenR, G, lenG, J, lenJ); if (lenR == 0) { if (lenJ == 1) { fmpz_powm_ui(lc, lc, lenG - 1, mod); fmpz_mul(res, res, lc); fmpz_mod(res, res, mod); } else fmpz_zero(res); break; } else { fmpz_powm_ui(lc, lc, lenG - lenR, mod); fmpz_mul(res, res, lc); fmpz_mod(res, res, mod); if (((lenG | lenJ) & 1) == 0) fmpz_negmod(res, res, mod); } if (lenJ < FMPZ_MOD_POLY_GCD_CUTOFF) { fmpz_t r; fmpz_init(r); _fmpz_mod_poly_resultant_euclidean(r, J, lenJ, R, lenR, mod); fmpz_mul(res, res, r); fmpz_mod(res, res, mod); fmpz_clear(r); break; } _fmpz_mod_poly_hgcd_res(NULL, NULL, G, &(lenG), J, &(lenJ), J, lenJ, R, lenR, mod, res); } } _fmpz_vec_clear(J, len2); _fmpz_vec_clear(G, len1); fmpz_clear(lc); fmpz_clear(invB); } void fmpz_mod_poly_resultant_hgcd(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_hgcd(res, B, A, ctx); if (((A->length | B->length) & 1) == 0) fmpz_negmod(res, res, fmpz_mod_ctx_modulus(ctx)); } else /* lenA >= lenB >= 0 */ { slong lenA = A->length, lenB = B->length; /* lenA >= lenB >= 1 */ _fmpz_mod_poly_resultant_hgcd(res, A->coeffs, lenA, B->coeffs, lenB, fmpz_mod_ctx_modulus(ctx)); } } #undef __set #undef __rem flint2-2.8.4/fmpz_mod_poly/reverse.c000066400000000000000000000027461414523752600174420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_mod_poly/scalar_div_fmpz.c000066400000000000000000000036151414523752600211260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_scalar_div_fmpz(fmpz *res, const fmpz *poly, slong len, const fmpz_t x, const fmpz_t p) { fmpz_t g, xinv; fmpz_init(g); fmpz_init(xinv); if (fmpz_sgn(x) < 0 || fmpz_cmp(x, p) >= 0) { fmpz_mod(xinv, x, p); fmpz_gcdinv(g, xinv, xinv, p); } else fmpz_gcdinv(g, xinv, x, p); if (!fmpz_is_one(g)) { flint_printf("Exception (_fmpz_mod_poly_scalar_div_fmpz). Impossible inverse.\n"); flint_abort(); } _fmpz_vec_scalar_mul_fmpz(res, poly, len, xinv); _fmpz_vec_scalar_mod_fmpz(res, res, len, p); 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_printf("Exception (fmpz_mod_poly_scalar_div_fmpz). Division by zero.\n"); flint_abort(); } } fmpz_mod_poly_fit_length(res, poly->length, ctx); _fmpz_mod_poly_scalar_div_fmpz(res->coeffs, poly->coeffs, poly->length, x, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, poly->length); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/scalar_mul_fmpz.c000066400000000000000000000022311414523752600211320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_scalar_mul_fmpz(fmpz *res, const fmpz *poly, slong len, const fmpz_t x, const fmpz_t p) { _fmpz_vec_scalar_mul_fmpz(res, poly, len, x); _fmpz_vec_scalar_mod_fmpz(res, res, len, p); } 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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, poly->length); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/scalar_mul_ui.c000066400000000000000000000021571414523752600206020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_scalar_mul_ui(fmpz *res, const fmpz *poly, slong len, ulong x, const fmpz_t p) { _fmpz_vec_scalar_mul_ui(res, poly, len, x); _fmpz_vec_scalar_mod_fmpz(res, res, len, p); } 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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, poly->length); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/set.c000066400000000000000000000017141414523752600165540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } } flint2-2.8.4/fmpz_mod_poly/set_coeff_fmpz.c000066400000000000000000000023511414523752600207500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" 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(poly->coeffs + n, x, fmpz_mod_ctx_modulus(ctx)); } if (n == poly->length - 1) _fmpz_mod_poly_normalise(poly); /* we may have set the leading coefficient to 0 */ } flint2-2.8.4/fmpz_mod_poly/set_coeff_si.c000066400000000000000000000020221414523752600204020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" 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); } flint2-2.8.4/fmpz_mod_poly/set_coeff_ui.c000066400000000000000000000024241414523752600204120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" 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 */ } flint2-2.8.4/fmpz_mod_poly/set_fmpz.c000066400000000000000000000014351414523752600176100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" 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); } flint2-2.8.4/fmpz_mod_poly/set_fmpz_poly.c000066400000000000000000000015741414523752600206570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" void fmpz_mod_poly_set_fmpz_poly(fmpz_mod_poly_t f, const fmpz_poly_t g, const fmpz_mod_ctx_t ctx) { slong i; fmpz_mod_poly_fit_length(f, g->length, ctx); _fmpz_mod_poly_set_length(f, g->length); for (i = 0; i < g->length; i++) { fmpz_mod(f->coeffs + i, g->coeffs + i, fmpz_mod_ctx_modulus(ctx)); } _fmpz_mod_poly_normalise(f); } flint2-2.8.4/fmpz_mod_poly/set_nmod_poly.c000066400000000000000000000013441414523752600206330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" 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]); } flint2-2.8.4/fmpz_mod_poly/set_trunc.c000066400000000000000000000020371414523752600177660ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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); } } flint2-2.8.4/fmpz_mod_poly/shift_left.c000066400000000000000000000027101414523752600201050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_mod_poly/shift_right.c000066400000000000000000000026521414523752600202750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_mod_poly/sqr.c000066400000000000000000000031641414523752600165670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_sqr(fmpz *res, const fmpz *poly, slong len, const fmpz_t p) { _fmpz_poly_sqr(res, poly, len); _fmpz_vec_scalar_mod_fmpz(res, res, 2 * len - 1, p); } 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, fmpz_mod_ctx_modulus(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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, 2 * len - 1); _fmpz_mod_poly_normalise(res); } } flint2-2.8.4/fmpz_mod_poly/sub.c000066400000000000000000000025551414523752600165560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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_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); } } 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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, max); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/sub_series.c000066400000000000000000000022341414523752600201220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_set_length(res, max); _fmpz_mod_poly_normalise(res); } flint2-2.8.4/fmpz_mod_poly/test/000077500000000000000000000000001414523752600165715ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_poly/test/t-add.c000066400000000000000000000060251414523752600177310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-add_series.c000066400000000000000000000110621414523752600213000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("add_series...."); fflush(stdout); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-berlekamp_massey.c000066400000000000000000000140021414523752600225160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_poly.h" int main(void) { slong i, j, k, l; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); fmpz_mod_ctx_init_ui(ctx, 101); flint_printf("berlekamp_massey...."); fflush(stdout); { 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"); 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); flint_abort(); } /* Check berlekamp-massey does its job - 2k coeffcients 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-compose_divconquer.c000066400000000000000000000112111414523752600230760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("compose_divconquer...."); fflush(stdout); 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_divconquer(c, a, b, ctx); fmpz_mod_poly_compose_divconquer(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"); 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; 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_divconquer(c, a, b, ctx); fmpz_mod_poly_compose_divconquer(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"); 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_divconquer(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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-compose_horner.c000066400000000000000000000112121414523752600222150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("compose_horner...."); fflush(stdout); 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_horner(c, a, b, ctx); fmpz_mod_poly_compose_horner(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"); 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_horner(c, a, b, ctx); fmpz_mod_poly_compose_horner(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"); 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_horner(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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-compose_mod.c000066400000000000000000000146651414523752600215160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("compose_mod...."); fflush(stdout); 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"); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-compose_mod_brent_kung.c000066400000000000000000000153111414523752600237210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung...."); fflush(stdout); 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"); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000210561414523752600270340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung_precomp_preinv...."); fflush(stdout); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-compose_mod_brent_kung_precomp_preinv_threaded.c000066400000000000000000000224071414523752600306750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" #include "thread_support.h" int main(void) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i; fmpz_mod_ctx_t ctx; #endif FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung_precomp_preinv_threaded...."); fflush(stdout); #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) 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_newton(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"); 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_newton(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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; #else FLINT_TEST_CLEANUP(state); flint_printf("SKIPPED\n"); return 0; #endif } flint2-2.8.4/fmpz_mod_poly/test/t-compose_mod_brent_kung_preinv.c000066400000000000000000000227761414523752600253210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung_preinv...."); fflush(stdout); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-compose_mod_brent_kung_vec_preinv.c000066400000000000000000000067301414523752600261460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung_vec_preinv...."); fflush(stdout); 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_newton(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); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-compose_mod_brent_kung_vec_preinv_threaded.c000066400000000000000000000074021414523752600300030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" #include "thread_support.h" int main(void) { int i; int tmul = 200; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 1; #endif flint_printf("compose_mod_brent_kung_vec_preinv_threaded...."); fflush(stdout); 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_newton(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); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-compose_mod_horner.c000066400000000000000000000147551414523752600230730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("compose_mod_horner...."); fflush(stdout); 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"); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-derivative.c000066400000000000000000000110021414523752600213320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("derivative...."); fflush(stdout); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-discriminant.c000066400000000000000000000071331414523752600216660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("discriminant...."); fflush(stdout); 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"); 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"); flint_abort(); } fmpz_clear(n); fmpz_clear(y); fmpz_mod_poly_clear(f, ctx); } FLINT_TEST_CLEANUP(state); fmpz_mod_ctx_clear(ctx); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-div_basecase.c000066400000000000000000000136521414523752600216150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("div_basecase...."); fflush(stdout); fmpz_mod_ctx_init_ui(ctx, 2); /* Compare to divrem_basecase */ 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_basecase(q, a, b, ctx); fmpz_mod_poly_divrem_basecase(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"); 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_basecase(q, a, b, ctx); fmpz_mod_poly_div_basecase(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"); 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_basecase(q, a, b, ctx); fmpz_mod_poly_div_basecase(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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-div_newton_n_preinv.c000066400000000000000000000220631414523752600232550ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("div_newton_n_preinv...."); fflush(stdout); 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_newton (binv, binv, b->length, ctx); fmpz_mod_poly_div_basecase(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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-div_series.c000066400000000000000000000050671414523752600213420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { slong i, j; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("div_series...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-divides.c000066400000000000000000000145461414523752600206370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_mod_poly.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divides...."); fflush(stdout); /* 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-divides_classical.c000066400000000000000000000146561414523752600226570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_mod_poly.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divides_classical...."); fflush(stdout); /* 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-divrem_basecase.c000066400000000000000000000145641414523752600223240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("divrem_basecase...."); fflush(stdout); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-divrem_divconquer.c000066400000000000000000000145671414523752600227400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("divrem_divconquer...."); fflush(stdout); 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_divconquer(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 #1:\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"); 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_divconquer(q, r, a, b, ctx); fmpz_mod_poly_divrem_divconquer(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 #2:\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"); 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_divconquer(q, r, a, b, ctx); fmpz_mod_poly_divrem_divconquer(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 #3:\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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-divrem_f.c000066400000000000000000000125261414523752600207770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("divrem_f...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-divrem_newton_n_preinv.c000066400000000000000000000431271414523752600237650ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("divrem_newton_n_preinv...."); fflush(stdout); 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_newton (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"); 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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-evaluate_fmpz.c000066400000000000000000000061671414523752600220520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("evaluate_fmpz...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-evaluate_fmpz_vec_fast.c000066400000000000000000000050711414523752600237150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("evaluate_fmpz_vec_fast...."); fflush(stdout); 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, 10); 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); fmpz_mod_poly_evaluate_fmpz_vec_iter(y, P, x, npoints, ctx); fmpz_mod_poly_evaluate_fmpz_vec_fast(z, P, x, npoints, ctx); result = _fmpz_vec_equal(y, z, npoints); if (!result) { flint_printf("FAIL:\n"); flint_printf("mod="); fmpz_print(mod); flint_printf(", n=%wd, npoints=%wd\n\n", n, npoints); flint_printf("P: "); fmpz_mod_poly_print(P, ctx); flint_printf("\n\n"); for (j = 0; j < npoints; j++) fmpz_print(y + j), flint_printf(" "); flint_printf("\n"); for (j = 0; j < npoints; j++) fmpz_print(z + j), flint_printf(" "); flint_printf("\n"); abort(); } 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-find_distinct_nonzero_roots.c000066400000000000000000000065071414523752600250270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_poly.h" int main(void) { slong i, j; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("find_distinct_nonzero_roots...."); fflush(stdout); 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); 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); 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); 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); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-frobenius_powers_precomp.c000066400000000000000000000101451414523752600243170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("frobenius_powers_precomp...."); fflush(stdout); 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_newton (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"); 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_newton (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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-gcd_euclidean.c000066400000000000000000000254201414523752600217470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("gcd_euclidean...."); fflush(stdout); 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_euclidean(c, a, b, ctx); fmpz_mod_poly_gcd_euclidean(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"); 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_euclidean(c, a, b, ctx); fmpz_mod_poly_gcd_euclidean(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"); 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_euclidean(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_euclidean(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"); 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_euclidean(c, a, b, ctx); fmpz_mod_poly_gcd_euclidean(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"); 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_euclidean(c, a, b, ctx); fmpz_mod_poly_gcd_euclidean(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"); 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_euclidean(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_euclidean(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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-gcd_euclidean_f.c000066400000000000000000000050061414523752600222520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("gcd_euclidean_f...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-gcd_hgcd.c000066400000000000000000000252701414523752600207260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("gcd_hgcd...."); fflush(stdout); fmpz_mod_ctx_init_ui(ctx, 2); /* Generic case, most likely co-prime arguments ******************************/ /* Check aliasing of a and c */ for (i = 0; i < 30 * 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, 300), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 300), ctx); fmpz_mod_poly_gcd_hgcd(c, a, b, ctx); fmpz_mod_poly_gcd_hgcd(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"); 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 < 30 * 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, 300), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 300), ctx); fmpz_mod_poly_gcd_hgcd(c, a, b, ctx); fmpz_mod_poly_gcd_hgcd(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"); 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 < 20 * 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, 300), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 300), ctx); fmpz_mod_poly_gcd_hgcd(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_hgcd(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"); 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 < 30 * 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, 200), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 200), 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_hgcd(c, a, b, ctx); fmpz_mod_poly_gcd_hgcd(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"); 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 < 30 * 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, 200), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 200), 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_hgcd(c, a, b, ctx); fmpz_mod_poly_gcd_hgcd(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"); 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 < 20 * 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, 200), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 200), 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_euclidean(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_hgcd(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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-gcdinv.c000066400000000000000000000106251414523752600204540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("gcdinv...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-gcdinv_euclidean.c000066400000000000000000000106771414523752600224740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("gcdinv_euclidean...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-get_set_fmpz_poly.c000066400000000000000000000035161414523752600227340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("get/set_fmpz_poly...."); fflush(stdout); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-get_set_nmod_poly.c000066400000000000000000000035641414523752600227200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("get/set_nmod_poly...."); fflush(stdout); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-init_realloc_clear.c000066400000000000000000000040471414523752600230150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("init/init2/realloc/clear...."); fflush(stdout); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-inv_series_newton.c000066400000000000000000000047441414523752600227470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("inv_series_newton...."); fflush(stdout); /* 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_newton(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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-invmod.c000066400000000000000000000152551414523752600205020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("invmod...."); fflush(stdout); 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); 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); 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); 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); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-minpoly.c000066400000000000000000000140211414523752600206630ustar00rootroot00000000000000/* This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 #include "flint.h" #include "fmpz_mod_poly.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.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"); 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"); 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 #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); 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"); 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"); 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); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-mullow.c000066400000000000000000000037371414523752600205270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("mullow...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-mulmod.c000066400000000000000000000153121414523752600204750ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("mulmod...."); fflush(stdout); 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"); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-mulmod_preinv.c000066400000000000000000000242241414523752600220620ustar00rootroot00000000000000/* Copyright (C) 2012 Lina Kulakova Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("mulmod_preinv...."); fflush(stdout); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-neg.c000066400000000000000000000035011414523752600177460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("neg...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-pow_trunc.c000066400000000000000000000071501414523752600212210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("pow_trunc...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-pow_trunc_binexp.c000066400000000000000000000071751414523752600225750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("pow_trunc_binexp...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-powers_mod_bsgs.c000077500000000000000000000061151414523752600224000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i, result, max_threads = 5; fmpz_mod_ctx_t ctx; #endif FLINT_TEST_INIT(state); flint_printf("powers_mod_bsgs...."); fflush(stdout); #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); #else FLINT_TEST_CLEANUP(state); flint_printf("SKIPPED\n"); #endif return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-powers_mod_naive.c000077500000000000000000000054701414523752600225470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("powers_mod_naive...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-powmod_fmpz_binexp.c000066400000000000000000000166141414523752600231140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("powmod_fmpz_binexp...."); fflush(stdout); 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"); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-powmod_fmpz_binexp_preinv.c000066400000000000000000000236651414523752600245030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("powmod_fmpz_binexp_preinv...."); fflush(stdout); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-powmod_ui_binexp.c000066400000000000000000000162471414523752600225570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("powmod_ui_binexp...."); fflush(stdout); 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"); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-powmod_ui_binexp_preinv.c000066400000000000000000000227401414523752600241350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("powmod_ui_binexp_preinv...."); fflush(stdout); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-powmod_x_fmpz_preinv.c000066400000000000000000000176711414523752600234650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("powmod_x_fmpz_preinv...."); fflush(stdout); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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_newton (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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-print_read.c000066400000000000000000000150521414523752600213300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ #undef __STRICT_ANSI__ #endif #include #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) #include #endif #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) int main(void) { int i, j, n, result; FILE *in, *out; int fd[2]; pid_t childpid; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); n = 100 * flint_test_multiplier(); fmpz_mod_ctx_init_ui(ctx, 2); flint_printf("print/ read...."); fflush(stdout); /* 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"); abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); 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"); 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"); 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"); 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"); 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"); abort(); } ++i; } fmpz_mod_poly_clear(t, newctx); fmpz_mod_ctx_clear(newctx); fclose(in); } if (i != n) { flint_printf("FAIL:\n"); flint_printf("Only %d out of %d objects were processed.\n", i, n); 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"); abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); 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"); abort(); } r = flint_fprintf(out, "blah"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); 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"); abort(); } fmpz_mod_poly_init(t, ctx); 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); abort(); } } fmpz_mod_poly_clear(t, newctx); fmpz_mod_ctx_clear(newctx); fclose(in); } } fmpz_mod_ctx_clear(ctx); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #else int main(void) { flint_printf("print/ read...."); fflush(stdout); flint_printf("SKIPPED\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fmpz_mod_poly/test/t-product_roots_fmpz_vec.c000066400000000000000000000044731414523752600240050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" #include "fmpz_mod_poly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("product_roots_fmpz_vec...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-radix.c000066400000000000000000000074671414523752600203230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.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; } int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("radix...."); fflush(stdout); 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"); } 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-randtest_monic_primitive.c000066400000000000000000000025371414523752600243060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("randtest_monic_primitive...."); fflush(stdout); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-rem_basecase.c000066400000000000000000000136551414523752600216210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("rem_basecase...."); fflush(stdout); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-resultant.c000066400000000000000000000076151414523752600212300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("resultant...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-resultant_euclidean.c000066400000000000000000000077131414523752600232400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("resultant_euclidean...."); fflush(stdout); fmpz_mod_ctx_init_ui(ctx, 2); /* Check res(f, g) == (-1)^(deg f deg g) res(g, f) */ for (i = 0; i < 100 * 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, 100), ctx); fmpz_mod_poly_randtest(g, state, n_randint(state, 100), ctx); fmpz_mod_poly_resultant_euclidean(x, f, g, ctx); fmpz_mod_poly_resultant_euclidean(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"); 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 < 100 * 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, 100), ctx); fmpz_mod_poly_randtest(g, state, n_randint(state, 100), ctx); fmpz_mod_poly_randtest(h, state, n_randint(state, 100), ctx); fmpz_mod_poly_resultant_euclidean(y, f, g, ctx); fmpz_mod_poly_resultant_euclidean(z, h, g, ctx); fmpz_mod_mul(y, y, z, ctx); fmpz_mod_poly_mul(f, f, h, ctx); fmpz_mod_poly_resultant_euclidean(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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-resultant_hgcd.c000066400000000000000000000076451414523752600222200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("resultant_hgcd...."); fflush(stdout); 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_hgcd(x, f, g, ctx); fmpz_mod_poly_resultant_hgcd(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"); 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_hgcd(y, f, g, ctx); fmpz_mod_poly_resultant_hgcd(z, h, g, ctx); fmpz_mod_mul(y, y, z, ctx); fmpz_mod_poly_mul(f, f, h, ctx); fmpz_mod_poly_resultant_hgcd(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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-scalar_div_fmpz.c000066400000000000000000000065121414523752600223450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("scalar_div_fmpz...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-scalar_mul_fmpz.c000066400000000000000000000035421414523752600223600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpz...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-set_equal.c000066400000000000000000000054631414523752600211700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("set/equal...."); fflush(stdout); 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"); 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"); abort(); } fmpz_clear(x); fmpz_mod_poly_clear(a, ctx); fmpz_mod_poly_clear(b, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-set_trunc.c000066400000000000000000000044341414523752600212110ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("set_trunc...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-shift_left_right.c000066400000000000000000000075771414523752600225420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("shift_left/right...."); fflush(stdout); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-sub.c000066400000000000000000000104561414523752600177750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); 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"); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-sub_series.c000066400000000000000000000110251414523752600213400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("sub_series...."); fflush(stdout); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-swap.c000066400000000000000000000036111414523752600201510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("swap...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-xgcd.c000066400000000000000000000121241414523752600201230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("xgcd...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-xgcd_euclidean.c000066400000000000000000000122221414523752600221330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("xgcd_euclidean...."); fflush(stdout); 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_euclidean(d, a, b, ctx); fmpz_mod_poly_xgcd_euclidean(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"); 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_euclidean(d, a, b, ctx); fmpz_mod_poly_xgcd_euclidean(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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-xgcd_hgcd.c000066400000000000000000000121531414523752600211120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("xgcd_hgcd...."); fflush(stdout); 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 < 50 * 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, 300), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 300), ctx); fmpz_mod_poly_gcd_hgcd(d, a, b, ctx); fmpz_mod_poly_xgcd_hgcd(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"); 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 < 50 * 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, 300), ctx); fmpz_mod_poly_randtest(b, state, n_randint(state, 300), 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_hgcd(d, a, b, ctx); fmpz_mod_poly_xgcd_hgcd(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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/test/t-zero.c000066400000000000000000000030441414523752600201560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("zero...."); fflush(stdout); 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"); flint_abort(); } fmpz_mod_poly_clear(a, ctx); fmpz_clear(p); } fmpz_mod_ctx_clear(ctx); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly/tree.c000066400000000000000000000052451414523752600167230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz_vec.h" #include "fmpz_poly.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_t mod) { 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, mod); } 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, mod); _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, mod); _fmpz_poly_set_length(pb, pa->length + (pa + 1)->length - 1); } else if (left > 0) fmpz_poly_set(pb, pa); } } flint2-2.8.4/fmpz_mod_poly/xgcd_euclidean.c000066400000000000000000000147371414523752600207300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_vec.h" #include "fmpz_mod_poly.h" slong _fmpz_mod_poly_xgcd_euclidean(fmpz *G, fmpz *S, fmpz *T, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t invB, const fmpz_t p) { _fmpz_vec_zero(G, lenB); _fmpz_vec_zero(S, lenB - 1); _fmpz_vec_zero(T, lenA - 1); if (lenB == 1) { fmpz_set(G + 0, B + 0); fmpz_one(T + 0); return 1; } else { fmpz *Q, *R; slong lenQ, lenR; TMP_INIT; TMP_START; FMPZ_VEC_TMP_INIT(Q, 2*lenA); R = Q + lenA; _fmpz_mod_poly_divrem(Q, R, A, lenA, B, lenB, invB, p); lenR = lenB - 1; FMPZ_VEC_NORM(R, lenR); if (lenR == 0) { _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 lenD, 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_invmod(inv, V3 + (lenV3 - 1), p); _fmpz_mod_poly_divrem_basecase(Q, D, D, lenD, V3, lenV3, inv, p); lenQ = lenD - lenV3 + 1; lenD = lenV3 - 1; FMPZ_VEC_NORM(D, lenD); if (lenV1 >= lenQ) _fmpz_mod_poly_mul(W, V1, lenV1, Q, lenQ, p); else _fmpz_mod_poly_mul(W, Q, lenQ, V1, lenV1, p); lenW = lenQ + lenV1 - 1; _fmpz_mod_poly_sub(U, U, lenU, W, lenW, p); 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, p); _fmpz_mod_poly_neg(Q, Q, lenQ, p); _fmpz_mod_poly_add(Q, G, lenD, Q, lenQ, p); _fmpz_mod_poly_divrem(T, W, Q, lenQ, B, lenB, invB, p); } FMPZ_VEC_TMP_CLEAR(W, FLINT_MAX(5*lenB, lenA + lenB)); FMPZ_VEC_TMP_CLEAR(Q, 2*lenA); fmpz_clear(inv); TMP_END; return lenD; } } } void fmpz_mod_poly_xgcd_euclidean(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(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_euclidean(g, s, t, A->coeffs, lenA, B->coeffs, lenB, inv, p); 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); } } flint2-2.8.4/fmpz_mod_poly/xgcd_euclidean_f.c000066400000000000000000000156571414523752600212370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_vec.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_t p) { _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, p); 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), p); if (!fmpz_is_one(f)) goto cleanup; _fmpz_mod_poly_divrem_basecase(Q, D, D, lenD, V3, lenV3, inv, p); lenQ = lenD - lenV3 + 1; lenD = lenV3 - 1; FMPZ_VEC_NORM(D, lenD); if (lenV1 >= lenQ) _fmpz_mod_poly_mul(W, V1, lenV1, Q, lenQ, p); else _fmpz_mod_poly_mul(W, Q, lenQ, V1, lenV1, p); lenW = lenQ + lenV1 - 1; _fmpz_mod_poly_sub(U, U, lenU, W, lenW, p); 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, p); _fmpz_mod_poly_neg(Q, Q, lenQ, p); _fmpz_mod_poly_add(Q, G, lenD, Q, lenQ, p); _fmpz_mod_poly_divrem(T, W, Q, lenQ, B, lenB, invB, p); } 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, p); 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); } } flint2-2.8.4/fmpz_mod_poly/xgcd_hgcd.c000066400000000000000000000322631414523752600176760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "mpn_extras.h" /* We define a whole bunch of macros here which essentially provide the nmod_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 __set(B, lenB, A, lenA) \ do { \ _fmpz_vec_set((B), (A), (lenA)); \ (lenB) = (lenA); \ } while (0) #define __add(C, lenC, A, lenA, B, lenB) \ do { \ _fmpz_mod_poly_add((C), (A), (lenA), (B), (lenB), mod); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ FMPZ_VEC_NORM((C), (lenC)); \ } while (0) #define __sub(C, lenC, A, lenA, B, lenB) \ do { \ _fmpz_mod_poly_sub((C), (A), (lenA), (B), (lenB), mod); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ FMPZ_VEC_NORM((C), (lenC)); \ } while (0) #define __mul(C, lenC, A, lenA, B, lenB) \ do { \ if ((lenA) != 0 && (lenB) != 0) \ { \ if ((lenA) >= (lenB)) \ _fmpz_mod_poly_mul((C), (A), (lenA), (B), (lenB), mod); \ else \ _fmpz_mod_poly_mul((C), (B), (lenB), (A), (lenA), mod); \ (lenC) = (lenA) + (lenB) - 1; \ } \ else \ { \ (lenC) = 0; \ } \ } while (0) #define __divrem(Q, lenQ, R, lenR, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ fmpz_invmod(invB, B + lenB - 1, mod); \ _fmpz_mod_poly_divrem((Q), (R), (A), (lenA), (B), (lenB), invB, mod); \ (lenQ) = (lenA) - (lenB) + 1; \ (lenR) = (lenB) - 1; \ FMPZ_VEC_NORM((R), (lenR)); \ } \ else \ { \ _fmpz_vec_set((R), (A), (lenA)); \ (lenQ) = 0; \ (lenR) = (lenA); \ } \ } while (0) #define __div(Q, lenQ, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ fmpz * __t = _fmpz_vec_init(lenB - 1); \ fmpz_invmod(invB, B + lenB - 1, mod); \ _fmpz_mod_poly_divrem((Q), __t, (A), (lenA), (B), (lenB), invB, mod); \ _fmpz_vec_clear(__t, lenB - 1); \ (lenQ) = (lenA) - (lenB) + 1; \ } \ else \ { \ (lenQ) = 0; \ } \ } while (0) slong _fmpz_mod_poly_xgcd_hgcd(fmpz *G, fmpz *S, fmpz *T, const fmpz *A, slong lenA, const fmpz *B, slong lenB, const fmpz_t mod) { slong lenG, lenS, lenT; if (lenB == 1) { fmpz_set(G + 0, B + 0); fmpz_set_ui(T, 1); lenG = 1; lenS = 0; lenT = 1; } else { slong lenq, lenr, len1 = lenA + lenB; fmpz *q = _fmpz_vec_init(len1); fmpz *r = q + lenA; fmpz_t invB; fmpz_init(invB); __divrem(q, lenq, r, lenr, A, lenA, B, lenB); if (lenr == 0) { __set(G, lenG, B, lenB); fmpz_set_ui(T + 0, 1); lenS = 0; lenT = 1; } else { fmpz *h, *j, *v, *w, *R[4], *X; slong lenh, lenj, lenv, lenw, lenR[4], len2; int 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]; X = _fmpz_vec_init(len2); h = X; j = h + lenh; v = j + lenj; w = v + lenv; R[0] = w + lenw; R[1] = R[0] + lenR[0]; R[2] = R[1] + lenR[1]; R[3] = R[2] + lenR[2]; sgnR = _fmpz_mod_poly_hgcd(R, lenR, h, &lenh, j, &lenj, B, lenB, r, lenr, mod); if (sgnR > 0) { _fmpz_mod_poly_neg(S, R[1], lenR[1], mod); _fmpz_vec_set(T, R[0], lenR[0]); } else { _fmpz_vec_set(S, R[1], lenR[1]); _fmpz_mod_poly_neg(T, R[0], lenR[0], mod); } lenS = lenR[1]; lenT = lenR[0]; while (lenj != 0) { __divrem(q, lenq, r, lenr, h, lenh, j, lenj); __mul(v, lenv, q, lenq, T, lenT); { slong l; _fmpz_vec_swap(S, T, FLINT_MAX(lenS, lenT)); 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 < FMPZ_MOD_POLY_GCD_CUTOFF) { fmpz *u0 = R[0], *u1 = R[1]; slong lenu0 = lenr - 1, lenu1 = lenj - 1; fmpz_invmod(invB, r + lenr - 1, mod); lenG = _fmpz_mod_poly_xgcd_euclidean(G, u0, u1, j, lenj, r, lenr, invB, mod); FMPZ_VEC_NORM(u0, lenu0); FMPZ_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; } sgnR = _fmpz_mod_poly_hgcd(R, lenR, h, &lenh, j, &lenj, j,lenj, r, lenr, mod); __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 > WORD(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); _fmpz_vec_clear(X, len2); } _fmpz_vec_clear(q, len1); fmpz_clear(invB); } _fmpz_vec_zero(S + lenS, lenB - 1 - lenS); _fmpz_vec_zero(T + lenT, lenA - 1 - lenT); return lenG; } void fmpz_mod_poly_xgcd_hgcd(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_hgcd(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; slong lenS, lenT; 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, A->coeffs + lenA - 1, p); fmpz_mod_poly_scalar_mul_fmpz(G, A, inv, ctx); fmpz_mod_poly_zero(T, ctx); fmpz_mod_poly_set_coeff_fmpz(S, 0, inv, ctx); _fmpz_mod_poly_set_length(S, 1); } else if (lenB == 1) /* lenA >= lenB = 1 */ { fmpz_mod_poly_fit_length(T, 1, ctx); _fmpz_mod_poly_set_length(T, 1); fmpz_invmod(inv, B->coeffs + 0, p); fmpz_set(T->coeffs + 0, inv); fmpz_mod_poly_set_coeff_ui(G, 0, 1, ctx); _fmpz_mod_poly_set_length(G, 1); fmpz_mod_poly_zero(S, ctx); } else /* lenA >= lenB >= 2 */ { 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(FLINT_MAX(lenB - 1, 2)); } else { fmpz_mod_poly_fit_length(S, FLINT_MAX(lenB - 1, 2), ctx); s = S->coeffs; } if (T == A || T == B) { t = _fmpz_vec_init(FLINT_MAX(lenA - 1, 2)); } else { fmpz_mod_poly_fit_length(T, FLINT_MAX(lenA - 1, 2), ctx); t = T->coeffs; } if (lenA >= lenB) lenG = _fmpz_mod_poly_xgcd_hgcd(g, s, t, A->coeffs, lenA, B->coeffs, lenB, p); else lenG = _fmpz_mod_poly_xgcd_hgcd(g, t, s, B->coeffs, lenB, A->coeffs, lenA, p); if (G == A || G == B) { _fmpz_vec_clear(G->coeffs, FLINT_MIN(lenA, lenB)); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); } if (S == A || S == B) { _fmpz_vec_clear(S->coeffs, FLINT_MAX(lenB - 1, 2)); S->coeffs = s; S->alloc = FLINT_MAX(lenB - 1, 2); } if (T == A || T == B) { _fmpz_vec_clear(T->coeffs, FLINT_MAX(lenA - 1, 2)); T->coeffs = t; T->alloc = FLINT_MAX(lenA - 1, 2); } _fmpz_mod_poly_set_length(G, lenG); lenS = FLINT_MAX(lenB - lenG, 1); lenT = FLINT_MAX(lenA - lenG, 1); FMPZ_VEC_NORM(S->coeffs, lenS); FMPZ_VEC_NORM(T->coeffs, lenT); _fmpz_mod_poly_set_length(S, lenS); _fmpz_mod_poly_set_length(T, lenT); if (!fmpz_is_one(G->coeffs + lenG - 1)) { fmpz_invmod(inv, G->coeffs + lenG - 1, 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); } } #undef __set #undef __add #undef __sub #undef __mul #undef __divrem #undef __div flint2-2.8.4/fmpz_mod_poly/zero_coeffs.c000066400000000000000000000015621414523752600202660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } } flint2-2.8.4/fmpz_mod_poly_factor.h000066400000000000000000000164461414523752600173340ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPZ_MOD_POLY_FACTOR_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #ifdef __cplusplus extern "C" { #endif /* Factoring ****************************************************************/ 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]; FLINT_DLL 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; FLINT_DLL void fmpz_mod_poly_factor_clear(fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_factor_realloc(fmpz_mod_poly_factor_t fac, slong alloc, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_factor_fit_length(fmpz_mod_poly_factor_t fac, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL 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); FLINT_DLL void fmpz_mod_poly_factor_print(const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fmpz_mod_poly_factor_pow(fmpz_mod_poly_factor_t fac, slong exp, const fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_poly_is_irreducible(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_poly_is_irreducible_ddf(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_poly_is_irreducible_rabin(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_poly_is_irreducible_rabin_f(fmpz_t fac, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); FLINT_DLL int _fmpz_mod_poly_is_squarefree(const fmpz * f, slong len, const fmpz_t p); FLINT_DLL int _fmpz_mod_poly_is_squarefree_f(fmpz_t fac, const fmpz * f, slong len, const fmpz_t p); FLINT_DLL int fmpz_mod_poly_is_squarefree(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); FLINT_DLL int fmpz_mod_poly_is_squarefree_f(fmpz_t fac, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mod_poly_factor_squarefree(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); FLINT_DLL void fmpz_mod_poly_factor(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mod_poly_factor_berlekamp(fmpz_mod_poly_factor_t factors, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_poly_interval_poly_worker(void * arg_ptr); /* Roots *********************************************************************/ FLINT_DLL 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); FLINT_DLL 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); /* Inlines *******************************************************************/ FLINT_DLL 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 flint2-2.8.4/fmpz_mod_poly_factor/000077500000000000000000000000001414523752600171505ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_poly_factor/clear.c000066400000000000000000000015371414523752600204100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_mod_poly.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); } flint2-2.8.4/fmpz_mod_poly_factor/concat.c000066400000000000000000000015701414523752600205660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_mod_poly.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); } flint2-2.8.4/fmpz_mod_poly_factor/factor.c000066400000000000000000000014751414523752600206010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.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); } flint2-2.8.4/fmpz_mod_poly_factor/factor_berlekamp.c000066400000000000000000000202031414523752600226110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.h" #include "fmpz_mat.h" #include "ulong_extras.h" #include "profiler.h" #include "perm.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, *perm; 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 */ perm = _perm_init(n); nullity = n - fmpz_mat_rref_mod(perm, matrix, p); _perm_clear(perm); /* 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); } flint2-2.8.4/fmpz_mod_poly_factor/factor_cantor_zassenhaus.c000066400000000000000000000043241414523752600244070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.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); } flint2-2.8.4/fmpz_mod_poly_factor/factor_distinct_deg.c000066400000000000000000000204061414523752600233140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "fmpz_mod_poly.h" /* 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_newton(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_newton(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); } flint2-2.8.4/fmpz_mod_poly_factor/factor_distinct_deg_threaded.c000066400000000000000000000600621414523752600251560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "fmpz_mod_poly.h" #include "thread_support.h" 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; const fmpz * p = fmpz_mod_ctx_modulus(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, p); } 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, j, 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; const fmpz * p = fmpz_mod_ctx_modulus(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, p); 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++) { for (j = 0; j < n; j++) fmpz_mod(C->rows[i] + j, C->rows[i] + j, p); } /* 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, p); 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, p); _fmpz_mod_poly_add(res->coeffs, t, n, C->rows[i], n, p); } _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, p); _fmpz_mod_poly_sub(tmp, H->coeffs, H->length, tmp, v->length - 1, p); _fmpz_mod_poly_mulmod_preinv(res->coeffs, tmp, v->length - 1, res->coeffs, v->length - 1, v->coeffs, v->length, vinv->coeffs, vinv->length, p); } 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_newton(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_newton(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_newton(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_newton(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); } flint2-2.8.4/fmpz_mod_poly_factor/factor_equal_deg.c000066400000000000000000000357101414523752600226060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "ulong_extras.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_newton(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 if (fmpz_mod_poly_degree(S[k].f, ctx) > d) { FLINT_ASSERT(S[k].g->length == 2); fmpz_mod_poly_scalar_mul_fmpz(tr, S[k].a, S[k].g->coeffs + 1, ctx); 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_newton(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_newton(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); } } flint2-2.8.4/fmpz_mod_poly_factor/factor_equal_deg_prob.c000066400000000000000000000052221414523752600236230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "ulong_extras.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_printf("Exception (fmpz_mod_poly_factor_equal_deg_prob): \n"); flint_printf("Input polynomial is linear.\n"); flint_abort(); } 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_newton(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; } flint2-2.8.4/fmpz_mod_poly_factor/factor_kaltofen_shoup.c000066400000000000000000000053571414523752600237050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.h" #include "thread_support.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_newton(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); } flint2-2.8.4/fmpz_mod_poly_factor/factor_squarefree.c000066400000000000000000000102701414523752600230140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "ulong_extras.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); 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); } flint2-2.8.4/fmpz_mod_poly_factor/fit_length.c000066400000000000000000000015711414523752600214430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.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); } } flint2-2.8.4/fmpz_mod_poly_factor/init.c000066400000000000000000000015171414523752600202630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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; } flint2-2.8.4/fmpz_mod_poly_factor/inlines.c000066400000000000000000000014611414523752600207570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_MOD_POLY_FACTOR_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpz_mod_poly.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); } flint2-2.8.4/fmpz_mod_poly_factor/insert.c000066400000000000000000000027651414523752600206320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.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++; } flint2-2.8.4/fmpz_mod_poly_factor/is_irreducible.c000066400000000000000000000015111414523752600222760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.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; } flint2-2.8.4/fmpz_mod_poly_factor/is_irreducible_ddf.c000066400000000000000000000115711414523752600231220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "fmpz_mod_poly.h" 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); if (!(h = flint_malloc((2 * m + l + 1) * sizeof(fmpz_mod_poly_struct)))) { flint_printf("Exception (fmpz_mod_poly_is_irreducible_ddf): \n"); flint_printf("Not enough memory.\n"); flint_abort(); } 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_newton(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; } flint2-2.8.4/fmpz_mod_poly_factor/is_irreducible_rabin.c000066400000000000000000000061521414523752600234570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.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_newton(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; } flint2-2.8.4/fmpz_mod_poly_factor/is_irreducible_rabin_f.c000066400000000000000000000055411414523752600237650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mod_poly.h" #include "ulong_extras.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_newton_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; } flint2-2.8.4/fmpz_mod_poly_factor/is_squarefree.c000066400000000000000000000026731414523752600221610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include int _fmpz_mod_poly_is_squarefree(const fmpz * f, slong len, const fmpz_t p) { fmpz * fd, * g; fmpz_t invd; 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, p); dlen = len - 1; FMPZ_VEC_NORM(fd, dlen); if (dlen) { fmpz_init(invd); fmpz_invmod(invd, fd + dlen - 1, p); res = (_fmpz_mod_poly_gcd(g, f, len, fd, dlen, invd, p) == 1); fmpz_clear(invd); } 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, fmpz_mod_ctx_modulus(ctx)); } flint2-2.8.4/fmpz_mod_poly_factor/is_squarefree_f.c000066400000000000000000000030041414523752600224530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include int _fmpz_mod_poly_is_squarefree_f(fmpz_t fac, const fmpz * f, slong len, const fmpz_t p) { 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, p); dlen = len - 1; FMPZ_VEC_NORM(fd, dlen); if (dlen) { fmpz_init(invd); fmpz_gcdinv(fac, invd, fd + dlen - 1, p); if (fmpz_is_one(fac)) res = (_fmpz_mod_poly_gcd_euclidean_f(fac, g, f, len, fd, dlen, p) == 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, fmpz_mod_ctx_modulus(ctx)); } flint2-2.8.4/fmpz_mod_poly_factor/pow.c000066400000000000000000000015011414523752600201160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.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; } flint2-2.8.4/fmpz_mod_poly_factor/print.c000066400000000000000000000016611414523752600204540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_mod_poly.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]); } } flint2-2.8.4/fmpz_mod_poly_factor/profile/000077500000000000000000000000001414523752600206105ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_poly_factor/profile/p-factor.c000066400000000000000000000261301414523752600224710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include #include "flint.h" #include "fmpz_mod_poly.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) { FLINT_TEST_INIT(state); 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}; 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 EXIT_SUCCESS; } flint2-2.8.4/fmpz_mod_poly_factor/profile/p-factor_equal_deg.c000066400000000000000000000056321414523752600245030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_poly.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; } flint2-2.8.4/fmpz_mod_poly_factor/realloc.c000066400000000000000000000040261414523752600207370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.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; } } flint2-2.8.4/fmpz_mod_poly_factor/roots.c000066400000000000000000000151551414523752600204710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" #include "fmpz.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_newton(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); } flint2-2.8.4/fmpz_mod_poly_factor/roots_factored.c000066400000000000000000000223721414523752600223370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" #include "fmpz.h" #include "fmpq.h" #include "long_extras.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(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) { 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; } flint2-2.8.4/fmpz_mod_poly_factor/set.c000066400000000000000000000024021414523752600201050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_mod_poly.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; } } } flint2-2.8.4/fmpz_mod_poly_factor/test/000077500000000000000000000000001414523752600201275ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_poly_factor/test/t-factor.c000066400000000000000000000077531414523752600220260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int iter; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("factor...."); fflush(stdout); 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); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factor/test/t-factor_berlekamp.c000066400000000000000000000077771414523752600240560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int iter; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("factor_berlekamp...."); fflush(stdout); 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); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factor/test/t-factor_cantor_zassenhaus.c000066400000000000000000000100171414523752600256230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int iter; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("factor_cantor_zassenhaus...."); fflush(stdout); 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); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factor/test/t-factor_distinct_deg.c000066400000000000000000000107311414523752600245340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.h" #include "ulong_extras.h" #define MAX_DEG 7 int main(void) { int iter; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("factor_distinct_deg...."); fflush(stdout); 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."); 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]]); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factor/test/t-factor_distinct_deg_threaded.c000066400000000000000000000115261414523752600263770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.h" #include "ulong_extras.h" #include "flint.h" #include "thread_support.h" #define MAX_DEG 9 int main(void) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int iter; fmpz_mod_ctx_t ctx; #endif FLINT_TEST_INIT(state); flint_printf("factor_distinct_deg_threaded...."); fflush(stdout); #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) 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."); 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]]); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; #else FLINT_TEST_CLEANUP(state); flint_printf("SKIPPED\n"); return 0; #endif } flint2-2.8.4/fmpz_mod_poly_factor/test/t-factor_equal_deg_prob.c000066400000000000000000000053601414523752600250460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int iter; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("factor_equal_deg_prob...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factor/test/t-factor_kaltofen_shoup.c000066400000000000000000000100111414523752600251040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int iter; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("factor_kaltofen_shoup...."); fflush(stdout); 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); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factor/test/t-factor_squarefree.c000066400000000000000000000074461414523752600242470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int iter; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("factor_squarefree...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factor/test/t-interval_threaded.c000066400000000000000000000126021414523752600242210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #include #define ulong mp_limb_t #include "flint.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" #include "thread_support.h" int main(void) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i; fmpz_mod_ctx_t ctx; #endif FLINT_TEST_INIT(state); flint_printf("interval_threaded...."); fflush(stdout); #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) 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_newton(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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; #else FLINT_TEST_CLEANUP(state); flint_printf("SKIPPED\n"); return 0; #endif } flint2-2.8.4/fmpz_mod_poly_factor/test/t-is_irreducible.c000066400000000000000000000046161414523752600235270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int iter; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("is_irreducible...."); fflush(stdout); 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"); abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly2, ctx); } fmpz_mod_ctx_clear(ctx); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factor/test/t-is_irreducible_ddf.c000066400000000000000000000046361414523752600243460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int iter; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("is_irreducible_ddf...."); fflush(stdout); 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"); abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly2, ctx); } fmpz_mod_ctx_clear(ctx); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factor/test/t-is_irreducible_rabin.c000066400000000000000000000046461414523752600247050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int iter; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("is_irreducible_rabin...."); fflush(stdout); 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"); abort(); } fmpz_clear(modulus); fmpz_mod_poly_clear(poly1, ctx); fmpz_mod_poly_clear(poly2, ctx); } fmpz_mod_ctx_clear(ctx); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factor/test/t-is_squarefree.c000066400000000000000000000054361414523752600234010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" int main(void) { int iter; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("is_squarefree...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factor/test/t-roots.c000066400000000000000000000074031414523752600217060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" 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"); flint_abort(); } if (!fmpz_is_one(roots->poly[i].coeffs + 1)) { flint_printf("FAILED:\ncheck root is monic\n"); 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"); flint_abort(); } if (roots->exp[i] != (want_mult ? multiplicity : 1)) { flint_printf("FAILED:\ncheck root multiplicity\n"); flint_abort(); } } fmpz_mod_poly_roots(roots, q, want_mult, ctx); if (roots->num > 0) { flint_printf("FAILED:\ncheck missing roots\n"); flint_abort(); } fmpz_mod_poly_clear(q, ctx); fmpz_mod_poly_clear(qt, ctx); fmpz_mod_poly_clear(r, ctx); } int main(void) { slong i, j, k, l; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("roots...."); fflush(stdout); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factor/test/t-roots_factored.c000066400000000000000000000162241414523752600235560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "fmpz_mod_poly_factor.h" #include "ulong_extras.h" 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"); 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"); flint_abort(); } if (!fmpz_is_one(roots->poly[i].coeffs + 1)) { flint_printf("FAILED:\ncheck root is monic\n"); 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"); flint_abort(); } if (roots->exp[i] != (want_mult ? multiplicity : 1)) { flint_printf("FAILED:\ncheck root multiplicity\n"); 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"); flint_abort(); } found = 1; } } if (!found) { flint_printf("FAILED:\ncheck missing roots\n"); 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); } int main(void) { slong i, j, k, l; fmpz_mod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("roots_factored...."); fflush(stdout); 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"); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mod_poly_factorxx.h000066400000000000000000000115741414523752600177110ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MOD_POLY_FACTORXX_H #define FMPZ_MOD_POLY_FACTORXX_H #include "fmpz_mod_poly.h" namespace flint { class fmpz_mod_poly_factorxx { private: fmpz_mod_poly_factor_t inner; fmpz_modxx_ctx_srcref ctx; public: fmpz_mod_poly_factorxx(fmpz_modxx_ctx_srcref c) : ctx(c) { fmpz_mod_poly_factor_init(inner, ctx._ctx()); } ~fmpz_mod_poly_factorxx() { fmpz_mod_poly_factor_clear(inner, ctx._ctx()); } fmpz_mod_poly_factorxx(const fmpz_mod_poly_factorxx& o) : ctx(o.ctx) { fmpz_mod_poly_factor_init(inner, ctx._ctx()); fmpz_mod_poly_factor_set(inner, o.inner, ctx._ctx()); } bool operator==(const fmpz_mod_poly_factorxx& o) { if(o.size() != size()) return false; for(slong i = 0;i < size();++i) if(p(i) != o.p(i) || exp(i) != o.exp(i)) return false; return true; } fmpz_mod_poly_factorxx& operator=(const fmpz_mod_poly_factorxx& o) { fmpz_mod_poly_factor_set(inner, o.inner, ctx._ctx()); return *this; } slong size() const {return inner->num;} slong exp(slong i) const {return inner->exp[i];} slong& exp(slong i) {return inner->exp[i];} fmpz_mod_polyxx p(slong i) const { fmpz_mod_polyxx p(ctx); fmpz_mod_poly_set(p._poly(), inner->poly + i, ctx._ctx()); return p; } fmpz_mod_poly_factor_t& _data() {return inner;} const fmpz_mod_poly_factor_t& _data() const {return inner;} void realloc(slong a) {fmpz_mod_poly_factor_realloc(inner, a, ctx._ctx());} void fit_length(slong a) {fmpz_mod_poly_factor_fit_length(inner, a, ctx._ctx());} void print() const {fmpz_mod_poly_factor_print(inner, ctx._ctx());} template void insert(const Fmpz_mod_poly& p, slong e, typename mp::enable_if >::type* = 0) {fmpz_mod_poly_factor_insert(_data(), p.evaluate()._poly(), e, ctx._ctx());} void concat(const fmpz_mod_poly_factorxx& o) {fmpz_mod_poly_factor_concat(_data(), o._data(), ctx._ctx());} void pow(slong exp) {fmpz_mod_poly_factor_pow(_data(), exp, ctx._ctx());} #define FMPZ_MOD_POLY_FACTORXX_DEFINE_SET_FACTOR(name) \ template \ void set_##name(const Fmpz_mod_poly& p, \ typename mp::enable_if >::type* = 0) \ {fmpz_mod_poly_##name(_data(), p.evaluate()._poly(), ctx._ctx());} FMPZ_MOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor) FMPZ_MOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_squarefree) FMPZ_MOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_cantor_zassenhaus) FMPZ_MOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_berlekamp) FMPZ_MOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_kaltofen_shoup) template bool set_factor_equal_deg_probab(frandxx& state, const Fmpz_mod_poly& p, slong d, typename mp::enable_if >::type* = 0) { return fmpz_mod_poly_factor_equal_deg_prob(_data(), state._data(), p.evaluate()._poly(), d); } template void set_factor_equal_deg(const Fmpz_mod_poly& p, slong d, typename mp::enable_if >::type* = 0) { fmpz_mod_poly_factor_equal_deg(_data(), p.evaluate()._poly(), d, ctx._ctx()); } template void set_factor_distinct_deg(const Fmpz_mod_poly& p, std::vector& degs, typename mp::enable_if >::type* = 0) { slong* dgs = °s.front(); fmpz_mod_poly_factor_distinct_deg(_data(), p.evaluate()._poly(), &dgs, ctx._ctx()); } }; #define FMPZ_MOD_POLY_FACTORXX_DEFINE_FACTOR(name) \ template \ fmpz_mod_poly_factorxx name(const Fmpz_mod_poly& p, \ typename mp::enable_if >::type* = 0) \ { \ fmpz_mod_poly_factorxx res(p.evaluate().get_ctx()); \ res.set_##name(p); \ return res; \ } FMPZ_MOD_POLY_FACTORXX_DEFINE_FACTOR(factor) FMPZ_MOD_POLY_FACTORXX_DEFINE_FACTOR(factor_squarefree) FMPZ_MOD_POLY_FACTORXX_DEFINE_FACTOR(factor_cantor_zassenhaus) FMPZ_MOD_POLY_FACTORXX_DEFINE_FACTOR(factor_berlekamp) FMPZ_MOD_POLY_FACTORXX_DEFINE_FACTOR(factor_kaltofen_shoup) // TODO do we want global versions of factor_distinct_deg etc? inline void print(const fmpz_mod_poly_factorxx& f) { f.print(); } } // flint #endif flint2-2.8.4/fmpz_mod_polyxx.h000066400000000000000000000737101414523752600163530ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_MOD_POLYXX_H #define FMPZ_MOD_POLYXX_H #include "fmpz_mod_poly.h" #include "fmpzxx.h" #include "fmpz_polyxx.h" #include "nmod_polyxx.h" #include "flintxx/expression.h" #include "flintxx/flint_classes.h" #include "flintxx/flint_exception.h" #include "flintxx/frandxx.h" #include "flintxx/ltuple.h" #include "flintxx/stdmath.h" #include "flintxx/vector.h" namespace flint { /////////////////////////////////////////////////////////////////////////////// // fmpz_mod_ctx_struct wrappers /////////////////////////////////////////////////////////////////////////////// class fmpz_modxx_ctx { private: mutable fmpz_mod_ctx_t ctx; public: fmpz_mod_ctx_t& _ctx() const {return ctx;} fmpzxx_ref modulus() {return fmpzxx_ref::make(ctx->n);} fmpzxx_srcref modulus() const {return fmpzxx_srcref::make(ctx->n);} fmpz_modxx_ctx(fmpzxx_srcref p) { fmpz_mod_ctx_init(ctx, p._fmpz()); } fmpz_modxx_ctx(ulong p) { fmpz_mod_ctx_init_ui(ctx, p); } ~fmpz_modxx_ctx() {fmpz_mod_ctx_clear(ctx);} void set_modulus(fmpzxx_srcref p) { fmpz_mod_ctx_set_modulus(ctx, p._fmpz()); } void set_modulus(ulong p) { fmpz_mod_ctx_set_modulus_ui(ctx, p); } }; class fmpz_modxx_ctx_srcref { private: mutable fmpz_mod_ctx_struct* ctx; fmpz_modxx_ctx_srcref(fmpz_mod_ctx_struct* c) : ctx(c) {} public: fmpz_mod_ctx_struct* _ctx() const {return ctx;} fmpzxx_ref modulus() {return fmpzxx_ref::make(ctx->n);} fmpzxx_srcref modulus() const {return fmpzxx_srcref::make(ctx->n);} fmpz_modxx_ctx_srcref(fmpz_modxx_ctx& c) : ctx(c._ctx()) {} fmpz_modxx_ctx_srcref(const fmpz_modxx_ctx& c) : ctx(c._ctx()) {} static fmpz_modxx_ctx_srcref make(fmpz_mod_ctx_struct* c) {return fmpz_modxx_ctx_srcref(c);} }; namespace traits { template struct has_fmpz_modxx_ctx : mp::false_ { }; template struct is_fmpz_mod_expr : has_fmpz_modxx_ctx::type> { }; } // traits namespace detail { struct has_fmpz_modxx_ctx_predicate { template struct type : traits::has_fmpz_modxx_ctx { }; }; } // detail namespace tools { template fmpz_modxx_ctx_srcref find_fmpz_modxx_ctx(const Expr& e) { return tools::find_subexpr(e).get_ctx(); } } // tools namespace detail { template struct fakemodtemplate : mp::enable_if > { }; } // detail /////////////////////////////////////////////////////////////////////////////// // fmpz_mod_poly_struct wrappers /////////////////////////////////////////////////////////////////////////////// FLINT_DEFINE_BINOP(divrem_f) FLINT_DEFINE_BINOP(gcd_euclidean_f) FLINT_DEFINE_BINOP(gcd_f) FLINT_DEFINE_BINOP(radix) FLINT_DEFINE_UNOP(fmpz_mod_polyxx_lead) // TODO standardise? FLINT_DEFINE_BINOP(fmpz_mod_polyxx_get_coeff) // TODO standardise? namespace detail { template struct fmpz_mod_poly_traits { typedef FLINT_UNOP_BUILD_RETTYPE( fmpz_mod_polyxx_lead, fmpzxx, Poly) lead_ref_t; typedef lead_ref_t lead_srcref_t; static lead_ref_t lead(const Poly& p) {return fmpz_mod_polyxx_lead(p);} }; } //detail template class fmpz_mod_polyxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef detail::fmpz_mod_poly_traits poly_traits_t; FLINTXX_DEFINE_BASICS(fmpz_mod_polyxx_expression) FLINTXX_DEFINE_CTORS(fmpz_mod_polyxx_expression) FLINTXX_DEFINE_C_REF(fmpz_mod_polyxx_expression, fmpz_mod_poly_struct, _poly) public: fmpz_modxx_ctx_srcref get_ctx() const {return this->_data().ctx;} fmpz_mod_ctx_struct* _ctx() const {return get_ctx()._ctx();} fmpz_modxx_ctx_srcref estimate_ctx() const { return tools::find_fmpz_modxx_ctx(*this);} static fmpz_mod_polyxx_expression zero(fmpz_modxx_ctx_srcref ctx) { return fmpz_mod_polyxx_expression(ctx); } static fmpz_mod_polyxx_expression one(fmpz_modxx_ctx_srcref ctx) { fmpz_mod_polyxx_expression res(ctx); res.set_one(); return res; } // Create a temporary. The context will be estimated. evaluated_t create_temporary() const { return evaluated_t(estimate_ctx()); } static fmpz_mod_polyxx_expression randtest( fmpz_modxx_ctx_srcref ctx, frandxx& state, slong len) { fmpz_mod_polyxx_expression res(ctx); fmpz_mod_poly_randtest(res._poly(), state._data(), len, ctx._ctx()); return res; } static fmpz_mod_polyxx_expression randtest_irreducible( fmpz_modxx_ctx_srcref ctx, frandxx& state, slong len) { fmpz_mod_polyxx_expression res(ctx); fmpz_mod_poly_randtest_irreducible(res._poly(), state._data(), len, ctx._ctx()); return res; } static fmpz_mod_polyxx_expression randtest_not_zero( fmpz_modxx_ctx_srcref ctx, frandxx& state, slong len) { fmpz_mod_polyxx_expression res(ctx); fmpz_mod_poly_randtest_not_zero(res._poly(), state._data(), len, ctx._ctx()); return res; } // These only make sense with immediates fmpzxx_srcref modulus() const {return get_ctx().modulus();} // These only make sense with target immediates void realloc(slong alloc) {fmpz_mod_poly_realloc(_poly(), alloc, _ctx());} void fit_length(slong len) {fmpz_mod_poly_fit_length(_poly(), len, _ctx());} void _normalise() {_fmpz_mod_poly_normalise(_poly());} void set_coeff(slong n, ulong c) {fmpz_mod_poly_set_coeff_ui(_poly(), n, c, _ctx());} template typename mp::enable_if >::type set_coeff(slong j, const Fmpz& c) { fmpz_mod_poly_set_coeff_fmpz(_poly(), j, c.evaluate()._fmpz(), _ctx()); } void truncate(slong n) {fmpz_mod_poly_truncate(_poly(), n, _ctx());} void zero_coeffs(slong i, slong j) {fmpz_mod_poly_zero_coeffs(_poly(), i, j, _ctx());} void set_randtest(frandxx& state, slong len) {fmpz_mod_poly_randtest(_poly(), state._data(), len, _ctx());} void set_randtest_irreducible(frandxx& state, slong len) {fmpz_mod_poly_randtest_irreducible(_poly(), state._data(), len, _ctx());} void set_randtest_not_zero(frandxx& state, slong len) {fmpz_mod_poly_randtest_not_zero(_poly(), state._data(), len, _ctx());} template slong remove(const Poly& p) { return fmpz_mod_poly_remove(_poly(), p.evaluate()._poly(), _ctx()); } void set_zero() {fmpz_mod_poly_zero(_poly(), _ctx());} // unified coefficient access typename poly_traits_t::lead_ref_t lead() { return poly_traits_t::lead(*this); } typename poly_traits_t::lead_srcref_t lead() const { return poly_traits_t::lead(*this); } // these cause evaluation slong length() const { auto e = this->evaluate(); return fmpz_mod_poly_length(e._poly(), e._ctx()); } slong degree() const { auto e = this->evaluate(); return fmpz_mod_poly_degree(e._poly(), e._ctx()); } bool is_zero() const { auto e = this->evaluate(); return fmpz_mod_poly_is_zero(e._poly(), e._ctx()); } bool is_one() const { auto e = this->evaluate(); return fmpz_mod_poly_is_one(e._poly(), e._ctx()); } bool is_squarefree() const { auto e = this->evaluate(); return fmpz_mod_poly_is_squarefree(e._poly(), e._ctx()); } bool is_irreducible() const { auto e = this->evaluate(); return fmpz_mod_poly_is_irreducible(e._poly(), e._ctx()); } bool is_irreducible_ddf() const { auto e = this->evaluate(); return fmpz_mod_poly_is_irreducible_ddf(e._poly(), e._ctx()); } bool is_irreducible_rabin() const { auto e = this->evaluate(); return fmpz_mod_poly_is_irreducible_rabin(e._poly(), e._ctx()); } // Lazy members FLINTXX_DEFINE_MEMBER_BINOP_(get_coeff, fmpz_mod_polyxx_get_coeff) FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval) FLINTXX_DEFINE_MEMBER_UNOP(derivative) FLINTXX_DEFINE_MEMBER_UNOP(invmod) FLINTXX_DEFINE_MEMBER_UNOP(make_monic) FLINTXX_DEFINE_MEMBER_UNOP(sqr) FLINTXX_DEFINE_MEMBER_BINOP(compose_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(compose_horner) FLINTXX_DEFINE_MEMBER_BINOP(div_basecase) FLINTXX_DEFINE_MEMBER_BINOP(divrem) FLINTXX_DEFINE_MEMBER_BINOP(divrem_basecase) FLINTXX_DEFINE_MEMBER_BINOP(divrem_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(divrem_f) FLINTXX_DEFINE_MEMBER_BINOP(gcd) FLINTXX_DEFINE_MEMBER_BINOP(gcd_euclidean) FLINTXX_DEFINE_MEMBER_BINOP(gcd_euclidean_f) FLINTXX_DEFINE_MEMBER_BINOP(gcd_f) FLINTXX_DEFINE_MEMBER_BINOP(gcdinv) FLINTXX_DEFINE_MEMBER_BINOP(invmod) FLINTXX_DEFINE_MEMBER_BINOP(inv_series_newton) FLINTXX_DEFINE_MEMBER_BINOP(shift_left) FLINTXX_DEFINE_MEMBER_BINOP(shift_right) FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_BINOP(radix) FLINTXX_DEFINE_MEMBER_BINOP(rem_basecase) FLINTXX_DEFINE_MEMBER_BINOP(xgcd) FLINTXX_DEFINE_MEMBER_BINOP(xgcd_euclidean) FLINTXX_DEFINE_MEMBER_3OP(compose_mod) FLINTXX_DEFINE_MEMBER_3OP(compose_mod_brent_kung) FLINTXX_DEFINE_MEMBER_3OP(compose_mod_horner) FLINTXX_DEFINE_MEMBER_3OP(mullow) FLINTXX_DEFINE_MEMBER_3OP(mulmod) FLINTXX_DEFINE_MEMBER_3OP(powmod_binexp) FLINTXX_DEFINE_MEMBER_3OP(pow_trunc) FLINTXX_DEFINE_MEMBER_3OP(pow_trunc_binexp) }; namespace detail { struct fmpz_mod_poly_data; } typedef fmpz_mod_polyxx_expression fmpz_mod_polyxx; typedef fmpz_mod_polyxx_expression > fmpz_mod_polyxx_ref; typedef fmpz_mod_polyxx_expression > fmpz_mod_polyxx_srcref; namespace traits { template<> struct has_fmpz_modxx_ctx : mp::true_ { }; template<> struct has_fmpz_modxx_ctx : mp::true_ { }; template<> struct has_fmpz_modxx_ctx : mp::true_ { }; } // traits namespace flint_classes { template<> struct ref_data { typedef void IS_REF_OR_CREF; typedef fmpz_mod_polyxx wrapped_t; typedef fmpz_mod_poly_struct* data_ref_t; typedef const fmpz_mod_poly_struct* data_srcref_t; fmpz_mod_poly_struct* inner; fmpz_modxx_ctx_srcref ctx; template ref_data(T& o, typename detail::fakemodtemplate::type* = 0) : inner(o._data().inner), ctx(o._data().ctx) {} static ref_data make(fmpz_mod_poly_struct* f, fmpz_modxx_ctx_srcref ctx) { return ref_data(f, ctx); } private: ref_data(fmpz_mod_poly_struct* fp, fmpz_modxx_ctx_srcref c) : inner(fp), ctx(c) {} }; template struct srcref_data { typedef void IS_REF_OR_CREF; typedef fmpz_mod_polyxx wrapped_t; typedef const fmpz_mod_poly_struct* data_ref_t; typedef const fmpz_mod_poly_struct* data_srcref_t; const fmpz_mod_poly_struct* inner; fmpz_modxx_ctx_srcref ctx; template srcref_data(const T& o, typename detail::fakemodtemplate::type* = 0) : inner(o._data().inner), ctx(o._data().ctx) {} template srcref_data(T o, typename detail::fakemodtemplate::type* = 0) : inner(o._data().inner), ctx(o._data().ctx) {} static srcref_data make(const fmpz_mod_poly_struct* f, fmpz_modxx_ctx_srcref ctx) { return srcref_data(f, ctx); } private: srcref_data(const fmpz_mod_poly_struct* fp, fmpz_modxx_ctx_srcref c) : inner(fp), ctx(c) {} }; } // flint_classes #define FMPZ_MOD_POLYXX_COND_S FLINTXX_COND_S(fmpz_mod_polyxx) #define FMPZ_MOD_POLYXX_COND_T FLINTXX_COND_T(fmpz_mod_polyxx) namespace detail { template<> struct fmpz_mod_poly_traits { typedef fmpzxx_srcref lead_srcref_t; typedef fmpzxx_srcref lead_ref_t; template static lead_srcref_t lead(P p) {return lead_srcref_t::make(fmpz_mod_poly_lead(p._poly(), p._ctx()));} }; template<> struct fmpz_mod_poly_traits { typedef fmpzxx_ref lead_ref_t; typedef fmpzxx_ref lead_srcref_t; template static lead_ref_t lead(P p) {return lead_ref_t::make(fmpz_mod_poly_lead(p._poly(), p._ctx()));} }; template<> struct fmpz_mod_poly_traits { typedef fmpzxx_ref lead_ref_t; typedef fmpzxx_srcref lead_srcref_t; template static lead_ref_t lead(P& p) {return lead_ref_t::make(fmpz_mod_poly_lead(p._poly(), p._ctx()));} template static lead_srcref_t lead(const P& p) {return lead_srcref_t::make(fmpz_mod_poly_lead(p._poly(), p._ctx()));} }; struct fmpz_mod_poly_data { typedef fmpz_mod_poly_t& data_ref_t; typedef const fmpz_mod_poly_t& data_srcref_t; fmpz_modxx_ctx_srcref ctx; fmpz_mod_poly_t inner; fmpz_mod_poly_data(fmpz_modxx_ctx_srcref c) : ctx(c) { fmpz_mod_poly_init(inner, ctx._ctx()); } fmpz_mod_poly_data(fmpz_modxx_ctx_srcref c, slong alloc) : ctx(c) { fmpz_mod_poly_init2(inner, alloc, ctx._ctx()); } fmpz_mod_poly_data(const fmpz_mod_poly_data& o) : ctx(o.ctx) { fmpz_mod_poly_init2(inner, o.inner->length, ctx._ctx()); fmpz_mod_poly_set(inner, o.inner, ctx._ctx()); } fmpz_mod_poly_data(fmpz_mod_polyxx_srcref c) : ctx(c.get_ctx()) { fmpz_mod_poly_init2(inner, c.length(), ctx._ctx()); fmpz_mod_poly_set(inner, c._poly(), ctx._ctx()); } ~fmpz_mod_poly_data() {fmpz_mod_poly_clear(inner, ctx._ctx());} }; struct is_fmpz_mod_polyxx_predicate { template struct type : FMPZ_MOD_POLYXX_COND_S { }; }; } // detail namespace traits { template struct is_fmpz_mod_polyxx : mp::or_< traits::is_T_expr, flint_classes::is_source > { }; } namespace rules { FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_MOD_POLYXX_COND_T, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_set(to._poly(), from._poly(), to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_MOD_POLYXX_COND_T, traits::is_unsigned_integer, fmpz_mod_poly_set_ui(to._poly(), from, to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_MOD_POLYXX_COND_T, FMPZXX_COND_S, fmpz_mod_poly_set_fmpz(to._poly(), from._fmpz(), to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_MOD_POLYXX_COND_T, FMPZ_POLYXX_COND_S, fmpz_mod_poly_set_fmpz_poly(to._poly(), from._poly(), to._ctx())) FLINTXX_DEFINE_CONVERSION_TMP(fmpz_polyxx, fmpz_mod_polyxx, fmpz_mod_poly_get_fmpz_poly(to._poly(), from._poly(), from._ctx())) FLINTXX_DEFINE_SWAP(fmpz_mod_polyxx, fmpz_mod_poly_swap(e1._poly(), e2._poly())) FLINTXX_DEFINE_EQUALS(fmpz_mod_polyxx, fmpz_mod_poly_equal(e1._poly(), e2._poly(), e1._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_mod_polyxx_get_coeff_op, fmpzxx, FMPZ_MOD_POLYXX_COND_S, traits::fits_into_slong, fmpz_mod_poly_get_coeff_fmpz(to._fmpz(), e1._poly(), e2, e1._ctx())) FLINT_DEFINE_PRINT_COND(FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_fprint(to, from._poly(), from._ctx())) FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPZ_MOD_POLYXX_COND_S, const char*, fmpz_mod_poly_fprint_pretty(to, from._poly(), extra, from._ctx())) // be careful with fread as it writes to the possibly shared ctx FLINT_DEFINE_READ_COND(FMPZ_MOD_POLYXX_COND_T, fmpz_mod_poly_fread(from, to._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_add(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_sub(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZXX_COND_S, fmpz_mod_poly_scalar_mul_fmpz(to._poly(), e1._poly(), e2._fmpz(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_mul(to._poly(), e1._poly(), e2._poly(), to._ctx())) // TODO expose the temporary FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_polyxx tmp(to.get_ctx()); fmpz_mod_poly_divrem(to._poly(), tmp._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_neg(to._poly(), from._poly(), to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(fmpz_mod_polyxx_lead_op, fmpzxx, FMPZ_MOD_POLYXX_COND_S, fmpz_set(to._fmpz(), fmpz_mod_poly_lead(from._poly(), from._ctx()))) FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, traits::fits_into_slong, fmpz_mod_poly_shift_left(to._poly(), e1._poly(), e2, to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, traits::fits_into_slong, fmpz_mod_poly_shift_right(to._poly(), e1._poly(), e2, to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(make_monic_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_make_monic(to._poly(), from._poly(), to._ctx())) FLINT_DEFINE_THREEARY_EXPR_COND3(mullow_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, traits::fits_into_slong, fmpz_mod_poly_mullow(to._poly(), e1._poly(), e2._poly(), e3, to._ctx())) FLINT_DEFINE_THREEARY_EXPR_COND3(mulmod_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_mulmod(to._poly(), e1._poly(), e2._poly(), e3._poly(), to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_sqr(to._poly(), from._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_rem(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_THREEARY_EXPR_COND3(powmod_binexp_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, traits::is_unsigned_integer, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_powmod_ui_binexp(to._poly(), e1._poly(), e2, e3._poly(), to._ctx())) FLINT_DEFINE_THREEARY_EXPR_COND3(powmod_binexp_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_powmod_fmpz_binexp(to._poly(), e1._poly(), e2._fmpz(), e3._poly(), to._ctx())) FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong, fmpz_mod_poly_pow_trunc(to._poly(), e1._poly(), e2, e3, to._ctx())) FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_binexp_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong, fmpz_mod_poly_pow_trunc_binexp(to._poly(), e1._poly(), e2, e3, to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, traits::is_unsigned_integer, fmpz_mod_poly_pow(to._poly(), e1._poly(), e2, to._ctx())) namespace rdetail { typedef make_ltuple::type>::type fmpz_mod_polyxx_pair; typedef make_ltuple::type>::type fmpz_mod_poly_divrem_f_rt; } // rdetail FLINT_DEFINE_BINARY_EXPR_COND2(divrem_basecase_op, rdetail::fmpz_mod_polyxx_pair, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_divrem_basecase( to.template get<0>()._poly(), to.template get<1>()._poly(), e1._poly(), e2._poly(), e1._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(divrem_divconquer_op, rdetail::fmpz_mod_polyxx_pair, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_divrem_divconquer( to.template get<0>()._poly(), to.template get<1>()._poly(), e1._poly(), e2._poly(), e1._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(divrem_op, rdetail::fmpz_mod_polyxx_pair, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_divrem_divconquer( to.template get<0>()._poly(), to.template get<1>()._poly(), e1._poly(), e2._poly(), e1._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(divrem_f_op, rdetail::fmpz_mod_poly_divrem_f_rt, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_divrem_f( to.template get<0>()._fmpz(), to.template get<1>()._poly(), to.template get<2>()._poly(), e1._poly(), e2._poly(), e1._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(div_basecase_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_div_basecase(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(rem_basecase_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_rem_basecase(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_newton_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, traits::fits_into_slong, fmpz_mod_poly_inv_series_newton(to._poly(), e1._poly(), e2, to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(gcd_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_gcd(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(gcd_euclidean_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_gcd_euclidean(to._poly(), e1._poly(), e2._poly(), to._ctx())) namespace rdetail { typedef make_ltuple::type>::type fmpz_mod_polyxx_triple; } // rdetail FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_op, rdetail::fmpz_mod_polyxx_triple, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_xgcd(to.template get<0>()._poly(), to.template get<1>()._poly(), to.template get<2>()._poly(), e1._poly(), e2._poly(), e1._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_euclidean_op, rdetail::fmpz_mod_polyxx_triple, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_xgcd_euclidean(to.template get<0>()._poly(), to.template get<1>()._poly(), to.template get<2>()._poly(), e1._poly(), e2._poly(), e1._ctx())) namespace rdetail { typedef make_ltuple::type>::type fmpz_mod_gcd_f_rt; } // rdetail FLINT_DEFINE_BINARY_EXPR_COND2(gcd_f_op, rdetail::fmpz_mod_gcd_f_rt, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_gcd_f(to.template get<0>()._fmpz(), to.template get<1>()._poly(), e1._poly(), e2._poly(), e1._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(gcd_euclidean_f_op, rdetail::fmpz_mod_gcd_f_rt, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_gcd_euclidean_f(to.template get<0>()._fmpz(), to.template get<1>()._poly(), e1._poly(), e2._poly(), e1._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(gcdinv_op, rdetail::fmpz_mod_polyxx_pair, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_gcdinv( to.template get<0>()._poly(), to.template get<1>()._poly(), e1._poly(), e2._poly(), e1._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(invmod_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, execution_check(fmpz_mod_poly_invmod(to._poly(), e1._poly(), e2._poly(), to._ctx()), "invmod", "fmpz_mod_polyxx")) FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_derivative(to._poly(), from._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpzxx, FMPZ_MOD_POLYXX_COND_S, FMPZXX_COND_S, fmpz_mod_poly_evaluate_fmpz(to._fmpz(), e1._poly(), e2._fmpz(), e1._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(compose_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_compose(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(compose_divconquer_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_compose_divconquer(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(compose_horner_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_compose_horner(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_compose_mod(to._poly(), e1._poly(), e2._poly(), e3._poly(), to._ctx())) FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_horner_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_compose_mod_horner(to._poly(), e1._poly(), e2._poly(), e3._poly(), to._ctx())) FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_brent_kung_op, fmpz_mod_polyxx, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, FMPZ_MOD_POLYXX_COND_S, fmpz_mod_poly_compose_mod_brent_kung(to._poly(), e1._poly(), e2._poly(), e3._poly(), to._ctx())) } // rules /////////////////////////////////////////////////////////////////////////////// // fmpz_mod_poly_vecxx (for radix conversion) /////////////////////////////////////////////////////////////////////////////// namespace detail { struct fmpz_mod_poly_vector_data { slong size; fmpz_mod_poly_struct** array; fmpz_modxx_ctx_srcref ctx; fmpz_mod_poly_vector_data(slong n, fmpz_modxx_ctx_srcref c) : size(n), ctx(c) { array = new fmpz_mod_poly_struct*[n]; for(slong i = 0;i < n;++i) { array[i] = new fmpz_mod_poly_struct(); fmpz_mod_poly_init(array[i], ctx._ctx()); } } ~fmpz_mod_poly_vector_data() { for(slong i = 0;i < size;++i) { fmpz_mod_poly_clear(array[i], ctx._ctx()); delete array[i]; } delete[] array; } fmpz_mod_poly_vector_data(const fmpz_mod_poly_vector_data& o) : size(o.size), ctx(o.ctx) { array = new fmpz_mod_poly_struct*[size]; for(slong i = 0;i < size;++i) { array[i] = new fmpz_mod_poly_struct(); fmpz_mod_poly_init(array[i], ctx._ctx()); fmpz_mod_poly_set(array[i], o.array[i], ctx._ctx()); } } fmpz_mod_polyxx_ref at(slong i) {return fmpz_mod_polyxx_ref::make(array[i], ctx);} fmpz_mod_polyxx_srcref at(slong i) const {return fmpz_mod_polyxx_srcref::make(array[i], ctx);} bool equals(const fmpz_mod_poly_vector_data& o) const { if(size != o.size) return false; for(slong i = 0;i < size;++i) if(!fmpz_mod_poly_equal(array[i], o.array[i], ctx._ctx())) return false; return true; } }; struct fmpz_mod_poly_vector_traits : wrapped_vector_traits { template static typename Expr::evaluated_t create_temporary(const Expr& e) { return typename Expr::evaluated_t(e.size(), tools::find_fmpz_modxx_ctx(e)); } }; } // detail // TODO would it make more sense to have this have its own class? typedef vector_expression< detail::fmpz_mod_poly_vector_traits, operations::immediate, detail::fmpz_mod_poly_vector_data> fmpz_mod_poly_vecxx; // TODO references template<> struct enable_vector_rules : mp::false_ { }; namespace rules { // TODO hack to make code look like references are implemented template struct FMPZ_MOD_POLY_VECXX_COND_S : mp::equal_types { }; #define FMPZ_MOD_POLY_VECXX_COND_T FMPZ_MOD_POLY_VECXX_COND_S // TODO references FLINT_DEFINE_GET(equals, bool, fmpz_mod_poly_vecxx, e1._data().equals(e2._data())) } // rules /////////////////////////////////////////////////////////////////////////////// // radix conversion /////////////////////////////////////////////////////////////////////////////// class fmpz_mod_poly_radixxx { private: fmpz_mod_poly_radix_t inner; // not copyable fmpz_mod_poly_radixxx(const fmpz_mod_poly_radixxx&); public: template fmpz_mod_poly_radixxx(const Fmpz_mod_poly& r, slong deg, typename mp::enable_if< traits::is_fmpz_mod_polyxx >::type* = 0) { auto e = r.evaluate(); fmpz_mod_poly_radix_init(inner, e._poly(), deg, e._ctx()); } ~fmpz_mod_poly_radixxx() {fmpz_mod_poly_radix_clear(inner);} fmpz_mod_poly_radix_t& _data() {return inner;} const fmpz_mod_poly_radix_t& _data() const {return inner;} slong degR() const {return inner->degR;} }; namespace traits { template struct is_fmpz_mod_poly_radixxx : mp::equal_types { }; } // traits namespace vectors { template<> struct outsize { template static unsigned get(const Expr& e) { return e._data().first().degree() / e._data().second().degR() + 1; } }; } namespace rules { FLINT_DEFINE_BINARY_EXPR_COND2(radix_op, fmpz_mod_poly_vecxx, FMPZ_MOD_POLYXX_COND_S, traits::is_fmpz_mod_poly_radixxx, fmpz_mod_poly_radix(to._array(), e1._poly(), e2._data(), e1._ctx())) } } // flint #include "fmpz_mod_poly_factorxx.h" #endif flint2-2.8.4/fmpz_mod_vec.h000066400000000000000000000035721414523752600155640ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPZ_MOD_VEC_INLINE static __inline__ #endif #include #include "flint.h" #include "fmpz_mod.h" #ifdef __cplusplus extern "C" { #endif FLINT_DLL void _fmpz_mod_vec_set_fmpz_vec(fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_vec_neg(fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL void _fmpz_mod_vec_sub(fmpz * a, const fmpz * b, const fmpz * c, slong n, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_vec_mul(fmpz * A, const fmpz * B, const fmpz * C, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void _fmpz_mod_vec_dot(fmpz_t d, const fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx); FLINT_DLL 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 flint2-2.8.4/fmpz_mod_vec/000077500000000000000000000000001414523752600154045ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_vec/dot.c000066400000000000000000000012271414523752600163400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_zero(d); for (len--; len >= 0; len--) fmpz_addmul(d, a + len, b + len); fmpz_mod_set_fmpz(d, d, ctx); } flint2-2.8.4/fmpz_mod_vec/dot_rev.c000066400000000000000000000012501414523752600172100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" void _fmpz_mod_vec_dot_rev(fmpz_t r, const fmpz * a, const fmpz * b, slong len, const fmpz_mod_ctx_t ctx) { slong i; fmpz_zero(r); for (i = 0; i < len; i++) fmpz_addmul(r, a + i, b + len - i - 1); fmpz_mod_set_fmpz(r, r, ctx); } flint2-2.8.4/fmpz_mod_vec/mul.c000066400000000000000000000011601414523752600163430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_vec/neg.c000066400000000000000000000011701414523752600163200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_vec/scalar_div_fmpz_mod.c000066400000000000000000000013121414523752600215470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" 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); } flint2-2.8.4/fmpz_mod_vec/scalar_mul_fmpz_mod.c000066400000000000000000000013351414523752600215670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" 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); } } flint2-2.8.4/fmpz_mod_vec/set_fmpz_vec.c000066400000000000000000000012061414523752600202330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" void _fmpz_mod_vec_set_fmpz_vec(fmpz * A, const fmpz * B, slong len, const fmpz_mod_ctx_t ctx) { for (len--; len >= 0; len--) fmpz_mod_set_fmpz(A + len, B + len, ctx); } flint2-2.8.4/fmpz_mod_vec/sub.c000066400000000000000000000011631414523752600163420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mod_vec/test/000077500000000000000000000000001414523752600163635ustar00rootroot00000000000000flint2-2.8.4/fmpz_mod_vec/test/t-empty.c000066400000000000000000000010601414523752600201230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mod_vec.h" int main(void) { flint_printf("empty...."); fflush(stdout); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly.h000066400000000000000000001727341414523752600153170ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPZ_MPOLY_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "fmpz_mod.h" #include "n_poly.h" #ifdef __cplusplus extern "C" { #endif /* Type definitions **********************************************************/ /* context object for fmpz_mpoly */ typedef struct { mpoly_ctx_t minfo; } fmpz_mpoly_ctx_struct; typedef fmpz_mpoly_ctx_struct fmpz_mpoly_ctx_t[1]; /* fmpz_mpoly_t sparse multivariates with fmpz coeffs */ 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]; 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 coeffcients. 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 ************************************************************/ FLINT_DLL void fmpz_mpoly_ctx_init(fmpz_mpoly_ctx_t ctx, slong nvars, const ordering_t ord); FLINT_DLL void fmpz_mpoly_ctx_init_rand(fmpz_mpoly_ctx_t mctx, flint_rand_t state, slong max_nvars); FLINT_DLL 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 ********************************************************/ FLINT_DLL void fmpz_mpoly_init(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_init2(fmpz_mpoly_t A, slong alloc, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_init3(fmpz_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void _fmpz_mpoly_realloc(fmpz ** Acoeff, ulong ** Aexp, slong * Aalloc, slong len, slong N); FLINT_DLL void fmpz_mpoly_realloc(fmpz_mpoly_t A, slong alloc, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void _fmpz_mpoly_fit_length(fmpz ** Acoeff, ulong ** Aexp, slong * Aalloc, slong len, slong N); FLINT_DLL void fmpz_mpoly_fit_length(fmpz_mpoly_t A, slong len, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_fit_length_reset_bits(fmpz_mpoly_t A, slong len, flint_bitcnt_t bits, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_clear(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE 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; } FMPZ_MPOLY_INLINE 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; } } FMPZ_MPOLY_INLINE 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; } } /* Input/output **************************************************************/ FLINT_DLL int fmpz_mpoly_set_str_pretty(fmpz_mpoly_t A, const char * str, const char ** x, const fmpz_mpoly_ctx_t ctx); FLINT_DLL char * _fmpz_mpoly_get_str_pretty(const fmpz * poly, const ulong * exps, slong len, const char ** x, slong bits, const mpoly_ctx_t mctx); FLINT_DLL char * fmpz_mpoly_get_str_pretty(const fmpz_mpoly_t A, const char ** x, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int fmpz_mpoly_fprint_pretty(FILE * file, const fmpz_mpoly_t A, const char ** x, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE 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); } FMPZ_MPOLY_INLINE 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); } /* Basic manipulation *******************************************************/ FLINT_DLL void fmpz_mpoly_gen(fmpz_mpoly_t poly, slong i, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mpoly_is_gen(const fmpz_mpoly_t poly, slong k, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void _fmpz_mpoly_set(fmpz * poly1, ulong * exps1, const fmpz * poly2, const ulong * exps2, slong n, slong N); FLINT_DLL void fmpz_mpoly_set(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int _fmpz_mpoly_equal(fmpz * poly1, ulong * exps1, const fmpz * poly2, const ulong * exps2, slong n, slong N); FLINT_DLL 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) { fmpz_mpoly_struct t = *A; *A = *B; *B = t; } 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; } FMPZ_MPOLY_INLINE slong fmpz_mpoly_max_bits(const fmpz_mpoly_t A) { return _fmpz_vec_max_bits(A->coeffs, A->length); } /* Constants *****************************************************************/ FLINT_DLL int fmpz_mpoly_is_fmpz(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_get_fmpz(fmpz_t c, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_fmpz(fmpz_mpoly_t A, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_ui(fmpz_mpoly_t A, ulong c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL int fmpz_mpoly_equal_fmpz(const fmpz_mpoly_t A, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mpoly_equal_ui(const fmpz_mpoly_t A, ulong c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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 *******************************************************************/ FMPZ_MPOLY_INLINE 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); } FMPZ_MPOLY_INLINE 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); } FMPZ_MPOLY_INLINE 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); } FMPZ_MPOLY_INLINE void fmpz_mpoly_degree_fmpz(fmpz_t deg, const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) { mpoly_degree_fmpz(deg, A->exps, A->length, A->bits, var, ctx->minfo); } FMPZ_MPOLY_INLINE slong fmpz_mpoly_degree_si(const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx) { return mpoly_degree_si(A->exps, A->length, A->bits, var, ctx->minfo); } FMPZ_MPOLY_INLINE 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); } FMPZ_MPOLY_INLINE 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); } FMPZ_MPOLY_INLINE 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); } FMPZ_MPOLY_INLINE 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); } /* Coefficients **************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mpoly_get_coeff_fmpz_fmpz(fmpz_t c, const fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL ulong fmpz_mpoly_get_coeff_ui_fmpz( const fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL slong fmpz_mpoly_get_coeff_si_fmpz( const fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_get_coeff_fmpz_ui(fmpz_t c, const fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL ulong fmpz_mpoly_get_coeff_ui_ui( const fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL slong fmpz_mpoly_get_coeff_si_ui( const fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void _fmpz_mpoly_set_coeff_fmpz_fmpz(fmpz_mpoly_t A, const fmpz_t c, const fmpz * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_coeff_fmpz_fmpz(fmpz_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_coeff_ui_fmpz(fmpz_mpoly_t A, const ulong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_coeff_si_fmpz(fmpz_mpoly_t A, const slong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_coeff_fmpz_ui(fmpz_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_coeff_ui_ui(fmpz_mpoly_t A, const ulong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_coeff_si_ui(fmpz_mpoly_t A, const slong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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 ****************************************************************/ FLINT_DLL int fmpz_mpoly_is_fmpz_poly(const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mpoly_get_fmpz_poly(fmpz_poly_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fmpz_mpoly_set_fmpz_poly(fmpz_mpoly_t A, const fmpz_poly_t B, slong v, const fmpz_mpoly_ctx_t ctx); /* comparison ****************************************************************/ FLINT_DLL int fmpz_mpoly_cmp(const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); /* container operations ******************************************************/ FLINT_DLL 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; } FLINT_DLL void fmpz_mpoly_resize(fmpz_mpoly_t A, slong new_length, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_get_term_coeff_fmpz(fmpz_t c, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); FLINT_DLL ulong fmpz_mpoly_get_term_coeff_ui( const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); FLINT_DLL slong fmpz_mpoly_get_term_coeff_si( const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_term_coeff_fmpz(fmpz_mpoly_t A, slong i, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_term_coeff_ui(fmpz_mpoly_t A, slong i, ulong c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_term_coeff_si(fmpz_mpoly_t A, slong i, slong c, const fmpz_mpoly_ctx_t ctx); FMPZ_MPOLY_INLINE 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); } FMPZ_MPOLY_INLINE 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_DLL void fmpz_mpoly_get_term_exp_fmpz(fmpz ** exp, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_get_term_exp_ui(ulong * exp, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_get_term_exp_si(slong * exp, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); FLINT_DLL ulong fmpz_mpoly_get_term_var_exp_ui(const fmpz_mpoly_t A, slong i, slong var, const fmpz_mpoly_ctx_t ctx); FLINT_DLL slong fmpz_mpoly_get_term_var_exp_si(const fmpz_mpoly_t A, slong i, slong var, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_term_exp_fmpz(fmpz_mpoly_t A, slong i, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_set_term_exp_ui(fmpz_mpoly_t A, slong i, const ulong * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_get_term(fmpz_mpoly_t M, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_get_term_monomial(fmpz_mpoly_t M, const fmpz_mpoly_t A, slong i, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_push_term_fmpz_fmpz(fmpz_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_push_term_ui_fmpz(fmpz_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_push_term_si_fmpz(fmpz_mpoly_t A, slong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_push_term_fmpz_ui(fmpz_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_push_term_ui_ui(fmpz_mpoly_t A, ulong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_push_term_si_ui(fmpz_mpoly_t A, slong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_sort_terms(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_combine_like_terms(fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_reverse(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_assert_canonical(const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void _fmpz_mpoly_radix_sort1(fmpz_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask); FLINT_DLL void _fmpz_mpoly_radix_sort(fmpz_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask); FLINT_DLL void _fmpz_mpoly_push_exp_ffmpz(fmpz_mpoly_t A, const fmpz * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void _fmpz_mpoly_push_exp_pfmpz(fmpz_mpoly_t A, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void _fmpz_mpoly_push_exp_ui(fmpz_mpoly_t A, const ulong * exp, const fmpz_mpoly_ctx_t ctx); /* Random generation *********************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ******************************************************/ FLINT_DLL void fmpz_mpoly_add_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_add_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_add_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_sub_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_sub_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_sub_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_add(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fmpz_mpoly_sub(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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 *********************************************************/ FLINT_DLL void fmpz_mpoly_neg(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fmpz_mpoly_scalar_mul_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_scalar_mul_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mpoly_scalar_divexact_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_scalar_divexact_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int fmpz_mpoly_scalar_divides_si(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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 ***********************************************/ FLINT_DLL void fmpz_mpoly_derivative(fmpz_mpoly_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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 ****************************************************************/ FLINT_DLL int _fmpz_pow_ui_is_not_feasible(flint_bitcnt_t bbits, ulong e); FLINT_DLL int _fmpz_pow_fmpz_is_not_feasible(flint_bitcnt_t bbits, const fmpz_t e); FLINT_DLL int fmpz_mpoly_evaluate_all_fmpz(fmpz_t ev, const fmpz_mpoly_t A, fmpz * const * vals, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ************************************************************/ FLINT_DLL void fmpz_mpoly_mul(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_t C, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ******************************************************************/ FLINT_DLL int fmpz_mpoly_pow_fmpz(fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_t k, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mpoly_pow_ui(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong k, const fmpz_mpoly_ctx_t ctx); /* Division ******************************************************************/ FLINT_DLL int fmpz_mpoly_divides(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mpoly_div(fmpz_mpoly_t Q, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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"); } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ***************************************************************/ FLINT_DLL 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); FLINT_DLL 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 ***********************************************************************/ FLINT_DLL void fmpz_mpoly_term_content(fmpz_mpoly_t M, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int fmpz_mpoly_gcd(fmpz_mpoly_t G, const fmpz_mpoly_t A, const fmpz_mpoly_t B, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fmpz_mpoly_deflation(fmpz * shift, fmpz * stride, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ***************************************************************/ FLINT_DLL void fmpz_mpoly_univar_init(fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_univar_clear(fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_univar_fit_length(fmpz_mpoly_univar_t A, slong length, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_univar_print_pretty(const fmpz_mpoly_univar_t A, const char ** x, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL 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); FLINT_DLL void fmpz_mpoly_to_univar(fmpz_mpoly_univar_t A, const fmpz_mpoly_t B, slong var, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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) { fmpz_mpoly_univar_struct t = *A; *A = *B; *B = t; } FMPZ_MPOLY_INLINE 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); } FMPZ_MPOLY_INLINE slong fmpz_mpoly_univar_length(const fmpz_mpoly_univar_t A, const fmpz_mpoly_ctx_t ctx) { return A->length; } FMPZ_MPOLY_INLINE 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); } 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); } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int fmpz_mpoly_univar_discriminant(fmpz_mpoly_t d, const fmpz_mpoly_univar_t fx, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int fmpz_mpoly_discriminant(fmpz_mpoly_t R, const fmpz_mpoly_t A, slong var, const fmpz_mpoly_ctx_t ctx); /****************************************************************************** Internal functions (guaranteed to change without notice) ******************************************************************************/ FLINT_DLL void mpoly_void_ring_init_fmpz_mpoly_ctx(mpoly_void_ring_t R, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_pow_fps(fmpz_mpoly_t A, const fmpz_mpoly_t B, ulong k, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpolyl_lead_coeff(fmpz_mpoly_t c, const fmpz_mpoly_t A, slong num_vars, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mpolyl_content(fmpz_mpoly_t g, const fmpz_mpoly_t A, slong num_vars, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int fmpz_mpoly_repack_bits(fmpz_mpoly_t A, const fmpz_mpoly_t B, flint_bitcnt_t Abits, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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]; FLINT_DLL void fmpz_mpolyd_init(fmpz_mpolyd_t poly, slong nvars); FLINT_DLL void fmpz_mpolyd_fit_length(fmpz_mpolyd_t poly, slong len); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_mpoly_height(fmpz_t max, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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]; FLINT_DLL void fmpz_mpoly_geobucket_init(fmpz_mpoly_geobucket_t B, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_geobucket_clear(fmpz_mpoly_geobucket_t B, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_geobucket_empty(fmpz_mpoly_t p, fmpz_mpoly_geobucket_t B, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_geobucket_fit_length(fmpz_mpoly_geobucket_t B, slong i, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_geobucket_set(fmpz_mpoly_geobucket_t B, fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_geobucket_add(fmpz_mpoly_geobucket_t B, fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_geobucket_sub(fmpz_mpoly_geobucket_t B, fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx); /* Helpers for array methods *************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _fmpz_mpoly_addmul_array1_slong1(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3); FLINT_DLL void _fmpz_mpoly_addmul_array1_slong(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3); FLINT_DLL void _fmpz_mpoly_addmul_array1_slong2(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3); FLINT_DLL void _fmpz_mpoly_addmul_array1_fmpz(fmpz * poly1, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3); FLINT_DLL void _fmpz_mpoly_submul_array1_slong(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3); FLINT_DLL void _fmpz_mpoly_submul_array1_slong2(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3); FLINT_DLL void _fmpz_mpoly_submul_array1_slong1(ulong * poly1, const slong * poly2, const ulong * exp2, slong len2, const slong * poly3, const ulong * exp3, slong len3); FLINT_DLL void _fmpz_mpoly_submul_array1_fmpz(fmpz * poly1, const fmpz * poly2, const ulong * exp2, slong len2, const fmpz * poly3, const ulong * exp3, slong len3); FLINT_DLL void _fmpz_mpoly_submul_array1_slong_1(ulong * poly1, slong d, const ulong exp2, const slong * poly3, const ulong * exp3, slong len3); FLINT_DLL void _fmpz_mpoly_submul_array1_slong2_1(ulong * poly1, slong d, const ulong exp2, const slong * poly3, const ulong * exp3, slong len3); FLINT_DLL void _fmpz_mpoly_submul_array1_fmpz_1(fmpz * poly1, const fmpz_t d, ulong exp2, const fmpz * poly3, const ulong * exp3, slong len3); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL slong fmpz_mpoly_append_array_sm1_DEGLEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb); FLINT_DLL slong fmpz_mpoly_append_array_sm2_DEGLEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb); FLINT_DLL slong fmpz_mpoly_append_array_sm3_DEGLEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb); FLINT_DLL slong fmpz_mpoly_append_array_fmpz_DEGLEX(fmpz_mpoly_t P, slong Plen, fmpz * coeff_array, slong top, slong nvars, slong degb); FLINT_DLL slong fmpz_mpoly_append_array_sm1_DEGREVLEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb); FLINT_DLL slong fmpz_mpoly_append_array_sm2_DEGREVLEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb); FLINT_DLL slong fmpz_mpoly_append_array_sm3_DEGREVLEX(fmpz_mpoly_t P, slong Plen, ulong * coeff_array, slong top, slong nvars, slong degb); FLINT_DLL slong fmpz_mpoly_append_array_fmpz_DEGREVLEX(fmpz_mpoly_t P, slong Plen, fmpz * coeff_array, slong top, slong nvars, slong degb); FLINT_DLL slong _fmpz_mpoly_from_ulong_array(fmpz ** poly1, ulong ** exp1, slong * alloc, ulong * poly2, const slong * mults, slong num, slong bits, slong k); FLINT_DLL slong _fmpz_mpoly_from_ulong_array2(fmpz ** poly1, ulong ** exp1, slong * alloc, ulong * poly2, const slong * mults, slong num, slong bits, slong k); FLINT_DLL slong _fmpz_mpoly_from_ulong_array1(fmpz ** poly1, ulong ** exp1, slong * alloc, ulong * poly2, const slong * mults, slong num, slong bits, slong k); FLINT_DLL slong _fmpz_mpoly_from_fmpz_array(fmpz ** poly1, ulong ** exp1, slong * alloc, fmpz * poly2, const slong * mults, slong num, slong bits, slong k); FLINT_DLL void _fmpz_mpoly_to_ulong_array2(ulong * p, const fmpz * coeffs, const ulong * exps, slong len); FLINT_DLL void _fmpz_mpoly_to_ulong_array1(ulong * p, const fmpz * coeffs, const ulong * exps, slong len); FLINT_DLL void _fmpz_mpoly_to_ulong_array(ulong * p, const fmpz * coeffs, const ulong * exps, slong len); FLINT_DLL 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 *******/ FMPZ_MPOLY_INLINE 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); } } FMPZ_MPOLY_INLINE 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); } } 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]); } FLINT_DLL mpz_srcptr _fmpz_mpoly_get_mpz_signed_uiuiui(ulong * sm, fmpz x, mpz_ptr t); FMPZ_MPOLY_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); } /****************************************************************************** Internal consistency checks ******************************************************************************/ /* 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| */ FMPZ_MPOLY_INLINE 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); /* mask with high bit set in each field of exponent vector */ for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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_printf("fmpz_mpoly_remainder_test FAILED i = %wd\n", i); flint_printf("rem ");fmpz_mpoly_print_pretty(r, NULL, ctx); printf("\n\n"); flint_printf("den ");fmpz_mpoly_print_pretty(g, NULL, ctx); printf("\n\n"); flint_abort(); } } 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) */ FMPZ_MPOLY_INLINE 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); /* mask with high bit set in each field of exponent vector */ for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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_printf("fmpz_mpoly_remainder_strongtest FAILED i = %wd\n", i); flint_printf("rem ");fmpz_mpoly_print_pretty(r, NULL, ctx); printf("\n\n"); flint_printf("den ");fmpz_mpoly_print_pretty(g, NULL, ctx); printf("\n\n"); flint_abort(); } } flint_free(rexp); flint_free(gexp); } #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpz_mpoly/000077500000000000000000000000001414523752600151305ustar00rootroot00000000000000flint2-2.8.4/fmpz_mpoly/add.c000066400000000000000000000175061414523752600160350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/add_fmpz.c000066400000000000000000000051311414523752600170600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/clear.c000066400000000000000000000013571414523752600163700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" void fmpz_mpoly_clear(fmpz_mpoly_t poly, const fmpz_mpoly_ctx_t ctx) { if (poly->coeffs != NULL) { slong i; for (i = 0; i < poly->alloc; i++) _fmpz_demote(poly->coeffs + i); flint_free(poly->coeffs); flint_free(poly->exps); } } flint2-2.8.4/fmpz_mpoly/cmp.c000066400000000000000000000021601414523752600160520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } return 0; } flint2-2.8.4/fmpz_mpoly/combine_like_terms.c000066400000000000000000000026531414523752600211340ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/compose_fmpz_mpoly.c000066400000000000000000000035141414523752600212200ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/compose_fmpz_mpoly_gen.c000066400000000000000000000023441414523752600220510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/compose_fmpz_mpoly_geobucket.c000066400000000000000000000035051414523752600232500ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/compose_fmpz_mpoly_horner.c000066400000000000000000000261111414523752600225730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 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 */ 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 == 0) { fmpz_mpoly_zero(A, 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; } flint2-2.8.4/fmpz_mpoly/compose_fmpz_poly.c000066400000000000000000000151551414523752600210470ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mpoly/compose_mat.c000066400000000000000000000043041414523752600176030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_vec(v, M, u); 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; } flint2-2.8.4/fmpz_mpoly/content_vars.c000066400000000000000000000122621414523752600200040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/ctx_clear.c000066400000000000000000000007541414523752600172460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" void fmpz_mpoly_ctx_clear(fmpz_mpoly_ctx_t ctx) { mpoly_ctx_clear(ctx->minfo); } flint2-2.8.4/fmpz_mpoly/ctx_init.c000066400000000000000000000011061414523752600171130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/ctx_init_rand.c000066400000000000000000000010531414523752600201200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" 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); } flint2-2.8.4/fmpz_mpoly/deflate.c000066400000000000000000000031111414523752600166740ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mpoly/deflation.c000066400000000000000000000013021414523752600172350ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/derivative.c000066400000000000000000000057001414523752600174400ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/discriminant.c000066400000000000000000000014441414523752600177630ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_mpoly/div.c000066400000000000000000000011511414523752600160540ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpz_mpoly/div_monagan_pearce.c000066400000000000000000000635401414523752600211050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "longlong.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) + FLINT_BITS - 2) && FLINT_ABS(bits3) <= FLINT_BITS - 2; /* 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]); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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) + FLINT_BITS - 2) && FLINT_ABS(bits3) <= FLINT_BITS - 2; /* 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]); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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); } flint2-2.8.4/fmpz_mpoly/divides.c000066400000000000000000000026401414523752600167250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" #include "thread_pool.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; } flint2-2.8.4/fmpz_mpoly/divides_array.c000066400000000000000000001334551414523752600201340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "hashmap.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++) { c2 = poly1 + 2*((slong) exp2[i]); if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { c = c2 + 2*((slong) exp3[j]); 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 + 2*((slong) exp2); if (d != 0) { for (j = 0; j < len3; j++) { c = c2 + 2*((slong) exp3[j]); 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 FLINT_BITS - 2 for coefficients of the quotient */ bits1 = FLINT_ABS(bits3) + FLINT_BITS + FLINT_BIT_COUNT(len3) - 2; small = FLINT_ABS(bits2) <= bits1 && FLINT_ABS(bits3) <= FLINT_BITS - 2; 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 FLINT_BITS - 2 for coefficients of the quotient */ bits1 = FLINT_ABS(bits3) + FLINT_BITS + FLINT_BIT_COUNT(len3) - 2; small = FLINT_ABS(bits2) <= bits1 && FLINT_ABS(bits3) <= FLINT_BITS - 2; /* 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])) > FLINT_BITS - 2) { 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; } flint2-2.8.4/fmpz_mpoly/divides_heap_threaded.c000066400000000000000000002003661414523752600215670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "fmpz_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 */ 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); } } 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); } 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]); } } } 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*/ 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 stuct 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 */ 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 <= FLINT_BITS - 2 && _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; } 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 <= FLINT_BITS - 2 && _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 */ 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 <= FLINT_BITS - 2 && FLINT_ABS(Acoeffbits) <= (S->coeff_bits + FLINT_BIT_COUNT(Blen) + FLINT_BITS - 2); 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 with high bit set in each word of each field of exponent vector */ mask = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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]); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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; } 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 <= FLINT_BITS - 2 && FLINT_ABS(Acoeffbits) <= (S->coeff_bits + FLINT_BIT_COUNT(Blen) + FLINT_BITS - 2); 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]); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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 !FLINT_KNOW_STRONG_ORDER return fmpz_mpoly_divides_monagan_pearce(Q, A, B, ctx); #endif 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; } flint2-2.8.4/fmpz_mpoly/divides_monagan_pearce.c000066400000000000000000000621621414523752600217510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) + FLINT_BITS - 2) && FLINT_ABS(bits3) <= FLINT_BITS - 2; /* 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 indicies */ 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]); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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) << (FLINT_BITS - 2))) == 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 neccesary */ 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) + FLINT_BITS - 2) && FLINT_ABS(bits3) <= FLINT_BITS - 2; /* 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 indicies */ 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]); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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) << (FLINT_BITS - 2))) == 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); } flint2-2.8.4/fmpz_mpoly/divrem.c000066400000000000000000000012021414523752600165550ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/divrem_array.c000066400000000000000000001127371414523752600177730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.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 FLINT_BITS - 2 for coefficients of the quotient */ bits1 = FLINT_ABS(bits3) + FLINT_BITS + FLINT_BIT_COUNT(len3) - 2; small = FLINT_ABS(bits2) <= bits1 && FLINT_ABS(bits3) <= FLINT_BITS - 2; 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 FLINT_BITS - 2 for coefficients of the quotient */ bits1 = FLINT_ABS(bits3) + FLINT_BITS + FLINT_BIT_COUNT(len3) - 2; small = FLINT_ABS(bits2) <= bits1 && FLINT_ABS(bits3) <= FLINT_BITS - 2; /* 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])) > FLINT_BITS - 2) { 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; } flint2-2.8.4/fmpz_mpoly/divrem_ideal.c000066400000000000000000000012761414523752600177260ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/divrem_ideal_monagan_pearce.c000066400000000000000000000665231414523752600227530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "longlong.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. */ 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; slong ** hinds; 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 = (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) + FLINT_BITS - 2) && FLINT_ABS(bits3) <= FLINT_BITS - 2; 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; sdiv_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) + FLINT_BITS - 2) && FLINT_ABS(bits3) <= FLINT_BITS - 2; 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; sdiv_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; } flint2-2.8.4/fmpz_mpoly/divrem_monagan_pearce.c000066400000000000000000000703131414523752600216050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "longlong.h" /* 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) + FLINT_BITS - 2) && FLINT_ABS(bits3) <= FLINT_BITS - 2; /* 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 indicies */ 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 cofficient info in "small" case */ if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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 neccesary */ 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) + FLINT_BITS - 2) && FLINT_ABS(bits3) <= FLINT_BITS - 2; /* 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 indicies */ 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 cofficient info in "small" case */ if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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 neccesary */ 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); } flint2-2.8.4/fmpz_mpoly/equal.c000066400000000000000000000042351414523752600164070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.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; } flint2-2.8.4/fmpz_mpoly/equal_fmpz.c000066400000000000000000000015231414523752600174400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/equal_si.c000066400000000000000000000015131414523752600170760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/equal_ui.c000066400000000000000000000015131414523752600171000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/evaluate_all.c000066400000000000000000000134421414523752600177360ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mpoly/evaluate_all_fmpz_mod.c000066400000000000000000000013401414523752600216230ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_mpoly/evaluate_all_nmod.c000066400000000000000000000016041414523752600207500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/evaluate_one.c000066400000000000000000000155651414523752600177570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/fit_length.c000066400000000000000000000020341414523752600174160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_mpoly/fit_length_reset_bits.c000066400000000000000000000027111414523752600216430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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: possibly 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->exps = (ulong *) flint_realloc(A->exps, newN*A->alloc*sizeof(ulong)); } A->bits = bits; } flint2-2.8.4/fmpz_mpoly/fprint_pretty.c000066400000000000000000000063401414523752600202100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" 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); } flint2-2.8.4/fmpz_mpoly/gcd.c000066400000000000000000000021541414523752600160330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/gcd_brown.c000066400000000000000000000013751414523752600172460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/gcd_cofactors.c000066400000000000000000000030061414523752600200730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/gcd_hensel.c000066400000000000000000000013771414523752600173770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/gcd_subresultant.c000066400000000000000000000014021414523752600206410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/gcd_zippel.c000066400000000000000000000013771414523752600174240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/gcd_zippel2.c000066400000000000000000000014011414523752600174720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/gen.c000066400000000000000000000016601414523752600160500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/geobuckets.c000066400000000000000000000102521414523752600174270ustar00rootroot00000000000000/* 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 2.1 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" 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); } flint2-2.8.4/fmpz_mpoly/get_coeff_fmpz_fmpz.c000066400000000000000000000015651414523752600213140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mpoly/get_coeff_fmpz_monomial.c000066400000000000000000000017671414523752600221570ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mpoly/get_coeff_fmpz_ui.c000066400000000000000000000015521414523752600207510ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mpoly/get_coeff_si_fmpz.c000066400000000000000000000015471414523752600207530ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mpoly/get_coeff_si_ui.c000066400000000000000000000015421414523752600204070ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mpoly/get_coeff_ui_fmpz.c000066400000000000000000000015471414523752600207550ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mpoly/get_coeff_ui_ui.c000066400000000000000000000015421414523752600204110ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mpoly/get_coeff_vars_ui.c000066400000000000000000000102001414523752600207360ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/get_fmpz.c000066400000000000000000000017601414523752600171130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/get_mpz_signed_uiuiui.c000066400000000000000000000025101414523752600216610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.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 */ 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; } flint2-2.8.4/fmpz_mpoly/get_set_is_fmpz_poly.c000066400000000000000000000065331414523752600215270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 < 1) { fmpz_mpoly_zero(A, ctx); return; } 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); } flint2-2.8.4/fmpz_mpoly/get_str_pretty.c000066400000000000000000000073011414523752600203530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); } flint2-2.8.4/fmpz_mpoly/get_term.c000066400000000000000000000020031414523752600170750ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/get_term_coeff_fmpz.c000066400000000000000000000026741414523752600213110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/get_term_exp_fmpz.c000066400000000000000000000015051414523752600210130ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/get_term_exp_si.c000066400000000000000000000015751414523752600204610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/get_term_exp_ui.c000066400000000000000000000015421414523752600204550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/get_term_monomial.c000066400000000000000000000020061414523752600207730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/get_term_var_exp_si.c000066400000000000000000000015651414523752600213300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/get_term_var_exp_ui.c000066400000000000000000000015651414523752600213320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/inflate.c000066400000000000000000000045611414523752600167240ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/init.c000066400000000000000000000026161414523752600162440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/inlines.c000066400000000000000000000011631414523752600167360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_MPOLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mpoly.h" flint2-2.8.4/fmpz_mpoly/integral.c000066400000000000000000000131111414523752600170760ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/is_canonical.c000066400000000000000000000034231414523752600177200ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_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_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"); } } flint2-2.8.4/fmpz_mpoly/is_fmpz.c000066400000000000000000000013361414523752600167460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/is_gen.c000066400000000000000000000013401414523752600165360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/lead_coeff_vars.c000066400000000000000000000035431414523752600204030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/fmpz_mpoly/mpolyd.c000066400000000000000000000161571414523752600166120ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" 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_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_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_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_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; } 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_mpolyd_print(fmpz_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 (fmpz_is_zero(poly->coeffs + i)) continue; if (!first) printf(" + "); fmpz_print(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%d^%wd", j, e); } FLINT_ASSERT(k == 0); first = 0; } if (first) flint_printf("0"); } 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; } flint2-2.8.4/fmpz_mpoly/mul.c000066400000000000000000000202561414523752600160760ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 relevent 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 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 == 0 || C->length == 0) { fmpz_mpoly_zero(A, ctx); return; } if (fmpz_mpoly_is_fmpz(B, ctx)) { if (A == B || C == B) { fmpz_t t; fmpz_init_set(t, B->coeffs); fmpz_mpoly_scalar_mul_fmpz(A, C, t, ctx); fmpz_clear(t); } else { fmpz_mpoly_scalar_mul_fmpz(A, C, B->coeffs, ctx); } return; } if (fmpz_mpoly_is_fmpz(C, ctx)) { if (A == C || B == C) { fmpz_t t; fmpz_init_set(t, C->coeffs); fmpz_mpoly_scalar_mul_fmpz(A, B, t, ctx); fmpz_clear(t); } else { fmpz_mpoly_scalar_mul_fmpz(A, B, C->coeffs, 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; } flint2-2.8.4/fmpz_mpoly/mul_array.c000066400000000000000000001452401414523752600172750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)) /* 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++) { c2 = poly1 + 2*((slong) exp2[i]); if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { c = c2 + 2*((slong) exp3[j]); smul_ppmm(p[1], p[0], poly2[i], poly3[j]); add_ssaaaa(c[1], c[0], c[1], c[0], p[1], p[0]); } } } } } } /* 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 <= (FLINT_BITS - 2) && Bbits <= (FLINT_BITS - 2); 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(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 wil 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 <= (FLINT_BITS - 2) && Bbits <= (FLINT_BITS - 2)) { 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(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 ( 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; } flint2-2.8.4/fmpz_mpoly/mul_array_threaded.c000066400000000000000000000727721414523752600211460ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "thread_pool.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 <= FLINT_BITS - 2 && Bbits <= FLINT_BITS - 2) { 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 wil 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 <= FLINT_BITS - 2 && Bbits <= FLINT_BITS - 2) { 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 wil 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 (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; } flint2-2.8.4/fmpz_mpoly/mul_dense.c000066400000000000000000000247121414523752600172550ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" 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; } 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. */ 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 */ 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 irrelevent 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)) { count_leading_zeros(msb, 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(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) { 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; } flint2-2.8.4/fmpz_mpoly/mul_heap_threaded.c000066400000000000000000000676541414523752600207500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "thread_pool.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 divisons */ 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; } flint2-2.8.4/fmpz_mpoly/mul_johnson.c000066400000000000000000000452141414523752600176350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.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; } flint2-2.8.4/fmpz_mpoly/neg.c000066400000000000000000000016041414523752600160460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/pow_fmpz.c000066400000000000000000000041041414523752600171340ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/pow_fps.c000066400000000000000000000406041414523752600167550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" #include "long_extras.h" #include "fmpz_mod_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; } flint2-2.8.4/fmpz_mpoly/pow_ui.c000066400000000000000000000022171414523752600166000ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } } flint2-2.8.4/fmpz_mpoly/profile/000077500000000000000000000000001414523752600165705ustar00rootroot00000000000000flint2-2.8.4/fmpz_mpoly/profile/p-divides.c000066400000000000000000000170561414523752600206310ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_mpoly/profile/p-gcd.c000066400000000000000000000217651414523752600177410ustar00rootroot00000000000000/* 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 2.1 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_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; } flint2-2.8.4/fmpz_mpoly/profile/p-mul.c000066400000000000000000000160111414523752600177650ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_mpoly/profile/p-sqrt.c000066400000000000000000000065731414523752600201750ustar00rootroot00000000000000/* 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 2.1 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"); 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"); 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"); 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"); 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; } flint2-2.8.4/fmpz_mpoly/push_term_fmpz_fmpz.c000066400000000000000000000043241414523752600213750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_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_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); } flint2-2.8.4/fmpz_mpoly/push_term_fmpz_ui.c000066400000000000000000000031661414523752600210410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/quasidiv.c000066400000000000000000000012641414523752600171240ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpz_mpoly/quasidiv_heap.c000066400000000000000000000704741414523752600201320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) + FLINT_BITS - 2) && FLINT_ABS(bits3) <= FLINT_BITS - 2; 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 indicies */ 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 cofficient info */ fmpz_abs(lc_abs_lg, poly3 + 0); if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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) { /* optimation: 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) << (FLINT_BITS - 2))) == 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) + FLINT_BITS - 2) && FLINT_ABS(bits3) <= FLINT_BITS - 2; 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 indicies */ 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 cofficient info */ fmpz_abs(lc_abs_lg, poly3 + 0); if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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) { /* optimation: 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) << (FLINT_BITS - 2))) == 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); } flint2-2.8.4/fmpz_mpoly/quasidivrem.c000066400000000000000000000012011414523752600176170ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpz_mpoly/quasidivrem_heap.c000066400000000000000000000706251414523752600206340ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "longlong.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) + FLINT_BITS - 2) && FLINT_ABS(bits3) <= FLINT_BITS - 2; 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 indicies */ 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 cofficient info */ fmpz_abs(lc_abs_lg, poly3 + 0); if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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) + FLINT_BITS - 2) && FLINT_ABS(bits3) <= FLINT_BITS - 2; 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 indicies */ 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 cofficient info */ fmpz_abs(lc_abs_lg, poly3 + 0); if (small) { lc_abs = FLINT_ABS(poly3[0]); lc_sign = FLINT_SIGN_EXT(poly3[0]); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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); } flint2-2.8.4/fmpz_mpoly/quasidivrem_ideal.c000066400000000000000000000013231414523752600207620ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpz_mpoly/quasidivrem_ideal_heap.c000066400000000000000000000577601414523752600217770ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; slong ** hinds; 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 = (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_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; } flint2-2.8.4/fmpz_mpoly/randtest_bits.c000066400000000000000000000023571414523752600201500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/randtest_bound.c000066400000000000000000000022461414523752600203130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/randtest_bounds.c000066400000000000000000000022071414523752600204730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/realloc.c000066400000000000000000000036571414523752600167300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.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; } flint2-2.8.4/fmpz_mpoly/repack_bits.c000066400000000000000000000041451414523752600175660ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/resize.c000066400000000000000000000024111414523752600165730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/resultant.c000066400000000000000000000016341414523752600173210ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_mpoly/reverse.c000066400000000000000000000021771414523752600167560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/scalar_divexact_fmpz.c000066400000000000000000000030071414523752600214640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/scalar_divides_fmpz.c000066400000000000000000000041401414523752600213030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/scalar_fmma.c000066400000000000000000000201621414523752600175420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/scalar_mul_fmpz.c000066400000000000000000000030461414523752600204550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/select_exps.c000066400000000000000000000110651414523752600176150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 becuase 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 = 0; /* mask will be unused if bits > FLINT_BITS*/ for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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; } flint2-2.8.4/fmpz_mpoly/set.c000066400000000000000000000024341414523752600160720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/set_coeff_fmpz_fmpz.c000066400000000000000000000055161414523752600213300ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/set_coeff_fmpz_monomial.c000066400000000000000000000021261414523752600221610ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/set_coeff_fmpz_ui.c000066400000000000000000000016071414523752600207660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/set_coeff_si_fmpz.c000066400000000000000000000012621414523752600207610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/set_coeff_si_ui.c000066400000000000000000000012551414523752600204240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/set_coeff_ui_fmpz.c000066400000000000000000000012621414523752600207630ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/set_coeff_ui_ui.c000066400000000000000000000012551414523752600204260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/set_fmpz.c000066400000000000000000000015521414523752600171260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/set_si.c000066400000000000000000000014671414523752600165720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/set_str_pretty.c000066400000000000000000000024201414523752600203640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/fmpz_mpoly/set_term_coeff_fmpz.c000066400000000000000000000025541414523752600213220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/set_term_exp_fmpz.c000066400000000000000000000017571414523752600210400ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/set_term_exp_ui.c000066400000000000000000000020101414523752600204600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/set_ui.c000066400000000000000000000015521414523752600165670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/sort_terms.c000066400000000000000000000106511414523752600175000ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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) { count_leading_zeros(msb, 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; } flint2-2.8.4/fmpz_mpoly/sqrt_heap.c000066400000000000000000001052451414523752600172710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "longlong.h" #include "mpn_extras.h" /* 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) << (FLINT_BITS - 2); *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 explictly 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) << (FLINT_BITS - 2); 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); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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) << (FLINT_BITS - 2); 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); count_leading_zeros(lc_norm, lc_abs); lc_n = lc_abs << lc_norm; invert_limb(lc_i, 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; } flint2-2.8.4/fmpz_mpoly/sub.c000066400000000000000000000167201414523752600160730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/sub_fmpz.c000066400000000000000000000052411414523752600171230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly/term_content.c000066400000000000000000000034031414523752600177750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/test/000077500000000000000000000000001414523752600161075ustar00rootroot00000000000000flint2-2.8.4/fmpz_mpoly/test/t-add_sub.c000066400000000000000000000317041414523752600201220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("add/sub...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-add_sub_fmpz.c000066400000000000000000000067631414523752600211650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("add/sub_fmpz...."); fflush(stdout); /* 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; fmpz_t c; slong nvars, len, coeff_bits, exp_bits; fmpz_init(c); 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); 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); 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; ordering_t ord; fmpz_t c; slong nvars, len, coeff_bits, exp_bits; fmpz_init(c); 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); 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-add_sub_si.c000066400000000000000000000065501414523752600206160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("add/sub_si...."); fflush(stdout); /* 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); 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; 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); 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-add_sub_ui.c000066400000000000000000000065171414523752600206230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("add/sub_ui...."); fflush(stdout); /* 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; ulong 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 = 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); 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; ordering_t ord; ulong 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); 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-cmp.c000066400000000000000000000136001414523752600172730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int result; slong i, j1, j2; FLINT_TEST_INIT(state); flint_printf("cmp...."); fflush(stdout); /* 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-compose_fmpz_mpoly.c000066400000000000000000000310141414523752600224340ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j, v; FLINT_TEST_INIT(state); flint_printf("compose_fmpz_mpoly...."); fflush(stdout); { 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); 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); 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); 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); 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); 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); 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); 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/nvars1 + 1) + 1; len2 = n_randint(state, 10/nvars2 + 1) + 1; exp_bound1 = n_randint(state, 15/nvars1 + 2) + 2; exp_bound2 = n_randint(state, 15/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); 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); 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); flint_abort(); } if (!fmpz_equal(fe, ge)) { printf("FAIL\n"); flint_printf("Check composition and evalall commute\ni: %wd\n", i); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-compose_fmpz_poly.c000066400000000000000000000244321414523752600222650ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, v; FLINT_TEST_INIT(state); flint_printf("compose_fmpz_poly...."); fflush(stdout); { 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); 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); 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); 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/nvars1 + 1); len2 = n_randint(state, 40); exp_bound1 = n_randint(state, 200/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); 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); 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/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); 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); 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-content_vars.c000066400000000000000000000073371414523752600212330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("content_vars...."); fflush(stdout); 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); 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); SLONG_SWAP(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"); flint_abort(); } if (fmpz_mpoly_is_zero(g, ctx)) { if (!fmpz_mpoly_is_zero(f, ctx)) { flint_printf("FAIL: check zero content\n"); 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"); flint_abort(); } } if (!fmpz_mpoly_divides(t, f, g, ctx)) { flint_printf("FAIL: check content divides\n"); flint_abort(); } if (!fmpz_mpoly_content_vars(t, t, vars, num_vars, ctx)) { flint_printf("FAIL: check cofactor content could be computed\n"); flint_abort(); } if (!fmpz_mpoly_is_one(t, ctx)) { flint_printf("FAIL: check cofactor content is one\n"); flint_abort(); } } if (!fmpz_mpoly_content_vars(f, f, vars, num_vars, ctx)) { flint_printf("FAIL: check aliased content could be computed\n"); flint_abort(); } if (!fmpz_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: check aliasing\n"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-degree.c000066400000000000000000000140771414523752600177600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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"); 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"); flint_abort(); } if (degs_si[i] != fmpz_mpoly_degree_si(A, i, ctx)) { printf("FAIL\n"); flint_printf("Check individual degree_si\n"); 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"); flint_abort(); } fmpz_clear(degi); } for (i = 0; i < nvars; i++) { fmpz_clear(degs[i]); flint_free(degs[i]); } flint_free(degs); } int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("degree...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-degrees_term_exp_fits_ui_si.c000066400000000000000000000201121414523752600242460ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("degrees_term_exp_fits_ui_si...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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"); flint_abort(); } } else { printf("FAIL\nFLINT_BITS is not 64 or 32\n"); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-derivative_integral.c000066400000000000000000000226371414523752600225550ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j, result; slong tmul = 5; FLINT_TEST_INIT(state); flint_printf("derivative/integral...."); fflush(stdout); /* 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"); 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"); 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; ordering_t ord; slong nvars, len, len1, len2; slong idx, coeff_bits, exp_bits, exp_bits1, exp_bits2; 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); 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); 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; ordering_t ord; slong nvars, len, len1, len2; slong idx, coeff_bits, exp_bits, exp_bits1, exp_bits2; 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); 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); 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; ordering_t ord; slong nvars, len, len1, len2; slong idx, coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_t s, s1; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); 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); flint_abort(); } } fmpz_clear(s); fmpz_clear(s1); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(f1, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-div_monagan_pearce.c000066400000000000000000000311171414523752600223200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("div_monagan_pearce...."); fflush(stdout); { 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"); 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); 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; 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); max_bound = 1 + 500/ctx->minfo->nvars/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++) { 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); 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; 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); max_bound = 1 + 500/ctx->minfo->nvars/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++) { 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); 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; 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); max_bound = 1 + 500/ctx->minfo->nvars/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++) { 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-divides.c000066400000000000000000000270671414523752600201570ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "nmod_mpoly.h" int main(void) { int i, j, result, ret, max_threads = 5, tmul = 25; FLINT_TEST_INIT(state); flint_printf("divides...."); fflush(stdout); /* 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); 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); 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; 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; max_bound = 1 + 20/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++) { 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); 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; 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; max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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; 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; max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-divides_array.c000066400000000000000000000211521414523752600213420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result, ok1, ok2; FLINT_TEST_INIT(state); flint_printf("divides_array...."); fflush(stdout); /* 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); 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); 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); 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_clear(k, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-divides_heap_threaded.c000066400000000000000000000330721414523752600230050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "thread_pool.h" #include "fmpz_mpoly.h" int main(void) { int result, result2; slong i, j, max_threads = 5, tmul = 15; FLINT_TEST_INIT(state); flint_printf("divides_heap_threaded...."); fflush(stdout); { 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"); 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); 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); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-divides_monagan_pearce.c000066400000000000000000000333701414523752600231700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result, ok1, ok2; FLINT_TEST_INIT(state); flint_printf("divides_monagan_pearce...."); fflush(stdout); /* 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); 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; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; fmpz * shifts, * strides; 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, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 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); 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); 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, 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, 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); 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; 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); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 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); 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); 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, 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, 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); 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; 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); 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); 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-divrem_array.c000066400000000000000000000351201414523752600212010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result, ok1, ok2; FLINT_TEST_INIT(state); flint_printf("divrem_array...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-divrem_ideal_monagan_pearce.c000066400000000000000000000230251414523752600241610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, w, result; slong tmul = 10; FLINT_TEST_INIT(state); flint_printf("divrem_ideal_monagan_pearce...."); fflush(stdout); /* 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; ordering_t ord; slong nvars, len, len1, len2; slong coeff_bits, exp_bits, exp_bits1, exp_bits2; fmpz_mpoly_struct * qarr[1], * darr[1]; 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_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); 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; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; slong coeff_bits; 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)); ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 9) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); 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; exp_bound = n_randint(state, 2 + 175/nvars/nvars) + 1; exp_bound1 = n_randint(state, 2 + 175/nvars/nvars) + 1; exp_bound2 = n_randint(state, 2 + 175/nvars/nvars) + 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); 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; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; slong coeff_bits; 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)); ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); 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; exp_bound = n_randint(state, 3 + 200/nvars/nvars) + 1; exp_bound1 = n_randint(state, 3 + 200/nvars/nvars) + 1; exp_bound2 = n_randint(state, 3 + 200/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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-divrem_monagan_pearce.c000066400000000000000000000334711414523752600230310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("divrem_monagan_pearce...."); fflush(stdout); /* 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; slong coeff_bits, exp_bits, exp_bits1, exp_bits2; 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_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); 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, 15); len1 = n_randint(state, 15); len2 = n_randint(state, 15) + 1; exp_bound = n_randint(state, 800/nvars/nvars) + 1; exp_bound1 = n_randint(state, 800/nvars/nvars) + 1; exp_bound2 = n_randint(state, 800/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_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); 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, 15); len1 = n_randint(state, 15); len2 = n_randint(state, 15) + 1; exp_bound = n_randint(state, 800/nvars/nvars) + 1; exp_bound1 = n_randint(state, 800/nvars/nvars) + 1; exp_bound2 = n_randint(state, 800/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); 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); 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, 15); len1 = n_randint(state, 15); len2 = n_randint(state, 15) + 1; exp_bound = n_randint(state, 800/nvars/nvars) + 1; exp_bound1 = n_randint(state, 800/nvars/nvars) + 1; exp_bound2 = n_randint(state, 800/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); 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); 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, 15); len1 = n_randint(state, 15); len2 = n_randint(state, 15) + 1; exp_bound = n_randint(state, 800/nvars/nvars) + 1; exp_bound1 = n_randint(state, 800/nvars/nvars) + 1; exp_bound2 = n_randint(state, 800/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_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); 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, 15); len1 = n_randint(state, 15); len2 = n_randint(state, 15) + 1; exp_bound = n_randint(state, 800/nvars/nvars) + 1; exp_bound1 = n_randint(state, 800/nvars/nvars) + 1; exp_bound2 = n_randint(state, 800/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_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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-evaluate.c000066400000000000000000000304001414523752600203170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j, v; FLINT_TEST_INIT(state); flint_printf("evaluate_one_fmpz/all_fmpz...."); fflush(stdout); { 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); 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); 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); flint_abort(); } if (!fmpz_mpoly_evaluate_one_fmpz(A, B, 1, C + 1, ctx)) { printf("FAIL\n"); flint_printf("Check example 4\n", i); 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); 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++) { ordering_t ord; 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; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); 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); 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); 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); 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++) { ordering_t ord; 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; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); 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); 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); 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); 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; ordering_t ord; fmpz ** vals; slong nvars, len1, len2, 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(fg, ctx); fmpz_init(fe); fmpz_init(ge); fmpz_init(fge); fmpz_init(t); len1 = n_randint(state, 500); len2 = n_randint(state, 500); exp_bound1 = n_randint(state, 5000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 5000/nvars/nvars) + 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); 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); 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; ordering_t ord; fmpz ** vals; slong nvars, len1, len2, 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(fg, ctx); fmpz_init(fe); fmpz_init(ge); fmpz_init(fge); fmpz_init(t); len1 = n_randint(state, 100); len2 = n_randint(state, 100); exp_bound1 = n_randint(state, 1000/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1000/nvars/nvars) + 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-gcd.c000066400000000000000000000674701414523752600172670ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" 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); 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); 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } int main(void) { const slong max_threads = 5; slong i, j, k, tmul = 10; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 1; #endif flint_printf("gcd...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-gcd_brown.c000066400000000000000000000115131414523752600204610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } int main(void) { slong tmul = 10; slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_brown...."); fflush(stdout); { 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; 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); degbound = 1 + 50/ctx->minfo->nvars/ctx->minfo->nvars; 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-gcd_cofactors.c000066400000000000000000001041201414523752600213120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); } int main(void) { const slong max_threads = 5; slong i, j, k, tmul = 2; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 1; #endif flint_printf("gcd_cofactors...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-gcd_hensel.c000066400000000000000000000124561414523752600206170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 20; FLINT_TEST_INIT(state); flint_printf("gcd_hensel...."); fflush(stdout); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-gcd_subresultant.c000066400000000000000000000123531414523752600220700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } int main(void) { slong i, j; slong tmul = 10; FLINT_TEST_INIT(state); flint_printf("gcd_subresultant...."); fflush(stdout); { 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/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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-gcd_zippel.c000066400000000000000000000230651414523752600206420ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_zippel...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-gcd_zippel2.c000066400000000000000000000203661414523752600207250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 20; FLINT_TEST_INIT(state); flint_printf("gcd_zippel2...."); fflush(stdout); { 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-gen.c000066400000000000000000000050711414523752600172700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gen/is_gen...."); fflush(stdout); for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f1, f2; ordering_t ord; slong nvars, len, coeff_bits, exp_bits, k1, k2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); 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); 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); flint_abort(); } fmpz_mpoly_clear(f1, ctx); fmpz_mpoly_clear(f2, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-get_coeff_vars_ui.c000066400000000000000000000122541414523752600221710ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j1, j2; FLINT_TEST_INIT(state); flint_printf("get_coeff_vars_ui...."); fflush(stdout); /* 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"); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-get_set_coeff.c000066400000000000000000000074441414523752600213210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j, k, result; FLINT_TEST_INIT(state); flint_printf("get_set_coeff...."); fflush(stdout); /* 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); 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); flint_abort(); } flint_free(exp); } fmpz_mpoly_clear(f, ctx); fmpz_clear(c); fmpz_clear(d); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-get_set_coeff_fmpz_monomial.c000066400000000000000000000073671414523752600242540ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("get/set_coeff_fmpz_monomial...."); fflush(stdout); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-get_set_is_fmpz.c000066400000000000000000000043331414523752600217000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("get_set_is_fmpz...."); fflush(stdout); /* 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); 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); 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); flint_abort(); } fmpz_clear(c); fmpz_clear(d); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-get_set_str_pretty.c000066400000000000000000000034741414523752600224550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("get_set_str_pretty...."); fflush(stdout); { 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(f1, ctx); } } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-get_set_term_coeff_fmpz.c000066400000000000000000000043471414523752600234030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("get/set_term_coeff_fmpz...."); fflush(stdout); /* 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); 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); flint_abort(); } } } fmpz_mpoly_clear(f, ctx); fmpz_clear(c); fmpz_clear(d); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-get_set_term_exp_fmpz.c000066400000000000000000000057121414523752600231120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get/set_term_exp_fmpz...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-get_set_term_exp_si.c000066400000000000000000000054061414523752600225510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get/set_term_exp_si...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-get_set_term_exp_ui.c000066400000000000000000000053711414523752600225540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get/set_term_exp_ui...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-get_term.c000066400000000000000000000041271414523752600203260ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("get_term...."); fflush(stdout); /* 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); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-get_term_monomial.c000066400000000000000000000050141414523752600222150ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("get_term_monomial...."); fflush(stdout); /* 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-inflate_deflate.c000066400000000000000000000154371414523752600216340ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j, success; FLINT_TEST_INIT(state); flint_printf("inflate_deflate...."); fflush(stdout); /* 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-init.c000066400000000000000000000025701414523752600174630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); /* Check aliasing of a and c */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-mul.c000066400000000000000000000222121414523752600173100ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" int main(void) { int i, j, result, max_threads = 5; slong tmul = 10; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 2; #endif flint_printf("mul...."); fflush(stdout); /* 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"); 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"); 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"); 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); 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, nvars; flint_bitcnt_t coeff_bits, exp_bound, exp_bound1, exp_bound2; fmpz_mpoly_ctx_init_rand(ctx, state, 4); nvars = 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/nvars/nvars); exp_bound1 = 3 + n_randint(state, 1 + 100/nvars/nvars); exp_bound2 = 3 + n_randint(state, 1 + 100/nvars/nvars); len = exp_bound + 1; len1 = exp_bound1 + 1; len2 = exp_bound2 + 1; for (j = n_randint(state, nvars) + 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); 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, nvars; flint_bitcnt_t coeff_bits, exp_bound, exp_bound1, exp_bound2; fmpz_mpoly_ctx_init_rand(ctx, state, 4); nvars = 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/nvars/nvars); exp_bound1 = 3 + n_randint(state, 1 + 100/nvars/nvars); exp_bound2 = 3 + n_randint(state, 1 + 100/nvars/nvars); len = exp_bound + 1; len1 = exp_bound1 + 1; len2 = exp_bound2 + 1; for (j = n_randint(state, nvars) + 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-mul_array.c000066400000000000000000000140201414523752600205040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("mul_array...."); fflush(stdout); /* 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; 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; max_bound = max_bound/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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; 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); max_bound = 200/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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; 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); max_bound = 200/ctx->minfo->nvars/ctx->minfo->nvars; 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-mul_array_threaded.c000066400000000000000000000146321414523752600223550ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result, max_threads = 5; int tmul = 20; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 1; #endif flint_printf("mul_array_threaded...."); fflush(stdout); /* 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; 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; max_bound = max_bound/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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; 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); max_bound = 200/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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; 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); max_bound = 200/ctx->minfo->nvars/ctx->minfo->nvars; 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-mul_dense.c000066400000000000000000000140421414523752600204700ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j, result, success; FLINT_TEST_INIT(state); flint_printf("mul_dense...."); fflush(stdout); /* 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/ctx->minfo->nvars; 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-mul_heap_threaded.c000066400000000000000000000154461414523752600221600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j, result, max_threads = 5; slong tmul = 10; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 2; #endif flint_printf("mul_heap_threaded...."); fflush(stdout); { 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"); 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); 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); 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-mul_johnson.c000066400000000000000000000177511414523752600210620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("mul_johnson...."); fflush(stdout); /* 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; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; slong coeff_bits; int ok1; 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); exp_bound = n_randint(state, 800/nvars/nvars) + 1; exp_bound1 = n_randint(state, 800/nvars/nvars) + 1; exp_bound2 = n_randint(state, 800/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); 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); 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); 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); 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-neg.c000066400000000000000000000053661414523752600172770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg...."); fflush(stdout); /* Check -(-a) == a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f, g, h; 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); 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); 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; 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_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); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-pow_fps.c000066400000000000000000000106021414523752600201700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "fmpz_mpoly_factor.h" 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); } } int main(void) { slong i, j, tmul = 5; FLINT_TEST_INIT(state); flint_printf("pow_fps...."); fflush(stdout); /* 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); 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-pow_ui.c000066400000000000000000000103151414523752600200160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" 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_set_ui(res, 1, 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); } } int main(void) { slong i, j, tmul = 20; FLINT_TEST_INIT(state); flint_printf("pow_ui...."); fflush(stdout); /* 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); 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-print_parse.c000066400000000000000000000067551414523752600210570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" void check_match( const char * sa, const char * sb, const char ** vars, const fmpz_mpoly_ctx_t ctx) { fmpz_mpoly_t a, b; fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(b, ctx); if (0 != fmpz_mpoly_set_str_pretty(a, sa, vars, ctx)) { flint_printf("FAIL: set_str failed\n"); flint_printf("sa = %s\n", sa); flint_abort(); } if (0 != fmpz_mpoly_set_str_pretty(b, sb, vars, ctx)) { flint_printf("FAIL: set_str failed\n"); flint_printf("sb = %s\n", sb); flint_abort(); } if (!fmpz_mpoly_equal(a, b, ctx)) { flint_printf("FAIL: results do not match\n"); flint_printf("sa = %s, sb = %s\n", sa, sb); flint_printf("a: "); fmpz_mpoly_print_pretty(a, vars, ctx); flint_printf("\n"); flint_printf("b: "); fmpz_mpoly_print_pretty(b, vars, ctx); flint_printf("\n"); flint_abort(); } fmpz_mpoly_clear(a, ctx); fmpz_mpoly_clear(b, ctx); } int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("print_parse...."); fflush(stdout); { 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"}; { fmpz_mpoly_ctx_init(ctx, 6, ORD_LEX); check_match("-(1+x)^2", "-1-2*x-x^2", vars, ctx); check_match("x+--y", "x+y", vars, ctx); check_match("-x+-x*-y", "-x+x*y", vars, ctx); check_match("-x+-x^2*-y^3/-x*-y-y", "-x+x*y^4-y", vars, ctx); check_match("1+-x+x^2+-x^3+x^4+-x^5+x^6+-x^7", "1-x+x^2-x^3+x^4-x^5+x^6-x^7", vars, ctx); fmpz_mpoly_ctx_clear(ctx); } /* check that parsing inverts printing */ for (i = 0; i < 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 < 4000; 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); if (0 != fmpz_mpoly_set_str_pretty(f1, str, vars, ctx)) { flint_printf("FAIL: set_str failed\n"); flint_printf("i = %wd, len1 = %wd\n", i ,len1); flint_abort(); } fmpz_mpoly_assert_canonical(f1, ctx); flint_free(str); if (!fmpz_mpoly_equal(f, f1, ctx)) { flint_printf("FAIL: check that parsing inverts printing\n"); flint_printf("i = %wd, len1 = %wd\n", i ,len1); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(f1, ctx); fmpz_mpoly_ctx_clear(ctx); } } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-push_term_fmpz_fmpz.c000066400000000000000000000074141414523752600226200ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("push_term_fmpz_fmpz...."); fflush(stdout); /* 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; fmpz ** 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 = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); exp2 = (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]); } 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); /* 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); /* 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); 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); 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 pushed polynomial matches add\ni=%wd\n",i,j); 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); for (k = 0; k < nvars; k++) { fmpz_clear(exp2[k]); flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(exp2); flint_free(exp); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-push_term_fmpz_ui.c000066400000000000000000000064521414523752600222620ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("push_term_fmpz_ui...."); fflush(stdout); /* 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-quasidiv_heap.c000066400000000000000000000303511414523752600213400ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int result; slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("quasidiv_heap...."); fflush(stdout); /* 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); 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; 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); max_bound = 1 + 200/ctx->minfo->nvars/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++) { 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); 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; 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); max_bound = 1 + 200/ctx->minfo->nvars/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++) { 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); 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; 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); max_bound = 1 + 200/ctx->minfo->nvars/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++) { 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-quasidivrem_heap.c000066400000000000000000000342741414523752600220540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("quasidivrem_heap...."); fflush(stdout); /* 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; ordering_t ord; slong nvars, len, len1, len2; flint_bitcnt_t coeff_bits, exp_bits, exp_bits1, exp_bits2; 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(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); 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; 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_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; exp_bound = n_randint(state, 1 + 200/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1 + 200/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1 + 200/nvars/nvars) + 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"); 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; 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_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; exp_bound = n_randint(state, 1 + 200/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1 + 200/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1 + 200/nvars/nvars) + 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"); 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; 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_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; exp_bound = n_randint(state, 1 + 200/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1 + 200/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1 + 200/nvars/nvars) + 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"); 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; 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_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; exp_bound = n_randint(state, 1 + 200/nvars/nvars) + 1; exp_bound1 = n_randint(state, 1 + 200/nvars/nvars) + 1; exp_bound2 = n_randint(state, 1 + 200/nvars/nvars) + 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-quasidivrem_ideal_heap.c000066400000000000000000000176451414523752600232150ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j, w, result; FLINT_TEST_INIT(state); flint_printf("quasidivrem_ideal_heap...."); fflush(stdout); /* 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; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; slong coeff_bits; 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)); ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); 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; exp_bound = n_randint(state, 10/nvars + 1) + 2; exp_bound1 = n_randint(state, 25/nvars + 1) + 2; exp_bound2 = n_randint(state, 20/nvars + 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); 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; ordering_t ord; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2, num; slong coeff_bits; 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)); ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 10) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); 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; exp_bound = n_randint(state, 10/nvars + 1) + 2; exp_bound1 = n_randint(state, 25/nvars + 1) + 2; exp_bound2 = n_randint(state, 20/nvars + 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-repack_bits.c000066400000000000000000000150621414523752600210060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j, success; FLINT_TEST_INIT(state); flint_printf("repack...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-resize.c000066400000000000000000000061371414523752600200240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("resize...."); fflush(stdout); 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); flint_abort(); } if (!fmpz_mpoly_equal(f1, f3, ctx)) { printf("FAIL\n"); flint_printf("Check resize+setterm matches add\ni=%wd\n",i); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-resultant_discriminant.c000066400000000000000000000173271414523752600233130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("resultant_discriminant...."); fflush(stdout); /* 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"); flint_abort(); } if (!fmpz_mpoly_equal(d, d1, ctx)) { flint_printf("FAIL: Check quadratic polynomial\n"); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-reverse.c000066400000000000000000000054461414523752600202000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("reverse...."); fflush(stdout); /* 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; 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); 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); 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; 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_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); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-scalar_divexact_fmpz.c000066400000000000000000000071101414523752600227030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("scalar_divexact_fmpz...."); fflush(stdout); /* 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; fmpz_t c; slong nvars, len, coeff_bits, exp_bits; fmpz_init(c); 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); 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); 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; ordering_t ord; fmpz_t c; slong nvars, len, coeff_bits, exp_bits; fmpz_init(c); 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(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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-scalar_divexact_si.c000066400000000000000000000067001414523752600223460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("scalar_divexact_si...."); fflush(stdout); /* 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_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); 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; 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(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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-scalar_divexact_ui.c000066400000000000000000000066401414523752600223530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("scalar_divexact_ui...."); fflush(stdout); /* 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; ulong 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 = 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); 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; ordering_t ord; ulong 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(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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-scalar_divides_fmpz.c000066400000000000000000000071531414523752600225320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("scalar_divides_fmpz...."); fflush(stdout); /* 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; fmpz_t c; slong nvars, len, coeff_bits, exp_bits; fmpz_init(c); 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); 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); 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; ordering_t ord; fmpz_t c; slong nvars, len, coeff_bits, exp_bits; fmpz_init(c); 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(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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-scalar_fmma.c000066400000000000000000000074311414523752600207660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("scalar_fmma...."); fflush(stdout); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-scalar_mul_fmpz.c000066400000000000000000000076071414523752600217040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpz...."); fflush(stdout); /* 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; ordering_t ord; fmpz_t a, b, c; slong nvars, len, coeff_bits, exp_bits; fmpz_init(a); fmpz_init(b); fmpz_init(c); 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); 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); 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; ordering_t ord; fmpz_t c; slong nvars, len, coeff_bits, exp_bits; fmpz_init(c); 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(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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-scalar_mul_si.c000066400000000000000000000075171414523752600213430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_si...."); fflush(stdout); /* 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; ordering_t ord; slong a, b, 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); 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); 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; 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(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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-scalar_mul_ui.c000066400000000000000000000071721414523752600213420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_ui...."); fflush(stdout); /* 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; ordering_t ord; ulong a, b, 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); 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); 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; ordering_t ord; ulong 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(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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-set_equal.c000066400000000000000000000067431414523752600205100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set/equal...."); fflush(stdout); /* 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; 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); 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); 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); 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); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-set_fmpz.c000066400000000000000000000040351414523752600203450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_fmpz...."); fflush(stdout); /* Set to random integer and compare */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; ordering_t ord; fmpz_t c, d; slong nvars, len, coeff_bits, exp_bits, j; ulong * exp; fmpz_init(c); fmpz_init(d); ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); 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); flint_abort(); } flint_free(exp); fmpz_mpoly_clear(f, ctx); fmpz_clear(c); fmpz_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-set_si.c000066400000000000000000000036201414523752600200030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_si...."); fflush(stdout); /* Set to random integer and compare */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; ordering_t ord; slong c, d; slong nvars, len, coeff_bits, exp_bits, j; ulong * exp; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); 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); flint_abort(); } flint_free(exp); fmpz_mpoly_clear(f, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-set_ui.c000066400000000000000000000036071414523752600200120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_ui...."); fflush(stdout); /* Set to random integer and compare */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t f; ordering_t ord; ulong c, d; slong nvars, len, coeff_bits, exp_bits, j; ulong * exp; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 1; fmpz_mpoly_ctx_init(ctx, nvars, ord); 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); flint_abort(); } flint_free(exp); fmpz_mpoly_clear(f, ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-sort_terms.c000066400000000000000000000040731414523752600207210ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("sort_terms...."); fflush(stdout); /* 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-sqrt_heap.c000066400000000000000000000252541414523752600205120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("sqrt_heap...."); fflush(stdout); { 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"); 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"); 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"); 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"); 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); 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"); 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); 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); 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"); flint_abort(); } if (!fmpz_mpoly_is_zero(h, ctx)) { printf("FAIL\n"); flint_printf("Nonsquare returns 0 sqrt\n"); 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"); flint_abort(); } } else if (!fmpz_mpoly_is_zero(g, ctx)) { flint_printf("FAIL\n"); flint_printf("Nonsquare returns 0 sqrt\n"); 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"); 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"); 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_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-term_content.c000066400000000000000000000072711414523752600212240ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("term_content...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); flint_abort(); } } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(k, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-total_degree.c000066400000000000000000000117071414523752600211600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); } int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("total_degree...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-univar.c000066400000000000000000000070141414523752600200220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("univar...."); fflush(stdout); /* 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-univar_resultant.c000066400000000000000000000126771414523752600221360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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"); 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); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("univar_resultant...."); fflush(stdout); { 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"); 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"); 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"); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/test/t-used_vars.c000066400000000000000000000045641414523752600205200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("used_vars...."); fflush(stdout); 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"); 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"); flint_abort(); } } } flint_free(used); fmpz_clear(one); fmpz_clear(fdeg); fmpz_mpoly_clear(f, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly/to_from_fmpz_poly.c000066400000000000000000000140761414523752600210500ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly/univar.c000066400000000000000000000437661414523752600166200ustar00rootroot00000000000000/* 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 2.1 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_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; } 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); } SLONG_SWAP(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; } flint2-2.8.4/fmpz_mpoly/void_ring.c000066400000000000000000000071701414523752600172610ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_mpoly_factor.h000066400000000000000000000514021414523752600166410ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define FMPZ_MPOLY_FACTOR_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "fmpz_mpoly.h" #include "fmpq_poly.h" #include "fmpz_poly_factor.h" #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ FLINT_DLL void tuple_print(fmpz * alpha, slong n); FLINT_DLL void tuple_saturate(fmpz * alpha, slong n, slong m); FLINT_DLL void tuple_next(fmpz * alpha, slong n); /*****************************************************************************/ 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]; FMPZ_MPOLY_FACTOR_INLINE void fmpz_mpoly_factor_init(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { fmpz_init_set_ui(f->constant, 1); fmpz_init_set_ui(f->constant_den, 1); f->poly = NULL; f->exp = NULL; f->num = 0; f->alloc = 0; } FLINT_DLL void fmpz_mpoly_factor_init2(fmpz_mpoly_factor_t f, slong alloc, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_factor_realloc(fmpz_mpoly_factor_t f, slong alloc, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_factor_fit_length(fmpz_mpoly_factor_t f, slong len, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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; } FMPZ_MPOLY_FACTOR_INLINE 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); } FMPZ_MPOLY_FACTOR_INLINE 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); } 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); } FMPZ_MPOLY_FACTOR_INLINE 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); } FLINT_DLL void fmpz_mpoly_factor_set(fmpz_mpoly_factor_t f, const fmpz_mpoly_factor_t g, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mpoly_factor_cmp(const fmpz_mpoly_factor_t f, const fmpz_mpoly_factor_t g, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpoly_factor_print_pretty(const fmpz_mpoly_factor_t f, const char ** vars, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mpoly_factor_content(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mpoly_factor_squarefree(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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; } FMPZ_MPOLY_FACTOR_INLINE 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); } FMPZ_MPOLY_FACTOR_INLINE void fmpz_mpoly_factor_zero(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { f->num = 0; fmpz_zero(f->constant); } FMPZ_MPOLY_FACTOR_INLINE void fmpz_mpoly_factor_one(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx) { f->num = 0; fmpz_one(f->constant); } FLINT_DLL void fmpz_mpoly_factor_sort(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mpoly_factor_expand(fmpz_mpoly_t A, const fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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; } FMPZ_MPOLY_FACTOR_INLINE 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; } FMPZ_MPOLY_FACTOR_INLINE 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; } /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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; } FLINT_DLL void fmpz_mpolyv_clear(fmpz_mpolyv_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpolyv_print_pretty(const fmpz_mpolyv_t poly, const char ** x, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpolyv_fit_length(fmpz_mpolyv_t A, slong length, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void fmpz_mpolyv_set_coeff(fmpz_mpolyv_t A, slong i, fmpz_mpoly_t c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int _fmpz_mpoly_vec_content_mpoly(fmpz_mpoly_t g, const fmpz_mpoly_struct * A, slong Alen, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void _fmpz_mpoly_vec_divexact_mpoly(fmpz_mpoly_struct * A, slong Alen, const fmpz_mpoly_t c, const fmpz_mpoly_ctx_t ctx); FLINT_DLL void _fmpz_mpoly_vec_mul_mpoly(fmpz_mpoly_struct * A, slong Alen, const fmpz_mpoly_t c, const fmpz_mpoly_ctx_t ctx); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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]; FLINT_DLL void fmpz_poly_pfrac_init(fmpz_poly_pfrac_t I); FLINT_DLL void fmpz_poly_pfrac_clear(fmpz_poly_pfrac_t I); FLINT_DLL int fmpz_poly_pfrac_precompute(fmpz_poly_pfrac_t I, const fmpz_poly_struct * b, slong r); FLINT_DLL 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]; FLINT_DLL 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); FLINT_DLL void fmpz_mpoly_pfrac_clear(fmpz_mpoly_pfrac_t I, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mpoly_pfrac(slong l, fmpz_mpoly_t t, const slong * degs, fmpz_mpoly_pfrac_t I, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void _fmpz_mpoly_get_lead0(fmpz_mpoly_t c, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL void fmpz_bpoly_clear(fmpz_bpoly_t A); FLINT_DLL 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); } FLINT_DLL 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; } FLINT_DLL slong fmpz_bpoly_degree1(const fmpz_bpoly_t A); FLINT_DLL void fmpz_bpoly_set_coeff(fmpz_bpoly_t A, slong exp0, slong exp1, const fmpz_t c); FLINT_DLL 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); FLINT_DLL 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; } FLINT_DLL void fmpz_tpoly_fit_length(fmpz_tpoly_t A, slong len); FLINT_DLL void fmpz_tpoly_clear(fmpz_tpoly_t A); FLINT_DLL void fmpz_bpoly_factor(fmpz_poly_t c, fmpz_tpoly_t F, fmpz_bpoly_t B); FLINT_DLL 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); /*****************************************************************************/ FMPZ_MPOLY_FACTOR_INLINE 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_DLL int _fmpz_mpoly_factor_squarefree(fmpz_mpoly_factor_t f, fmpz_mpoly_t A, const fmpz_t e, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int fmpz_mpoly_factor_irred(fmpz_mpoly_factor_t f, const fmpz_mpoly_ctx_t ctx, unsigned int algo); FLINT_DLL int fmpz_mpoly_factor_zassenhaus(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mpoly_factor_wang(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL int fmpz_mpoly_factor_zippel(fmpz_mpoly_factor_t f, const fmpz_mpoly_t A, const fmpz_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /****************************************************************************/ FLINT_DLL void fmpz_mpoly_compression_do(fmpz_mpoly_t L, const fmpz_mpoly_ctx_t Lctx, fmpz * Acoeffs, slong Alen, mpoly_compression_t M); FLINT_DLL 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 flint2-2.8.4/fmpz_mpoly_factor/000077500000000000000000000000001414523752600164665ustar00rootroot00000000000000flint2-2.8.4/fmpz_mpoly_factor/add.c000066400000000000000000000020661414523752600173660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly_factor/bpoly.c000066400000000000000000000105711414523752600177630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mpoly_factor/bpoly_factor.c000066400000000000000000000734211414523752600213240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "nmod_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_div(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); Bevalfac->num = 0; 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; } flint2-2.8.4/fmpz_mpoly_factor/clear.c000066400000000000000000000014171414523752600177230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly_factor/cmp.c000066400000000000000000000017321414523752600174140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly_factor/compression.c000066400000000000000000000061171414523752600212000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly_factor/eval.c000066400000000000000000000110551414523752600175630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "n_poly.h" /* only E and alphas are shifted by "var" so output is in E[0] and first relevent 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); } flint2-2.8.4/fmpz_mpoly_factor/expand.c000066400000000000000000000021121414523752600201050ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly_factor/factor.c000066400000000000000000000526521414523752600201220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "fmpq_poly.h" #include "fmpz_mod_mpoly.h" #include "nmod_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 satifies _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); } flint2-2.8.4/fmpz_mpoly_factor/factor_bound_si.c000066400000000000000000000024451414523752600217770ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "long_extras.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; } flint2-2.8.4/fmpz_mpoly_factor/factor_content.c000066400000000000000000000121001414523752600216340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 primitve 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--) SLONG_SWAP(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; } flint2-2.8.4/fmpz_mpoly_factor/factor_squarefree.c000066400000000000000000000065071414523752600223420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly_factor/fit_length.c000066400000000000000000000013011414523752600207500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fmpz_mpoly_factor/gcd_algo.c000066400000000000000000001557201414523752600204030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_fdiv_ui(Acoeff + i, out->mod.n); 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_fdiv_ui(Acoeff + i, (out + 0)->mod.n); 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); TMP_START; fmpz_init(g); /* 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); /* compute the coefficient of G */ fmpz_abs(g, B->coeffs + 0); _fmpz_vec_content_chained(g, A->coeffs, A->length, g); _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); fmpz_swap(G->coeffs + 0, g); _fmpz_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); } fmpz_clear(g); TMP_END; 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); } flint2-2.8.4/fmpz_mpoly_factor/gcd_brown.c000066400000000000000000000172601414523752600206040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "nmod_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; } flint2-2.8.4/fmpz_mpoly_factor/gcd_brown_threaded.c000066400000000000000000001042211414523752600224360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "nmod_mpoly.h" #include "thread_pool.h" #include "fmpq.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]--; } } } } 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_t zero, max, sum; fmpz_mpoly_t A; const ulong * exp_left = S->left_exp; const ulong * exp_right = S->right_exp; TMP_INIT; *A = *S->poly; TMP_START; 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 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; } } _fmpz_multi_crt_run_p(output, P, (const fmpz * const *) input); 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; } 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 = _fmpz_multi_crt_local_size(base->CRT); 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 useage 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 ** mptrs; 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 = (fmpz_mpoly_struct **) flint_malloc( (num_threads + 1)*sizeof(fmpz_mpoly_struct *)); abarptrs = (fmpz_mpoly_struct **) flint_malloc( (num_threads + 1)*sizeof(fmpz_mpoly_struct *)); bbarptrs = (fmpz_mpoly_struct **) flint_malloc( (num_threads + 1)*sizeof(fmpz_mpoly_struct *)); mptrs = (fmpz **) flint_malloc((num_threads + 1)*sizeof(fmpz *)); splitargs = (_splitworker_arg_struct *) flint_malloc( num_threads*sizeof(_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) << (FLINT_BITS - 2); 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; mptrs[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; mptrs[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; mptrs[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_p(joinbase->CRT, (const fmpz * const *) mptrs, 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 mptrs */ fmpz_one(temp); for (i = 0; i < num_images; i++) { fmpz_mul(temp, temp, mptrs[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(mptrs); 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; } flint2-2.8.4/fmpz_mpoly_factor/gcd_hensel.c000066400000000000000000000273301414523752600207320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly_factor/gcd_zippel.c000066400000000000000000000165321414523752600207610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_change_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--) SLONG_SWAP(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_change_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; } flint2-2.8.4/fmpz_mpoly_factor/gcd_zippel2.c000066400000000000000000002167621414523752600210520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "fmpz_mod_mpoly_factor.h" #include "fmpz_mod_vec.h" #include "n_poly.h" #include "nmod_mpoly_factor.h" #include "ulong_extras.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) << (FLINT_BITS - 2); 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) << (FLINT_BITS - 2); 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; } flint2-2.8.4/fmpz_mpoly_factor/get_set_lead0.c000066400000000000000000000021701414523752600213310ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fmpz_mpoly_factor/init.c000066400000000000000000000020601414523752600175730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly_factor/inlines.c000066400000000000000000000011611414523752600202720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_MPOLY_FACTOR_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpz_mpoly_factor.h" flint2-2.8.4/fmpz_mpoly_factor/interp.c000066400000000000000000000241541414523752600201410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" #include "nmod_mpoly.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_fdiv_ui(Acoeff + Ai, pctx->mod.n); 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; } flint2-2.8.4/fmpz_mpoly_factor/irred_wang.c000066400000000000000000000217541414523752600207640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly_factor/irred_zassenhaus.c000066400000000000000000000263761414523752600222210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "nmod_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; } flint2-2.8.4/fmpz_mpoly_factor/irred_zippel.c000066400000000000000000000700261414523752600213270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "nmod_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_fdiv_ui(A->coeffs + i, ctxp->mod.n); 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_fdiv_ui(t, ctxp->mod.n); 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; } void nmod_poly_set_fmpz_poly(nmod_poly_t a, const fmpz_poly_t b) { slong i; nmod_poly_fit_length(a, b->length); for (i = 0; i < b->length; i++) a->coeffs[i] = fmpz_fdiv_ui(b->coeffs + i, a->mod.n); a->length = b->length; _nmod_poly_normalise(a); } /* 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) << (FLINT_BITS - 2); 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; nmod_poly_set_fmpz_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_fdiv_ui(alpha + i, ctxp->mod.n); 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; } flint2-2.8.4/fmpz_mpoly_factor/lcc_kaltofen.c000066400000000000000000000443431414523752600212660ustar00rootroot00000000000000#include "fmpz_mpoly_factor.h" #include "n_poly.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_div(A->p + i, A->p + i, g); fmpz_poly_div(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); SLONG_SWAP(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); SLONG_SWAP(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_printf("non-exact division fmpz_mpoly_factor_divexact_mpoly_pow_ui"); flint_abort(); } 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_printf("non-exact division fmpz_mpoly_factor_divexact_mpoly_pow_ui"); flint_abort(); } 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; } flint2-2.8.4/fmpz_mpoly_factor/lcc_wang.c000066400000000000000000000101161414523752600204060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "n_poly.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; } flint2-2.8.4/fmpz_mpoly_factor/mpoly_hlift.c000066400000000000000000000331431414523752600211640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly_factor/mpoly_pfrac.c000066400000000000000000000202361414523752600211500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly_factor/mpolyl.c000066400000000000000000000033601414523752600201500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fmpz_mpoly_factor/mpolyv.c000066400000000000000000000111411414523752600201560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_mpoly_factor/poly_pfrac.c000066400000000000000000000272171414523752600210010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "fmpz_mpoly_factor.h" #include "fmpz_mod_vec.h" #include "ulong_extras.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; const fmpz * p = fmpz_mod_ctx_modulus(ctx); 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, p); _fmpz_mod_poly_mullow(Rcoeffs, Bcoeffs, Blen - 1, Qcoeffs + n, Qlen, p, Blen - 1); _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) << (FLINT_BITS - 2)); 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_newton(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, fmpz_mod_ctx_modulus(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); 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_newton(I->B_inv + i, I->B_inv + i, I->B[i].length, I->ctxs + i); goto again; } flint2-2.8.4/fmpz_mpoly_factor/print_pretty.c000066400000000000000000000014321414523752600213750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_mpoly_factor/profile/000077500000000000000000000000001414523752600201265ustar00rootroot00000000000000flint2-2.8.4/fmpz_mpoly_factor/profile/p-factor.c000066400000000000000000000167721414523752600220220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.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; } flint2-2.8.4/fmpz_mpoly_factor/realloc.c000066400000000000000000000036501414523752600202570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly_factor/set.c000066400000000000000000000015071414523752600174300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_mpoly_factor/sort.c000066400000000000000000000034251414523752600176250ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_mpoly_factor/test/000077500000000000000000000000001414523752600174455ustar00rootroot00000000000000flint2-2.8.4/fmpz_mpoly_factor/test/t-factor.c000066400000000000000000000104561414523752600213360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" void check_omega(slong lower, slong upper, const fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx) { 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 (!fmpz_mpoly_factor(g, p, ctx)) { flint_printf("check factorization could be computed\n"); 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"); 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"); 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"); 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"); flint_abort(); } } fmpz_mpoly_clear(q, ctx); fmpz_mpoly_factor_clear(g, ctx); fmpz_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } int main(void) { slong i, j, tmul = 25; FLINT_TEST_INIT(state); flint_printf("factor...."); fflush(stdout); { 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_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 nfacs, len; ulong expbound, powbound, pow; fmpz_mpoly_ctx_init_rand(ctx, state, 8); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(t, ctx); nfacs = 1 + (5 + n_randint(state, 5))/ctx->minfo->nvars; expbound = 3 + 40/nfacs/ctx->minfo->nvars; 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_clear(t, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly_factor/test/t-factor_content.c000066400000000000000000000072351414523752600230710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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"); 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"); 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"); 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"); flint_abort(); } } else { if (!fmpz_mpoly_content_vars(q, g->poly + i, &v, 1, ctx)) { flint_printf("FAIL:\ncheck content could be computed\n"); 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"); flint_abort(); } } } } fmpz_mpoly_clear(q, ctx); fmpz_mpoly_factor_clear(g, ctx); fmpz_clear(deg); } int main(void) { slong i, j, k, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_content...."); fflush(stdout); for (i = 0; i < tmul * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; fmpz_mpoly_t a, t; slong 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); nfacs = 5 + (8 + n_randint(state, 8))/ctx->minfo->nvars; 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly_factor/test/t-factor_squarefree.c000066400000000000000000000067361414523752600235660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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"); 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"); 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"); 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"); 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); } int main(void) { slong i, j, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_squarefree...."); fflush(stdout); 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 nfacs, len; ulong expbound, powbound, pow; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(t, ctx); nfacs = 1 + (7 + n_randint(state, 7))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 5); expbound = 2 + 50/nfacs/ctx->minfo->nvars/powbound; lower = 0; fmpz_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 60/powbound/ctx->minfo->nvars); 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); 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_it(a, ctx); fmpz_mpoly_clear(t, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly_factor/test/t-factor_wang.c000066400000000000000000000076231414523752600223540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" void check_omega(slong lower, slong upper, const fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx) { 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 (!fmpz_mpoly_factor_wang(g, p, ctx)) { flint_printf("check factorization 1 could be computed\n"); flint_abort(); } if (!fmpz_mpoly_factor(h, p, ctx)) { flint_printf("check factorization 2 could be computed\n"); 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"); 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"); 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"); flint_abort(); } 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"); 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"); flint_abort(); } } fmpz_mpoly_clear(q, ctx); fmpz_mpoly_factor_clear(g, ctx); fmpz_mpoly_factor_clear(h, ctx); fmpz_clear(omega); return; } int main(void) { slong i, j, tmul = 20; FLINT_TEST_INIT(state); flint_printf("factor_wang...."); fflush(stdout); 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 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); nfacs = 1 + (4 + n_randint(state, 5))/ctx->minfo->nvars; expbound = 2 + 25/nfacs/ctx->minfo->nvars; 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_clear(t, ctx); fmpz_mpoly_clear(at, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly_factor/test/t-factor_zassenhaus.c000066400000000000000000000123761414523752600236050ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" void check_omega(slong lower, slong upper, const fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx) { 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 (!fmpz_mpoly_factor_zassenhaus(g, p, ctx)) { flint_printf("check factorization 1 could be computed\n"); flint_abort(); } if (!fmpz_mpoly_factor(h, p, ctx)) { flint_printf("check factorization 2 could be computed\n"); 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"); 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"); 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"); flint_abort(); } 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"); 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"); flint_abort(); } } fmpz_mpoly_clear(q, ctx); fmpz_mpoly_factor_clear(g, ctx); fmpz_mpoly_factor_clear(h, ctx); fmpz_clear(omega); return; } int main(void) { slong i, j, tmul = 20; FLINT_TEST_INIT(state); flint_printf("factor_zassenhaus...."); fflush(stdout); { 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_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_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_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 nfacs, len; ulong expbound, powbound, pow; fmpz_mpoly_ctx_init_rand(ctx, state, 5); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(t, ctx); nfacs = 1 + (4 + n_randint(state, 5))/ctx->minfo->nvars; expbound = 2 + 20/nfacs/ctx->minfo->nvars; 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_clear(t, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly_factor/test/t-factor_zippel.c000066400000000000000000000073301414523752600227160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" void check_omega(slong lower, slong upper, const fmpz_mpoly_t p, const fmpz_mpoly_ctx_t ctx) { 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 (!fmpz_mpoly_factor_zippel(g, p, ctx)) { flint_printf("check factorization 1 could be computed\n"); flint_abort(); } if (!fmpz_mpoly_factor(h, p, ctx)) { flint_printf("check factorization 2 could be computed\n"); 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"); 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"); 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"); flint_abort(); } 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"); 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"); flint_abort(); } } fmpz_mpoly_clear(q, ctx); fmpz_mpoly_factor_clear(g, ctx); fmpz_mpoly_factor_clear(h, ctx); fmpz_clear(omega); return; } int main(void) { slong i, j, tmul = 20; FLINT_TEST_INIT(state); flint_printf("factor_zippel...."); fflush(stdout); 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 nfacs, len; ulong expbound, powbound, pow; fmpz_mpoly_ctx_init_rand(ctx, state, 7); fmpz_mpoly_init(a, ctx); fmpz_mpoly_init(t, ctx); nfacs = 1 + (5 + n_randint(state, 5))/ctx->minfo->nvars; expbound = 3 + 40/nfacs/ctx->minfo->nvars; 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_clear(t, ctx); fmpz_mpoly_clear(a, ctx); fmpz_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly_factor/test/t-gcd_brown.c000066400000000000000000000162501414523752600220220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" 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; } 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 = compute_gcd(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); 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); 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); 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); 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); flint_abort(); } res = compute_gcd(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); 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); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 15; FLINT_TEST_INIT(state); flint_printf("gcd_brown...."); fflush(stdout); 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, 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"); } 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly_factor/test/t-gcd_brown_threaded.c000066400000000000000000000210761414523752600236640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } 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; } 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 = compute_gcd(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); 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); 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); 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); 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); flint_abort(); } res = compute_gcd(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); 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); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 12, max_threads = 5; FLINT_TEST_INIT(state); flint_printf("gcd_brown_threaded...."); fflush(stdout); 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, 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"); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly_factor/test/t-gcd_subresultant.c000066400000000000000000000155741414523752600234360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" 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; } 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 = compute_gcd(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); 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); 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); 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); 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); flint_abort(); } res = compute_gcd(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); 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); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("gcd_subresultant...."); fflush(stdout); 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, 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"); } 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly_factor/test/t-gcd_zippel.c000066400000000000000000000347021414523752600222000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" 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"); 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; } 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 = compute_gcd(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); 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); 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); 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); flint_abort(); } res = fmpz_mpoly_divides(ca, a, g, ctx) && 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); flint_abort(); } res = compute_gcd(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); 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); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 25; FLINT_TEST_INIT(state); flint_printf("gcd_zippel...."); fflush(stdout); /* 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"); 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"); /* 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"); 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); 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"); } 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly_factor/test/t-gcd_zippel2.c000066400000000000000000000314171414523752600222620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" 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; } 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 = compute_gcd(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); 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); 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); 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); 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); flint_abort(); } res = compute_gcd(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); 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); flint_abort(); } cleanup: fmpz_mpoly_clear(ca, ctx); fmpz_mpoly_clear(cb, ctx); fmpz_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 20; FLINT_TEST_INIT(state); flint_printf("gcd_zippel2...."); fflush(stdout); { 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_mpoly_factor/test/t-lcc_kaltofen.c000066400000000000000000000216061414523752600225030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } int main(void) { slong i, j, k, l; FLINT_TEST_INIT(state); flint_printf("lcc_kaltofen...."); fflush(stdout); 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly_factor/test/t-poly_pfrac.c000066400000000000000000000123651414523752600222170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_mpoly_factor.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"); 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"); 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"); flint_abort(); } } } else { if (!found_bad) { flint_printf("FAIL: precomp should not have failed\n"); 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); } int main(void) { slong i, j, k, tmul = 10; FLINT_TEST_INIT(state); flint_printf("fmpz_poly_pfrac...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_mpoly_factor/tpoly.c000066400000000000000000000023301414523752600177770ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly_factor.h" #include "nmod_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); } } flint2-2.8.4/fmpz_mpoly_factor/tuple.c000066400000000000000000000036771414523752600200000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_poly.h000066400000000000000000001562451414523752600151410ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPZ_POLY_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "nmod_poly.h" #include "fmpq.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 * coeffs; slong alloc; slong length; } fmpz_poly_struct; typedef fmpz_poly_struct fmpz_poly_t[1]; 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 { 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 { 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 ********************************************************/ FLINT_DLL void fmpz_poly_init(fmpz_poly_t poly); FLINT_DLL void fmpz_poly_init2(fmpz_poly_t poly, slong alloc); FLINT_DLL void fmpz_poly_realloc(fmpz_poly_t poly, slong alloc); FLINT_DLL void fmpz_poly_fit_length(fmpz_poly_t poly, slong len); FLINT_DLL void fmpz_poly_clear(fmpz_poly_t poly); FLINT_DLL void _fmpz_poly_normalise(fmpz_poly_t poly); FMPZ_POLY_INLINE 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; } 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 ***************************************/ FLINT_DLL void fmpz_poly_set(fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void fmpz_poly_set_ui(fmpz_poly_t poly, ulong c); FLINT_DLL void fmpz_poly_set_si(fmpz_poly_t poly, slong c); FLINT_DLL void fmpz_poly_set_fmpz(fmpz_poly_t poly, const fmpz_t c); FLINT_DLL void fmpz_poly_set_mpz(fmpz_poly_t poly, const mpz_t c); FLINT_DLL int _fmpz_poly_set_str(fmpz * poly, const char * str); FLINT_DLL int fmpz_poly_set_str(fmpz_poly_t poly, const char * str); FLINT_DLL char * _fmpz_poly_get_str(const fmpz * poly, slong len); FLINT_DLL char * fmpz_poly_get_str(const fmpz_poly_t poly); FLINT_DLL char * _fmpz_poly_get_str_pretty(const fmpz * poly, slong len, const char * x); FLINT_DLL 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)); } FLINT_DLL void fmpz_poly_zero_coeffs(fmpz_poly_t poly, slong i, slong j); FLINT_DLL void fmpz_poly_swap(fmpz_poly_t poly1, fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_reverse(fmpz * res, const fmpz * poly, slong len, slong n); FLINT_DLL void fmpz_poly_reverse(fmpz_poly_t res, const fmpz_poly_t poly, slong n); FLINT_DLL ulong fmpz_poly_deflation(const fmpz_poly_t input); FLINT_DLL void fmpz_poly_deflate(fmpz_poly_t result, const fmpz_poly_t input, ulong deflation); FLINT_DLL void fmpz_poly_inflate(fmpz_poly_t result, const fmpz_poly_t input, ulong inflation); FMPZ_POLY_INLINE 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_DLL void fmpz_poly_set_trunc(fmpz_poly_t res, const fmpz_poly_t poly, slong n); /* Randomisation ***********************************************************/ FLINT_DLL void fmpz_poly_randtest(fmpz_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits); FLINT_DLL void fmpz_poly_randtest_unsigned(fmpz_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits); FLINT_DLL void fmpz_poly_randtest_not_zero(fmpz_poly_t f, flint_rand_t state, slong len, flint_bitcnt_t bits); FLINT_DLL void fmpz_poly_randtest_no_real_root(fmpz_poly_t p, flint_rand_t state, slong len, flint_bitcnt_t bits); /* Getting and setting coefficients ****************************************/ FLINT_DLL slong fmpz_poly_get_coeff_si(const fmpz_poly_t poly, slong n); FLINT_DLL void fmpz_poly_set_coeff_si(fmpz_poly_t poly, slong n, slong x); FLINT_DLL ulong fmpz_poly_get_coeff_ui(const fmpz_poly_t poly, slong n); FLINT_DLL void fmpz_poly_set_coeff_ui(fmpz_poly_t poly, slong n, ulong x); FLINT_DLL void fmpz_poly_set_coeff_fmpz(fmpz_poly_t poly, slong n, const fmpz_t x); FLINT_DLL 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 **************************************************************/ FLINT_DLL int fmpz_poly_equal(const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL 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) FMPZ_POLY_INLINE 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)); } 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)); } /* Deprecated */ #define fmpz_poly_is_x fmpz_poly_is_gen FMPZ_POLY_INLINE 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)); } /* Addition and subtraction ************************************************/ FLINT_DLL void _fmpz_poly_add(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_add(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void fmpz_poly_add_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); FLINT_DLL void _fmpz_poly_sub(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_sub(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void fmpz_poly_sub_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); FLINT_DLL void fmpz_poly_neg(fmpz_poly_t res, const fmpz_poly_t poly); FLINT_DLL void fmpz_poly_add_si(fmpz_poly_t res, const fmpz_poly_t poly, slong c); FLINT_DLL void fmpz_poly_sub_si(fmpz_poly_t res, const fmpz_poly_t poly, slong c); FLINT_DLL void fmpz_poly_si_sub(fmpz_poly_t res, slong c, const fmpz_poly_t poly); FLINT_DLL void fmpz_poly_add_fmpz(fmpz_poly_t res, const fmpz_poly_t poly, fmpz_t c); FLINT_DLL void fmpz_poly_sub_fmpz(fmpz_poly_t res, const fmpz_poly_t poly, fmpz_t c); FLINT_DLL void fmpz_poly_fmpz_sub(fmpz_poly_t res, fmpz_t c, const fmpz_poly_t poly); /* Scalar absolute value multiplication and division ***********************/ FLINT_DLL void fmpz_poly_scalar_abs(fmpz_poly_t res, const fmpz_poly_t poly); FLINT_DLL void fmpz_poly_scalar_mul_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x); FLINT_DLL void fmpz_poly_scalar_mul_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x); FLINT_DLL void fmpz_poly_scalar_mul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); FLINT_DLL void fmpz_poly_scalar_addmul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); FLINT_DLL void fmpz_poly_scalar_submul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); FLINT_DLL void fmpz_poly_scalar_fdiv_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x); FLINT_DLL void fmpz_poly_scalar_fdiv_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x); FLINT_DLL void fmpz_poly_scalar_fdiv_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); FLINT_DLL void fmpz_poly_scalar_tdiv_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x); FLINT_DLL void fmpz_poly_scalar_tdiv_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x); FLINT_DLL void fmpz_poly_scalar_tdiv_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); FLINT_DLL void fmpz_poly_scalar_divexact_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x); FLINT_DLL void fmpz_poly_scalar_divexact_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x); FLINT_DLL void fmpz_poly_scalar_divexact_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x); FLINT_DLL void fmpz_poly_scalar_fdiv_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong exp); FLINT_DLL void fmpz_poly_scalar_tdiv_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong exp); FLINT_DLL void fmpz_poly_scalar_mul_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong exp); FMPZ_POLY_INLINE 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); } } FMPZ_POLY_INLINE 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); } } FLINT_DLL slong _fmpz_poly_remove_content_2exp(fmpz * pol, slong len); FLINT_DLL void _fmpz_poly_scale_2exp(fmpz * pol, slong len, slong k); /* Bit packing *************************************************************/ FLINT_DLL void _fmpz_poly_bit_pack(mp_ptr arr, const fmpz * poly, slong len, flint_bitcnt_t bit_size, int negate); FLINT_DLL int _fmpz_poly_bit_unpack(fmpz * poly, slong len, mp_srcptr arr, flint_bitcnt_t bit_size, int negate); FLINT_DLL void _fmpz_poly_bit_unpack_unsigned(fmpz * poly, slong len, mp_srcptr arr, flint_bitcnt_t bit_size); FLINT_DLL void fmpz_poly_bit_pack(fmpz_t f, const fmpz_poly_t poly, flint_bitcnt_t bit_size); FLINT_DLL void fmpz_poly_bit_unpack(fmpz_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size); FLINT_DLL void fmpz_poly_bit_unpack_unsigned(fmpz_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size); /* Multiplication **********************************************************/ FLINT_DLL void _fmpz_poly_mul_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_mul_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_mullow_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); FLINT_DLL void fmpz_poly_mullow_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); FLINT_DLL void _fmpz_poly_mulhigh_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong start); FLINT_DLL void fmpz_poly_mulhigh_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong start); FLINT_DLL void _fmpz_poly_mulmid_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_mulmid_classical(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void fmpz_poly_mul_karatsuba(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_mul_karatsuba(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void _fmpz_poly_mullow_karatsuba_n(fmpz * res, const fmpz * poly1, const fmpz * poly2, slong n); FLINT_DLL void fmpz_poly_mullow_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); FLINT_DLL void _fmpz_poly_mulhigh_karatsuba_n(fmpz * res, const fmpz * poly1, const fmpz * poly2, slong len); FLINT_DLL void fmpz_poly_mulhigh_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong length); FLINT_DLL void _fmpz_poly_mul_KS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_mul_KS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_mullow_KS(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); FLINT_DLL void fmpz_poly_mullow_KS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); FLINT_DLL void _fmpz_poly_mul_SS(fmpz * output, const fmpz * input1, slong length1, const fmpz * input2, slong length2); FLINT_DLL void fmpz_poly_mul_SS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_mullow_SS(fmpz * output, const fmpz * input1, slong length1, const fmpz * input2, slong length2, slong n); FLINT_DLL void fmpz_poly_mullow_SS(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); FLINT_DLL void _fmpz_poly_mul(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_mul(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_mullow(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); FLINT_DLL void fmpz_poly_mullow(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); FLINT_DLL void fmpz_poly_mulhigh_n(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); /* FFT precached multiplication **********************************************/ FLINT_DLL void fmpz_poly_mul_SS_precache_init(fmpz_poly_mul_precache_t pre, slong len1, slong bits1, const fmpz_poly_t poly2); FLINT_DLL void fmpz_poly_mul_precache_clear(fmpz_poly_mul_precache_t pre); FLINT_DLL void _fmpz_poly_mullow_SS_precache(fmpz * output, const fmpz * input1, slong len1, fmpz_poly_mul_precache_t pre, slong trunc); FLINT_DLL 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 ******************************************************************/ FLINT_DLL void _fmpz_poly_sqr_KS(fmpz * rop, const fmpz * op, slong len); FLINT_DLL void fmpz_poly_sqr_KS(fmpz_poly_t rop, const fmpz_poly_t op); FLINT_DLL void fmpz_poly_sqr_karatsuba(fmpz_poly_t rop, const fmpz_poly_t op); FLINT_DLL void _fmpz_poly_sqr_karatsuba(fmpz * rop, const fmpz * op, slong len); FLINT_DLL void _fmpz_poly_sqr_classical(fmpz * rop, const fmpz * op, slong len); FLINT_DLL void fmpz_poly_sqr_classical(fmpz_poly_t rop, const fmpz_poly_t op); FLINT_DLL void _fmpz_poly_sqr(fmpz * rop, const fmpz * op, slong len); FLINT_DLL void fmpz_poly_sqr(fmpz_poly_t rop, const fmpz_poly_t op); FLINT_DLL void _fmpz_poly_sqrlow_KS(fmpz * res, const fmpz * poly, slong len, slong n); FLINT_DLL void fmpz_poly_sqrlow_KS(fmpz_poly_t res, const fmpz_poly_t poly, slong n); FLINT_DLL void _fmpz_poly_sqrlow_karatsuba_n(fmpz * res, const fmpz * poly, slong n); FLINT_DLL void fmpz_poly_sqrlow_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly, slong n); FLINT_DLL void _fmpz_poly_sqrlow_classical(fmpz * res, const fmpz * poly, slong len, slong n); FLINT_DLL void fmpz_poly_sqrlow_classical(fmpz_poly_t res, const fmpz_poly_t poly, slong n); FLINT_DLL void _fmpz_poly_sqrlow(fmpz * res, const fmpz * poly, slong len, slong n); FLINT_DLL void fmpz_poly_sqrlow(fmpz_poly_t res, const fmpz_poly_t poly, slong n); /* Powering ****************************************************************/ FLINT_DLL void _fmpz_poly_pow_multinomial(fmpz * res, const fmpz * poly, slong len, ulong e); FLINT_DLL void fmpz_poly_pow_multinomial(fmpz_poly_t res, const fmpz_poly_t poly, ulong e); FLINT_DLL void _fmpz_poly_pow_binomial(fmpz * res, const fmpz * poly, ulong e); FLINT_DLL void fmpz_poly_pow_binomial(fmpz_poly_t res, const fmpz_poly_t poly, ulong e); FLINT_DLL void _fmpz_poly_pow_binexp(fmpz * res, const fmpz * poly, slong len, ulong e); FLINT_DLL void fmpz_poly_pow_binexp(fmpz_poly_t res, const fmpz_poly_t poly, ulong e); FLINT_DLL void _fmpz_poly_pow_addchains(fmpz * res, const fmpz * poly, slong len, const int * a, int n); FLINT_DLL void fmpz_poly_pow_addchains(fmpz_poly_t res, const fmpz_poly_t poly, ulong e); FLINT_DLL void _fmpz_poly_pow_small(fmpz * res, const fmpz * poly, slong len, ulong e); FLINT_DLL void _fmpz_poly_pow(fmpz * res, const fmpz * poly, slong len, ulong e); FLINT_DLL void fmpz_poly_pow(fmpz_poly_t res, const fmpz_poly_t poly, ulong e); FLINT_DLL void _fmpz_poly_pow_trunc(fmpz * res, const fmpz * poly, ulong e, slong n); void FLINT_DLL fmpz_poly_pow_trunc(fmpz_poly_t res, const fmpz_poly_t poly, ulong e, slong n); /* Shifting ****************************************************************/ FLINT_DLL void _fmpz_poly_shift_left(fmpz * res, const fmpz * poly, slong len, slong n); FLINT_DLL void _fmpz_poly_shift_right(fmpz * res, const fmpz * poly, slong len, slong n); FLINT_DLL void fmpz_poly_shift_left(fmpz_poly_t res, const fmpz_poly_t poly, slong n); FLINT_DLL void fmpz_poly_shift_right(fmpz_poly_t res, const fmpz_poly_t poly, slong n); /* Norms *******************************************************************/ FLINT_DLL void _fmpz_poly_2norm(fmpz_t res, const fmpz * poly, slong len); FLINT_DLL void fmpz_poly_2norm(fmpz_t res, const fmpz_poly_t poly); FLINT_DLL flint_bitcnt_t _fmpz_poly_2norm_normalised_bits(const fmpz * poly, slong len); FMPZ_POLY_INLINE ulong fmpz_poly_max_limbs(const fmpz_poly_t poly) { return _fmpz_vec_max_limbs(poly->coeffs, poly->length); } FMPZ_POLY_INLINE slong fmpz_poly_max_bits(const fmpz_poly_t poly) { return _fmpz_vec_max_bits(poly->coeffs, poly->length); } FMPZ_POLY_INLINE void fmpz_poly_height(fmpz_t res, const fmpz_poly_t poly) { _fmpz_vec_height(res, poly->coeffs, poly->length); } /* Greatest common divisor *************************************************/ FLINT_DLL void _fmpz_poly_gcd_subresultant(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_gcd_subresultant(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL int _fmpz_poly_gcd_heuristic(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL int fmpz_poly_gcd_heuristic(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_gcd_modular(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_gcd_modular(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_gcd(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_gcd(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_lcm(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_lcm(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_resultant_euclidean(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_resultant_euclidean(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_resultant_modular(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_resultant_modular(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_resultant(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_resultant(fmpz_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL 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_DLL 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); FLINT_DLL void _fmpz_poly_xgcd_modular(fmpz_t r, fmpz * s, fmpz * t, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL 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 ********************************************************/ FLINT_DLL void _fmpz_poly_discriminant(fmpz_t res, const fmpz * poly, slong len); FLINT_DLL void fmpz_poly_discriminant(fmpz_t res, const fmpz_poly_t poly); /* Gaussian content ********************************************************/ FLINT_DLL void _fmpz_poly_content(fmpz_t res, const fmpz * poly, slong len); FLINT_DLL void fmpz_poly_content(fmpz_t res, const fmpz_poly_t poly); FLINT_DLL void _fmpz_poly_primitive_part(fmpz * res, const fmpz * poly, slong len); FLINT_DLL void fmpz_poly_primitive_part(fmpz_poly_t res, const fmpz_poly_t poly); /* Square-free *************************************************************/ FLINT_DLL int _fmpz_poly_is_squarefree(const fmpz * poly, slong len); FLINT_DLL int fmpz_poly_is_squarefree(const fmpz_poly_t poly); /* Euclidean division ******************************************************/ FLINT_DLL int _fmpz_poly_divrem_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact); FLINT_DLL void fmpz_poly_divrem_basecase(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); FLINT_DLL int _fmpz_poly_divrem_divconquer_recursive(fmpz * Q, fmpz * BQ, fmpz * W, const fmpz * A, const fmpz * B, slong lenB, int exact); FLINT_DLL int _fmpz_poly_divrem_divconquer(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact); FLINT_DLL void fmpz_poly_divrem_divconquer(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); FLINT_DLL int _fmpz_poly_divrem(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact); FLINT_DLL void fmpz_poly_divrem(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); FLINT_DLL int _fmpz_poly_div_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact); FLINT_DLL void fmpz_poly_div_basecase(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B); FLINT_DLL int _fmpz_poly_divremlow_divconquer_recursive(fmpz * Q, fmpz * QB, const fmpz * A, const fmpz * B, slong lenB, int exact); FLINT_DLL int _fmpz_poly_div_divconquer_recursive(fmpz * Q, fmpz * temp, const fmpz * A, const fmpz * B, slong lenB, int exact); FLINT_DLL int _fmpz_poly_div_divconquer(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact); FLINT_DLL void fmpz_poly_div_divconquer(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B); FLINT_DLL int _fmpz_poly_div(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, int exact); FLINT_DLL void fmpz_poly_div(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B); FLINT_DLL void _fmpz_poly_preinvert(fmpz * B_inv, const fmpz * B, slong n); FLINT_DLL void fmpz_poly_preinvert(fmpz_poly_t B_inv, const fmpz_poly_t B); FLINT_DLL void _fmpz_poly_div_preinv(fmpz * Q, const fmpz * A, slong len1, const fmpz * B, const fmpz * B_inv, slong len2); FLINT_DLL 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); FLINT_DLL void _fmpz_poly_divrem_preinv(fmpz * Q, fmpz * A, slong len1, const fmpz * B, const fmpz * B_inv, slong len2); FLINT_DLL 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); FLINT_DLL fmpz ** _fmpz_poly_powers_precompute(const fmpz * B, slong len); FLINT_DLL void fmpz_poly_powers_precompute(fmpz_poly_powers_precomp_t pinv, fmpz_poly_t poly); FLINT_DLL void _fmpz_poly_powers_clear(fmpz ** powers, slong len); FLINT_DLL void fmpz_poly_powers_clear(fmpz_poly_powers_precomp_t pinv); FLINT_DLL void _fmpz_poly_rem_powers_precomp(fmpz * A, slong m, const fmpz * B, slong n, fmpz ** const powers); FLINT_DLL 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); FLINT_DLL void _fmpz_poly_rem_basecase(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB); FLINT_DLL void fmpz_poly_rem_basecase(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); FLINT_DLL void _fmpz_poly_rem(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB); FLINT_DLL void fmpz_poly_rem(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); FLINT_DLL void fmpz_poly_div_root(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_t c); FLINT_DLL void _fmpz_poly_div_root(fmpz * Q, const fmpz * A, slong len, const fmpz_t c); /* Power series division ***************************************************/ FLINT_DLL void _fmpz_poly_inv_series_basecase(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n); FLINT_DLL void fmpz_poly_inv_series_basecase(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n); FLINT_DLL void _fmpz_poly_inv_series_newton(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n); FLINT_DLL void fmpz_poly_inv_series_newton(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n); FLINT_DLL void _fmpz_poly_inv_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n); FLINT_DLL void fmpz_poly_inv_series(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n); FLINT_DLL void _fmpz_poly_div_series_basecase(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n); FLINT_DLL void _fmpz_poly_div_series_divconquer(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n); FLINT_DLL void _fmpz_poly_div_series(fmpz * Q, const fmpz * A, slong Alen, const fmpz * B, slong Blen, slong n); FLINT_DLL void fmpz_poly_div_series_basecase(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, slong n); FLINT_DLL void fmpz_poly_div_series_divconquer(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, slong n); FLINT_DLL void fmpz_poly_div_series(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B, slong n); /* Divisibility testing ***************************************************/ FLINT_DLL int _fmpz_poly_divides(fmpz * q, const fmpz * a, slong len1, const fmpz * b, slong len2); FLINT_DLL int fmpz_poly_divides(fmpz_poly_t q, const fmpz_poly_t a, const fmpz_poly_t b); FLINT_DLL slong fmpz_poly_remove(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); /* Pseudo division *********************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _fmpz_poly_pseudo_divrem_cohen(fmpz * Q, fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB); FLINT_DLL void fmpz_poly_pseudo_divrem_cohen(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B); FLINT_DLL void _fmpz_poly_pseudo_rem_cohen(fmpz * R, const fmpz * A, slong lenA, const fmpz * B, slong lenB); FLINT_DLL 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 * 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); } 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); } FLINT_DLL void _fmpz_poly_pseudo_div(fmpz * Q, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv); FLINT_DLL void fmpz_poly_pseudo_div(fmpz_poly_t Q, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B); FLINT_DLL void _fmpz_poly_pseudo_rem(fmpz * R, ulong * d, const fmpz * A, slong lenA, const fmpz * B, slong lenB, const fmpz_preinvn_t inv); FLINT_DLL void fmpz_poly_pseudo_rem(fmpz_poly_t R, ulong * d, const fmpz_poly_t A, const fmpz_poly_t B); FLINT_DLL void fmpz_poly_divlow_smodp(fmpz * res, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_t p, slong n); FLINT_DLL void fmpz_poly_divhigh_smodp(fmpz * res, const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_t p, slong n); /* Derivative **************************************************************/ FLINT_DLL void _fmpz_poly_derivative(fmpz * rpoly, const fmpz * poly, slong len); FLINT_DLL void fmpz_poly_derivative(fmpz_poly_t res, const fmpz_poly_t poly); /* Evaluation **************************************************************/ void FLINT_DLL _fmpz_poly_evaluate_divconquer_fmpz(fmpz_t res, const fmpz * poly, slong len, const fmpz_t a); FLINT_DLL void fmpz_poly_evaluate_divconquer_fmpz(fmpz_t res, const fmpz_poly_t poly, const fmpz_t a); FLINT_DLL void _fmpz_poly_evaluate_horner_fmpz(fmpz_t res, const fmpz * f, slong len, const fmpz_t a); FLINT_DLL void fmpz_poly_evaluate_horner_fmpz(fmpz_t res, const fmpz_poly_t f, const fmpz_t a); FLINT_DLL void _fmpz_poly_evaluate_fmpz(fmpz_t res, const fmpz * f, slong len, const fmpz_t a); FLINT_DLL void fmpz_poly_evaluate_fmpz(fmpz_t res, const fmpz_poly_t f, const fmpz_t a); FLINT_DLL 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); FLINT_DLL void fmpz_poly_evaluate_horner_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a); FLINT_DLL 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); FLINT_DLL void fmpz_poly_evaluate_divconquer_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a); FLINT_DLL void _fmpz_poly_evaluate_fmpq(fmpz_t rnum, fmpz_t rden, const fmpz * f, slong len, const fmpz_t anum, const fmpz_t aden); FLINT_DLL void fmpz_poly_evaluate_fmpq(fmpq_t res, const fmpz_poly_t f, const fmpq_t a); FLINT_DLL void fmpz_poly_evaluate_mpq(mpq_t res, const fmpz_poly_t f, const mpq_t a); FLINT_DLL mp_limb_t _fmpz_poly_evaluate_mod(const fmpz * poly, slong len, mp_limb_t a, mp_limb_t n, mp_limb_t ninv); FLINT_DLL mp_limb_t fmpz_poly_evaluate_mod(const fmpz_poly_t poly, mp_limb_t a, mp_limb_t n); FLINT_DLL double _fmpz_poly_evaluate_horner_d(const fmpz * poly, slong n, double d); FLINT_DLL double fmpz_poly_evaluate_horner_d(const fmpz_poly_t poly, double d); FLINT_DLL double _fmpz_poly_evaluate_horner_d_2exp(slong * exp, const fmpz * poly, slong n, double d); FLINT_DLL double fmpz_poly_evaluate_horner_d_2exp(slong * exp, const fmpz_poly_t poly, double d); FLINT_DLL double _fmpz_poly_evaluate_horner_d_2exp2(slong * exp, const fmpz * poly, slong n, double d, slong dexp); FLINT_DLL double fmpz_poly_evaluate_horner_d_2exp2(slong * exp, const fmpz_poly_t poly, double d, slong dexp); /* Composition *************************************************************/ FLINT_DLL void _fmpz_poly_compose_horner(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_compose_horner(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_compose_divconquer(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_compose_divconquer(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); FLINT_DLL void _fmpz_poly_compose(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2); FLINT_DLL void fmpz_poly_compose(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2); /* Taylor shift ************************************************************/ FLINT_DLL void _fmpz_poly_taylor_shift_horner(fmpz * poly, const fmpz_t c, slong n); FLINT_DLL void fmpz_poly_taylor_shift_horner(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c); FLINT_DLL void _fmpz_poly_taylor_shift_divconquer(fmpz * poly, const fmpz_t c, slong n); FLINT_DLL void fmpz_poly_taylor_shift_divconquer(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c); FLINT_DLL 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); } FLINT_DLL void _fmpz_poly_taylor_shift(fmpz * poly, const fmpz_t c, slong n); FLINT_DLL void fmpz_poly_taylor_shift(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c); /* Power series composition and compositional inverse **********************/ FLINT_DLL void _fmpz_poly_compose_series_brent_kung(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); FLINT_DLL void fmpz_poly_compose_series_brent_kung(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); FLINT_DLL void _fmpz_poly_compose_series_horner(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); FLINT_DLL void fmpz_poly_compose_series_horner(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); FLINT_DLL void _fmpz_poly_compose_series(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, slong n); FLINT_DLL void fmpz_poly_compose_series(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n); FLINT_DLL void _fmpz_poly_revert_series_lagrange(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n); FLINT_DLL void fmpz_poly_revert_series_lagrange(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n); FLINT_DLL void _fmpz_poly_revert_series_lagrange_fast(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n); FLINT_DLL void fmpz_poly_revert_series_lagrange_fast(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n); FLINT_DLL void _fmpz_poly_revert_series_newton(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n); FLINT_DLL void fmpz_poly_revert_series_newton(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n); FLINT_DLL void _fmpz_poly_revert_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n); FLINT_DLL void fmpz_poly_revert_series(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n); /* Square root *************************************************************/ FLINT_DLL int _fmpz_poly_sqrtrem_classical(fmpz * res, fmpz * r, const fmpz * poly, slong len); FLINT_DLL int fmpz_poly_sqrtrem_classical(fmpz_poly_t b, fmpz_poly_t r, const fmpz_poly_t a); FLINT_DLL int _fmpz_poly_sqrtrem_divconquer(fmpz * res, fmpz * r, const fmpz * poly, slong len, fmpz * temp); FLINT_DLL int fmpz_poly_sqrtrem_divconquer(fmpz_poly_t b, fmpz_poly_t r, const fmpz_poly_t a); FLINT_DLL int _fmpz_poly_sqrt_classical(fmpz * res, const fmpz * poly, slong len, int exact); FLINT_DLL int fmpz_poly_sqrt_classical(fmpz_poly_t b, const fmpz_poly_t a); FLINT_DLL int _fmpz_poly_sqrt_divconquer(fmpz * res, const fmpz * poly, slong len, int exact); FLINT_DLL int fmpz_poly_sqrt_divconquer(fmpz_poly_t b, const fmpz_poly_t a); FLINT_DLL int _fmpz_poly_sqrt_KS(fmpz *rop, const fmpz *op, slong len); FLINT_DLL int fmpz_poly_sqrt_KS(fmpz_poly_t b, const fmpz_poly_t a); FLINT_DLL int _fmpz_poly_sqrt(fmpz * res, const fmpz * poly, slong len); FLINT_DLL int fmpz_poly_sqrt(fmpz_poly_t b, const fmpz_poly_t a); FLINT_DLL int _fmpz_poly_sqrt_series(fmpz * res, const fmpz * poly, slong len, slong n); FLINT_DLL int fmpz_poly_sqrt_series(fmpz_poly_t b, const fmpz_poly_t a, slong n); /* Power sums ****************************************************************/ FLINT_DLL void _fmpz_poly_power_sums_naive(fmpz * res, const fmpz * poly, slong len, slong n); FLINT_DLL void fmpz_poly_power_sums_naive(fmpz_poly_t res, const fmpz_poly_t poly, slong n); FLINT_DLL void fmpz_poly_power_sums(fmpz_poly_t res, const fmpz_poly_t poly, slong n); FLINT_DLL void _fmpz_poly_power_sums_to_poly(fmpz * res, const fmpz * poly, slong len); FLINT_DLL void fmpz_poly_power_sums_to_poly(fmpz_poly_t res, const fmpz_poly_t Q); /* Signature ***************************************************************/ FLINT_DLL void _fmpz_poly_signature(slong * r1, slong * r2, const fmpz * poly, slong len); FLINT_DLL void fmpz_poly_signature(slong * r1, slong * r2, const fmpz_poly_t poly); /* Input and output ********************************************************/ FLINT_DLL int _fmpz_poly_fprint(FILE * file, const fmpz * poly, slong len); FLINT_DLL int fmpz_poly_fprint(FILE * file, const fmpz_poly_t poly); FLINT_DLL int _fmpz_poly_fprint_pretty(FILE * file, const fmpz * poly, slong len, const char * x); FLINT_DLL int fmpz_poly_fprint_pretty(FILE * file, const fmpz_poly_t poly, const char * x); FMPZ_POLY_INLINE int _fmpz_poly_print_pretty(const fmpz * poly, slong len, const char * x) { return _fmpz_poly_fprint_pretty(stdout, poly, len, x); } FMPZ_POLY_INLINE int _fmpz_poly_print(const fmpz * poly, slong n) { return _fmpz_poly_fprint(stdout, poly, n); } FMPZ_POLY_INLINE int fmpz_poly_print(const fmpz_poly_t poly) { return fmpz_poly_fprint(stdout, poly); } FMPZ_POLY_INLINE int fmpz_poly_print_pretty(const fmpz_poly_t poly, const char * x) { return fmpz_poly_fprint_pretty(stdout, poly, x); } FLINT_DLL int fmpz_poly_fread(FILE * file, fmpz_poly_t poly); FLINT_DLL int fmpz_poly_fread_pretty(FILE *file, fmpz_poly_t poly, char **x); FMPZ_POLY_INLINE int fmpz_poly_read(fmpz_poly_t poly) { return fmpz_poly_fread(stdin, poly); } FMPZ_POLY_INLINE int fmpz_poly_read_pretty(fmpz_poly_t poly, char **x) { return fmpz_poly_fread_pretty(stdin, poly, x); } FMPZ_POLY_INLINE 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); } /* CRT ********************************************************************/ FLINT_DLL void fmpz_poly_get_nmod_poly(nmod_poly_t res, const fmpz_poly_t poly); FLINT_DLL void fmpz_poly_set_nmod_poly(fmpz_poly_t res, const nmod_poly_t poly); FLINT_DLL void fmpz_poly_set_nmod_poly_unsigned(fmpz_poly_t res, const nmod_poly_t poly); void FLINT_DLL _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); FLINT_DLL 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); FLINT_DLL 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 *****************************************************************/ FLINT_DLL void _fmpz_poly_product_roots_fmpz_vec(fmpz * poly, const fmpz * xs, slong n); FLINT_DLL void fmpz_poly_product_roots_fmpz_vec(fmpz_poly_t poly, const fmpz * xs, slong n); FLINT_DLL void _fmpz_poly_product_roots_fmpq_vec(fmpz * poly, const fmpq * xs, slong n); FLINT_DLL void fmpz_poly_product_roots_fmpq_vec(fmpz_poly_t poly, const fmpq * xs, slong n); /* Newton basis *************************************************************/ FLINT_DLL void _fmpz_poly_monomial_to_newton(fmpz * poly, const fmpz * roots, slong n); FLINT_DLL void _fmpz_poly_newton_to_monomial(fmpz * poly, const fmpz * roots, slong n); /* Multipoint evaluation and interpolation *********************************/ FLINT_DLL void fmpz_poly_evaluate_fmpz_vec(fmpz * res, const fmpz_poly_t f, const fmpz * a, slong n); FLINT_DLL void fmpz_poly_interpolate_fmpz_vec(fmpz_poly_t poly, const fmpz * xs, const fmpz * ys, slong n); /* Hensel lifting ************************************************************/ FLINT_DLL void fmpz_poly_hensel_build_tree(slong * link, fmpz_poly_t *v, fmpz_poly_t *w, const nmod_poly_factor_t fac); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /* Some functions for backwards compatibility */ FMPZ_POLY_INLINE void fmpz_poly_scalar_mul_mpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const mpz_t x) { fmpz_t t; fmpz_init_set_readonly(t, x); fmpz_poly_scalar_mul_fmpz(poly1, poly2, t); fmpz_clear_readonly(t); } FMPZ_POLY_INLINE void fmpz_poly_scalar_divexact_mpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const mpz_t x) { fmpz_t t; fmpz_init_set_readonly(t, x); fmpz_poly_scalar_divexact_fmpz(poly1, poly2, t); fmpz_clear_readonly(t); } FMPZ_POLY_INLINE void fmpz_poly_scalar_fdiv_mpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const mpz_t x) { fmpz_t t; fmpz_init_set_readonly(t, x); fmpz_poly_scalar_fdiv_fmpz(poly1, poly2, t); fmpz_clear_readonly(t); } FMPZ_POLY_INLINE void fmpz_poly_set_coeff_mpz(fmpz_poly_t poly, slong n, const mpz_t x) { fmpz_t t; fmpz_init_set_readonly(t, x); fmpz_poly_set_coeff_fmpz(poly, n, t); fmpz_clear_readonly(t); } FMPZ_POLY_INLINE void fmpz_poly_get_coeff_mpz(mpz_t x, const fmpz_poly_t poly, slong n) { fmpz_t t; fmpz_init(t); fmpz_poly_get_coeff_fmpz(t, poly, n); fmpz_get_mpz(x, t); fmpz_clear(t); } /* Roots */ FLINT_DLL void _fmpz_poly_bound_roots(fmpz_t bound, const fmpz * poly, slong len); FLINT_DLL void fmpz_poly_bound_roots(fmpz_t bound, const fmpz_poly_t poly); FLINT_DLL void _fmpz_poly_num_real_roots_sturm(slong * n_neg, slong * n_pos, const fmpz * pol, slong len); FLINT_DLL slong fmpz_poly_num_real_roots_sturm(const fmpz_poly_t poly); FLINT_DLL slong _fmpz_poly_num_real_roots(const fmpz * pol, slong len); FLINT_DLL slong fmpz_poly_num_real_roots(const fmpz_poly_t poly); /* CLD bounds */ FLINT_DLL void fmpz_poly_CLD_bound(fmpz_t res, const fmpz_poly_t f, slong n); /* Special polynomials */ FLINT_DLL void _fmpz_poly_cyclotomic(fmpz * a, ulong n, mp_ptr factors, slong num_factors, ulong phi); FLINT_DLL void fmpz_poly_cyclotomic(fmpz_poly_t poly, ulong n); FLINT_DLL ulong _fmpz_poly_is_cyclotomic(const fmpz * poly, slong len); FLINT_DLL ulong fmpz_poly_is_cyclotomic(const fmpz_poly_t poly); FLINT_DLL void _fmpz_poly_cos_minpoly(fmpz * f, ulong n); FLINT_DLL void fmpz_poly_cos_minpoly(fmpz_poly_t f, ulong n); FLINT_DLL void _fmpz_poly_swinnerton_dyer(fmpz * T, ulong n); FLINT_DLL void fmpz_poly_swinnerton_dyer(fmpz_poly_t poly, ulong n); FLINT_DLL void _fmpz_poly_chebyshev_t(fmpz * coeffs, ulong n); FLINT_DLL void fmpz_poly_chebyshev_t(fmpz_poly_t poly, ulong n); FLINT_DLL void _fmpz_poly_chebyshev_u(fmpz * coeffs, ulong n); FLINT_DLL void fmpz_poly_chebyshev_u(fmpz_poly_t poly, ulong n); FLINT_DLL void _fmpz_poly_legendre_pt(fmpz * coeffs, ulong n); FLINT_DLL void fmpz_poly_legendre_pt(fmpz_poly_t poly, ulong n); FLINT_DLL void _fmpz_poly_hermite_h(fmpz * coeffs, ulong n); FLINT_DLL void fmpz_poly_hermite_h(fmpz_poly_t poly, ulong n); FLINT_DLL void _fmpz_poly_hermite_he(fmpz * coeffs, ulong n); FLINT_DLL void fmpz_poly_hermite_he(fmpz_poly_t poly, ulong n); FLINT_DLL void _fmpz_poly_fibonacci(fmpz * coeffs, ulong n); FLINT_DLL void fmpz_poly_fibonacci(fmpz_poly_t poly, ulong n); FLINT_DLL void _fmpz_poly_eta_qexp(fmpz * f, slong e, slong n); FLINT_DLL void fmpz_poly_eta_qexp(fmpz_poly_t f, slong e, slong n); FLINT_DLL void _fmpz_poly_theta_qexp(fmpz * f, slong e, slong n); FLINT_DLL void fmpz_poly_theta_qexp(fmpz_poly_t f, slong e, slong n); #ifdef __cplusplus } #endif #include "fmpz_poly_factor.h" #endif flint2-2.8.4/fmpz_poly/000077500000000000000000000000001414523752600147535ustar00rootroot00000000000000flint2-2.8.4/fmpz_poly/2norm.c000066400000000000000000000014171414523752600161570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_2norm(fmpz_t res, const fmpz * poly, slong len) { slong i; fmpz_zero(res); for (i = 0; i < len; i++) fmpz_addmul(res, poly + i, poly + i); fmpz_sqrt(res, res); } void fmpz_poly_2norm(fmpz_t res, const fmpz_poly_t poly) { _fmpz_poly_2norm(res, poly->coeffs, poly->length); } flint2-2.8.4/fmpz_poly/2norm_normalised_bits.c000066400000000000000000000013701414523752600214130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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; } flint2-2.8.4/fmpz_poly/CLD_bound.c000066400000000000000000000164121414523752600167140ustar00rootroot00000000000000/* Copyright (C) 2010, 2016, 2020 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #define CLD_EPS 0.00000001 static 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); } } 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; 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); /* 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(&hi_exp, hi, r, rexp); lo_eval = fmpz_poly_evaluate_horner_d_2exp2(&lo_exp, lo, 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_2exp(&hi_exp, hi, r); lo_eval = fmpz_poly_evaluate_horner_d_2exp(&lo_exp, lo, 1/r); } else /* everything can be handled with doubles */ { double r = pow(2.0, rpow); hi_eval = fmpz_poly_evaluate_horner_d(hi, r); lo_eval = fmpz_poly_evaluate_horner_d(lo, 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: fmpz_poly_clear(lo); fmpz_poly_clear(hi); } flint2-2.8.4/fmpz_poly/CRT_ui.c000066400000000000000000000050141414523752600162440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "nmod_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_printf("Exception (_fmpz_poly_CRT_ui): m1 not invertible modulo m2.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/add.c000066400000000000000000000041701414523752600156510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/add_series.c000066400000000000000000000017571414523752600172330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #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); } flint2-2.8.4/fmpz_poly/bit_pack.c000066400000000000000000000035171414523752600167010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/bit_unpack.c000066400000000000000000000064521414523752600172450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf("Exception (fmpz_poly_bit_unpack_unsigned). Expected an unsigned value.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/bound_roots.c000066400000000000000000000030731414523752600174570ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_poly/chebyshev_t.c000066400000000000000000000024151414523752600174240ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_poly/chebyshev_u.c000066400000000000000000000024251414523752600174260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_poly/clear.c000066400000000000000000000013441414523752600162070ustar00rootroot00000000000000/* 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 2.1 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_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); } } flint2-2.8.4/fmpz_poly/compose.c000066400000000000000000000054411414523752600165700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/compose_divconquer.c000066400000000000000000000152441414523752600210310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/compose_horner.c000066400000000000000000000047121414523752600201450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/compose_series.c000066400000000000000000000043331414523752600201410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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_printf("Exception (fmpz_poly_compose_series). Inner polynomial \n" "must have zero constant term.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpz_poly/compose_series_brent_kung.c000066400000000000000000000063501414523752600223600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mat.h" #include "ulong_extras.h" 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_printf("Exception (fmpz_poly_compose_series_brent_kung). Inner \n" "polynomial must have zero constant term.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpz_poly/compose_series_horner.c000066400000000000000000000055431414523752600215220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" 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_printf("Exception (fmpz_poly_compose_series_horner). Inner polynomial \n" "must have zero constant term.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpz_poly/content.c000066400000000000000000000014451414523752600165750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/cos_minpoly.c000066400000000000000000000170141414523752600174550ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "ulong_extras.h" /* 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_div(f, P, Plen, Q, Qlen, 0); _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); } flint2-2.8.4/fmpz_poly/cyclotomic.c000066400000000000000000000071511414523752600172700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_poly/deflate.c000066400000000000000000000017611414523752600165300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_poly_deflate). Division by zero.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpz_poly/deflation.c000066400000000000000000000020221414523752600170600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" ulong fmpz_poly_deflation(const fmpz_poly_t input) { ulong deflation; slong i, coeff; 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; } flint2-2.8.4/fmpz_poly/derivative.c000066400000000000000000000017241414523752600172650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/discriminant.c000066400000000000000000000021411414523752600176010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/div.c000066400000000000000000000031011414523752600156740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #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_printf("Exception (fmpz_poly_div). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/div_basecase.c000066400000000000000000000061231414523752600175310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpz_poly_div_basecase). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/div_divconquer.c000066400000000000000000000075211414523752600201450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpz_poly_div_divconquer). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/div_divconquer_recursive.c000066400000000000000000000055361414523752600222400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/div_preinv.c000066400000000000000000000042401414523752600172640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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, n); _fmpz_poly_reverse(Q, Q, n, n); if (a != A) _fmpz_vec_clear(a, len1_in); _fmpz_vec_clear(A_rev, len1); } 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 */ } flint2-2.8.4/fmpz_poly/div_root.c000066400000000000000000000024311414523752600167440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } flint2-2.8.4/fmpz_poly/div_series.c000066400000000000000000000036001414523752600172520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_poly_div_series). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/div_series_basecase.c000066400000000000000000000161611414523752600211060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Not an exact division\n"); flint_abort(); } /* 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 > FLINT_BITS - 2 || Bbits[i] > FLINT_BITS - 2) { /* 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 { 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) { 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_printf("Exception (fmpz_poly_div_series_basecase). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/div_series_divconquer.c000066400000000000000000000037221414523752600215160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); _fmpz_vec_clear(Brev, n); flint_printf("Not an exact division\n"); flint_abort(); } _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_printf("Exception (fmpz_poly_div_series_divconquer). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/divhigh_smodp.c000066400000000000000000000030351414523752600177440ustar00rootroot00000000000000/* 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 2.1 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_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_printf("Exception (fmpz_poly_divhigh_smodp). Impossible inverse.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/divides.c000066400000000000000000000047121414523752600165520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.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_printf("Exception (fmpz_poly_divides). Division by zero.\n"); flint_abort(); } 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; } } flint2-2.8.4/fmpz_poly/divlow_smodp.c000066400000000000000000000033321414523752600176260ustar00rootroot00000000000000/* 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 2.1 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_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_printf("Exception (fmpz_poly_divlow_smodp). Impossible inverse.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/divrem.c000066400000000000000000000042171414523752600164110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpz_poly_divrem). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/divrem_basecase.c000066400000000000000000000061241414523752600202360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpz_poly_divrem_basecase). Division by zero.\n"); flint_abort(); } if (Q == R) { flint_printf("Exception (fmpz_poly_divrem_basecase). \n" "Output arguments Q and R may not be aliased.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/divrem_divconquer.c000066400000000000000000000114511414523752600206460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpz_poly_divrem_divconquer). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/divrem_divconquer_recursive.c000066400000000000000000000071531414523752600227410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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; } flint2-2.8.4/fmpz_poly/divrem_preinv.c000066400000000000000000000044711414523752600177760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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 > 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); } flint2-2.8.4/fmpz_poly/divremlow_divconquer_recursive.c000066400000000000000000000074601414523752600234640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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; } flint2-2.8.4/fmpz_poly/equal.c000066400000000000000000000016211414523752600162260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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; } flint2-2.8.4/fmpz_poly/equal_trunc.c000066400000000000000000000023721414523752600174450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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; } flint2-2.8.4/fmpz_poly/eta_qexp.c000066400000000000000000000125251414523752600167320ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_poly/evaluate_divconquer_fmpq.c000066400000000000000000000070671414523752600222210ustar00rootroot00000000000000/* 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 2.1 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_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; count_trailing_zeros(c, 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); count_trailing_zeros(c, 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)); } } flint2-2.8.4/fmpz_poly/evaluate_divconquer_fmpz.c000066400000000000000000000043671414523752600222320ustar00rootroot00000000000000/* 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 2.1 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_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; count_trailing_zeros(c, 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)); count_trailing_zeros(c, 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); } flint2-2.8.4/fmpz_poly/evaluate_fmpq.c000066400000000000000000000023661414523752600177570ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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)); } } flint2-2.8.4/fmpz_poly/evaluate_fmpz.c000066400000000000000000000020161414523752600177600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/evaluate_fmpz_vec.c000066400000000000000000000012541414523752600206200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #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); } flint2-2.8.4/fmpz_poly/evaluate_horner_d.c000066400000000000000000000016071414523752600206110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/evaluate_horner_d_2exp.c000066400000000000000000000064201414523752600215450ustar00rootroot00000000000000/* Copyright (C) 2016 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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) static dpe_t dpe_set_d_exp(double x, slong e) { dpe_t res; res.m = x; res.e = e; DPE_ADJUST(res); return res; } static dpe_t dpe_set_fmpz(const fmpz_t x) { dpe_t res; res.m = fmpz_get_d_2exp(&res.e, x); return res; } static 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 + ldexp(y.m, -d); res.e = x.e; } else { d = -d; if (d > 53 + ADJUSTMENT_DELAY) return y; res.m = y.m + ldexp(x.m, -d); res.e = y.e; } /* We delay adjustments */ /* DPE_ADJUST(res); */ return res; } static 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(slong * exp, const fmpz * poly, slong n, double d, slong dexp) { dpe_t s, t, x; slong i; if (d == 0.0) return fmpz_get_d_2exp(exp, poly + 0); x = dpe_set_d_exp(d, dexp); s = dpe_set_fmpz(poly + n - 1); for (i = n - 2; i >= 0; i--) { s = dpe_mul(s, x); if (!fmpz_is_zero(poly + i)) { t = dpe_set_fmpz(poly + 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_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); } flint2-2.8.4/fmpz_poly/evaluate_horner_fmpq.c000066400000000000000000000034431414523752600213310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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)); } } flint2-2.8.4/fmpz_poly/evaluate_horner_fmpz.c000066400000000000000000000025071414523752600213420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/evaluate_mod.c000066400000000000000000000024301414523752600175630ustar00rootroot00000000000000/* 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 2.1 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" 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); } } flint2-2.8.4/fmpz_poly/evaluate_mpq.c000066400000000000000000000013731414523752600176060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_evaluate_mpq(mpq_t res, const fmpz_poly_t f, const mpq_t a) { fmpq_t r, b; fmpq_init(r); fmpq_init(b); fmpq_set_mpq(b, a); fmpz_poly_evaluate_fmpq(r, f, b); fmpq_get_mpq(res, r); fmpq_clear(r); fmpq_clear(b); } flint2-2.8.4/fmpz_poly/fibonacci.c000066400000000000000000000030411414523752600170320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_poly/fit_length.c000066400000000000000000000013271414523752600172450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #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); } } flint2-2.8.4/fmpz_poly/fprint.c000066400000000000000000000014521414523752600164230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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); } flint2-2.8.4/fmpz_poly/fprint_pretty.c000066400000000000000000000100101414523752600200200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_poly.h" 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_pretty(FILE * file, const fmpz_poly_t poly, const char * x) { return _fmpz_poly_fprint_pretty(file, poly->coeffs, poly->length, x); } flint2-2.8.4/fmpz_poly/fread.c000066400000000000000000000022121414523752600161750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" 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_printf("Exception (fmpz_poly_fread). Length does not fit into a slong.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpz_poly/fread_pretty.c000066400000000000000000000131221414523752600176060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" 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 flint2-2.8.4/fmpz_poly/gcd.c000066400000000000000000000042211414523752600156530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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) { 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); } } } flint2-2.8.4/fmpz_poly/gcd_heuristic.c000066400000000000000000000235041414523752600177370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "mpn_extras.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 * mpz_ptr = 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, mpz_ptr->_mp_d, mpz_ptr->_mp_size); tlimbs = limbsg - mpz_ptr->_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; } } flint2-2.8.4/fmpz_poly/gcd_modular.c000066400000000000000000000225601414523752600174040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "mpn_extras.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_set_ui(l, 0); for (i = 0; i < len1; i++) fmpz_addmul(l, A + i, A + i); nb1 = fmpz_bits(l); fmpz_set_ui(l, 0); for (i = 0; i < len2; i++) fmpz_addmul(l, B + i, B + i); 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_fdiv_ui(g, mod.n); 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); } } } flint2-2.8.4/fmpz_poly/gcd_subresultant.c000066400000000000000000000101761414523752600204740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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 */ fmpz *T; slong len; T = A, A = B, B = T, len = lenA, lenA = lenB, lenB = len; } 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); } } } flint2-2.8.4/fmpz_poly/get_coeff_fmpz.c000066400000000000000000000012471414523752600201000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/get_coeff_si.c000066400000000000000000000012051414523752600175310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" 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); } flint2-2.8.4/fmpz_poly/get_coeff_ui.c000066400000000000000000000012061414523752600175340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" 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); } flint2-2.8.4/fmpz_poly/get_nmod_poly.c000066400000000000000000000016451414523752600177640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "nmod_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 { slong i; nmod_poly_fit_length(res, len); for (i = 0; i < len; i++) res->coeffs[i] = fmpz_fdiv_ui(poly->coeffs + i, res->mod.n); _nmod_poly_set_length(res, len); _nmod_poly_normalise(res); } } flint2-2.8.4/fmpz_poly/get_str.c000066400000000000000000000025751414523752600165770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/get_str_pretty.c000066400000000000000000000052211414523752600201750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" 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); } flint2-2.8.4/fmpz_poly/hensel_build_tree.c000066400000000000000000000052001414523752600205700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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]); /* Swap link[j+1] and V[minp] */ tmp = link[j + 1]; link[j+1] = link[minp]; link[minp] = tmp; 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); } flint2-2.8.4/fmpz_poly/hensel_continue_lift.c000066400000000000000000000047301414523752600213230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.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_printf("Exception (fmpz_poly_continue_hensel_lift).\n"); flint_abort(); } 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; } flint2-2.8.4/fmpz_poly/hensel_lift.c000066400000000000000000000035361414523752600174220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_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); } flint2-2.8.4/fmpz_poly/hensel_lift_once.c000066400000000000000000000024061414523752600204210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "nmod_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); } flint2-2.8.4/fmpz_poly/hensel_lift_only_inverse.c000066400000000000000000000077741414523752600222260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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_vec_scalar_mod_fmpz(M, g, lenG, p1); \ _fmpz_mod_poly_rem(D, C, lenC, M, lenG, one, p1); \ _fmpz_mod_poly_mul(E, D, lenG - 1, b, lenB, p1); \ if (lenB > 1) \ { \ _fmpz_mod_poly_rem(D, E, lenG + lenB - 2, M, lenG, one, p1); \ _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; 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_vec_scalar_mod_fmpz(C, D, lenC, p1); liftinv(B, b, lenB, G, lenG); liftinv(A, a, lenA, H, lenH); _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); } flint2-2.8.4/fmpz_poly/hensel_lift_tree.c000066400000000000000000000016031414523752600204320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/hensel_lift_tree_recursive.c000066400000000000000000000027131414523752600225240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #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); } } flint2-2.8.4/fmpz_poly/hensel_lift_without_inverse.c000066400000000000000000000070341414523752600227350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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_vec_scalar_mod_fmpz(M, g, lenG, p1); \ _fmpz_mod_poly_rem(D, C, lenF, M, lenG, one, p1); \ _fmpz_mod_poly_mul(E, D, lenG - 1, b, lenB, p1); \ if (lenB > 1) \ { \ _fmpz_mod_poly_rem(D, E, lenG + lenB - 2, M, lenG, one, p1); \ _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; 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_vec_scalar_mod_fmpz(C, D, lenF, p1); lift(G, g, lenG, b, lenB); lift(H, h, lenH, a, lenA); _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); } flint2-2.8.4/fmpz_poly/hensel_start_lift.c000066400000000000000000000050151414523752600206310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.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_printf("Exception (fmpz_poly_start_hensel_lift).\n"); flint_abort(); } 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; } flint2-2.8.4/fmpz_poly/hermite_h.c000066400000000000000000000024351414523752600170670ustar00rootroot00000000000000/* Copyright (C) 2011 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void _fmpz_poly_hermite_h(fmpz * coeffs, ulong n) { fmpz_t c; ulong fac = 1; if (n == 0) { fmpz_one(coeffs); return; } if (n == 1) { fmpz_zero(coeffs); fmpz_set_ui(coeffs + 1, 2); return; } fmpz_init(c); fmpz_one(c); fmpz_mul_2exp(c, c, n); while (1) { fmpz_set(coeffs + n, c); if (--n == 0) break; fmpz_zero(coeffs + n); fmpz_neg(c, c); fmpz_mul2_uiui(c, c, n+1, n); fmpz_fdiv_q_2exp(c, c, 2); fmpz_divexact_ui(c, c, fac); ++fac; if (--n == 0) { fmpz_set(coeffs, c); break; } } fmpz_clear(c); } 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); } flint2-2.8.4/fmpz_poly/hermite_he.c000066400000000000000000000023761414523752600172400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void _fmpz_poly_hermite_he(fmpz * coeffs, ulong n) { fmpz_t c; ulong fac = 1; if (n == 0) { fmpz_one(coeffs); return; } if (n == 1) { fmpz_zero(coeffs); fmpz_one(coeffs + 1); return; } fmpz_init(c); fmpz_one(c); while (1) { fmpz_set(coeffs + n, c); if (--n == 0) break; fmpz_zero(coeffs + n); fmpz_mul2_uiui(c, c, n+1, n); fmpz_neg(c, c); fmpz_fdiv_q_2exp(c, c, 1); fmpz_divexact_ui(c, c, fac); ++fac; if (--n == 0) { fmpz_set(coeffs, c); break; } } fmpz_clear(c); } 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); } flint2-2.8.4/fmpz_poly/inflate.c000066400000000000000000000024611414523752600165440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/fmpz_poly/init.c000066400000000000000000000015661414523752600160720ustar00rootroot00000000000000/* 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 2.1 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_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; } flint2-2.8.4/fmpz_poly/inlines.c000066400000000000000000000011611414523752600165570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_POLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" flint2-2.8.4/fmpz_poly/interpolate_fmpz_vec.c000066400000000000000000000036331414523752600213430ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } } flint2-2.8.4/fmpz_poly/inv_series.c000066400000000000000000000024471414523752600172740ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_poly_inv_series). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/inv_series_basecase.c000066400000000000000000000137731414523752600211260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" 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 > FLINT_BITS - 2 || Qbits[i] > FLINT_BITS - 2) { /* 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 { fmpz_mul(Qinv + i, Q + 1, Qinv + i - 1); for (j = 2; j < FLINT_MIN(i + 1, Qlen); j++) fmpz_addmul(Qinv + i, Q + j, Qinv + i - j); if (neg) fmpz_neg(Qinv + i, Qinv + i); } } 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_printf("Exception (fmpz_poly_inv_series_basecase). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/inv_series_newton.c000066400000000000000000000044211414523752600206600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #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_printf("Exception (fmpz_poly_inv_series_newton). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/is_cyclotomic.c000066400000000000000000000046251414523752600177660ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_poly/is_squarefree.c000066400000000000000000000026041414523752600177560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_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); } flint2-2.8.4/fmpz_poly/lcm.c000066400000000000000000000044031414523752600156730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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_div(V, res, len1 + len2 - 1, W, lenW, 0); 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); } flint2-2.8.4/fmpz_poly/legendre_pt.c000066400000000000000000000023311414523752600174060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_poly/monomial_to_newton.c000066400000000000000000000012621414523752600210270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/mul.c000066400000000000000000000115211414523752600157140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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) { mp_size_t limbs1, limbs2; 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); if (bits1 <= FLINT_BITS - 2 && bits2 <= FLINT_BITS - 2 && (len2 < 40 + (bits1 + bits2) / 2 || len1 < 70 + (bits1 + bits2) / 2)) { rbits = bits1 + bits2 + FLINT_BIT_COUNT(len2); if (rbits <= FLINT_BITS - 2) { _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; } } if (len2 < 7) { _fmpz_poly_mul_classical(res, poly1, len1, poly2, len2); return; } 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); } 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); } flint2-2.8.4/fmpz_poly/mul_KS.c000066400000000000000000000074101414523752600163130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fft.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 (limbs1 == limbs2) { if (limbs1 < 2000) mpn_mul_n(arr3, arr1, arr2, limbs1); else flint_mpn_mul_fft_main(arr3, arr1, limbs1, arr2, limbs2); } else if (limbs1 > limbs2) { if (limbs2 < 1000) mpn_mul(arr3, arr1, limbs1, arr2, limbs2); else flint_mpn_mul_fft_main(arr3, arr1, limbs1, arr2, limbs2); } else { if (limbs1 < 1000) mpn_mul(arr3, arr2, limbs2, arr1, limbs1); else flint_mpn_mul_fft_main(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); } } flint2-2.8.4/fmpz_poly/mul_SS.c000066400000000000000000000026101414523752600163200ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_poly/mul_classical.c000066400000000000000000000043111414523752600177310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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) { 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, len1, poly2); /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ _fmpz_vec_scalar_mul_fmpz(res + len1, poly2 + 1, len2 - 1, poly1 + len1 - 1); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < len1 - 1; i++) _fmpz_vec_scalar_addmul_fmpz(res + i + 1, poly2 + 1, len2 - 1, poly1 + i); } } 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); } flint2-2.8.4/fmpz_poly/mul_karatsuba.c000066400000000000000000000122011414523752600177450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "ulong_extras.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); } flint2-2.8.4/fmpz_poly/mulhigh_classical.c000066400000000000000000000052711414523752600205770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/mulhigh_karatsuba_n.c000066400000000000000000000101551414523752600211300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/mulhigh_n.c000066400000000000000000000027741414523752600171030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #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); } flint2-2.8.4/fmpz_poly/mullow.c000066400000000000000000000130731414523752600164420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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) { mp_size_t limbs1, limbs2; slong bits1, bits2, rbits; len1 = FLINT_MIN(len1, n); len2 = FLINT_MIN(len2, n); if (len2 == 1) { _fmpz_vec_scalar_mul_fmpz(res, poly1, len1, poly2); 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); if (bits1 <= FLINT_BITS - 2 && bits2 <= FLINT_BITS - 2 && (len2 < 50 || (4 * len2 >= 3 * n && n < 150 + bits1 + bits2))) { rbits = bits1 + bits2 + FLINT_BIT_COUNT(len2); if (rbits <= FLINT_BITS - 2) { _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; } } if (len2 < 7) { _fmpz_poly_mullow_classical(res, poly1, len1, poly2, len2, n); return; } limbs1 = (bits1 + FLINT_BITS - 1) / FLINT_BITS; limbs2 = (bits2 + FLINT_BITS - 1) / FLINT_BITS; if (n < 16 && (limbs1 > 12 || limbs2 > 12)) { int clear = 0, 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); } 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); } 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); } flint2-2.8.4/fmpz_poly/mullow_KS.c000066400000000000000000000074501414523752600170410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fft.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 (limbs1 == limbs2) { if (limbs1 < 2000) mpn_mul_n(arr3, arr1, arr2, limbs1); else flint_mpn_mul_fft_main(arr3, arr1, limbs1, arr2, limbs2); } else if (limbs1 > limbs2) { if (limbs2 < 1000) mpn_mul(arr3, arr1, limbs1, arr2, limbs2); else flint_mpn_mul_fft_main(arr3, arr1, limbs1, arr2, limbs2); } else { if (limbs1 < 1000) mpn_mul(arr3, arr2, limbs2, arr1, limbs1); else flint_mpn_mul_fft_main(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); } } flint2-2.8.4/fmpz_poly/mullow_SS.c000066400000000000000000000107231414523752600170460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_poly.h" #include "fft.h" #include "fft_tuning.h" #include "flint.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)); size1 = _fmpz_vec_max_limbs(input1, len1); size2 = _fmpz_vec_max_limbs(input2, len2); /* 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 */ bits1 = _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) { bits2 = _fmpz_vec_get_fft(jj, input2, limbs, len2); for (i = len2; i < 4*n; i++) flint_mpn_zero(jj[i], limbs + 1); } else bits2 = bits1; 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); } flint2-2.8.4/fmpz_poly/mullow_SS_precache.c000077500000000000000000000124401414523752600207010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_poly.h" #include "fft.h" #include "fft_tuning.h" #include "flint.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; 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 = _fmpz_vec_max_limbs(poly2->coeffs, pre->len2); /* 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 */ pre->bits2 = _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); pre->bits2 = FLINT_ABS(pre->bits2); /* 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); } flint2-2.8.4/fmpz_poly/mullow_classical.c000066400000000000000000000047441414523752600204650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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) { if ((len1 == 1 && len2 == 1) || n == 1) /* Special case if the length of output 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, FLINT_MIN(len1, n), poly2); /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ if (n > len1) _fmpz_vec_scalar_mul_fmpz(res + len1, poly2 + 1, n - len1, poly1 + len1 - 1); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < FLINT_MIN(len1, n) - 1; i++) _fmpz_vec_scalar_addmul_fmpz(res + i + 1, poly2 + 1, FLINT_MIN(len2, n - i) - 1, poly1 + i); } } 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); } flint2-2.8.4/fmpz_poly/mullow_karatsuba_n.c000066400000000000000000000101441414523752600210100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_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 i, lenr; int clear = 0; fmpz *copy1, *copy2; if (len1 == 0 || len2 == 0) { fmpz_poly_zero(res); return; } lenr = len1 + len2 - 1; if (n > lenr) n = lenr; if (len1 >= n) copy1 = poly1->coeffs; else { copy1 = (fmpz *) flint_malloc(n * sizeof(fmpz)); for (i = 0; i < len1; i++) copy1[i] = poly1->coeffs[i]; flint_mpn_zero((mp_ptr) copy1 + len1, n - len1); clear |= 1; } if (len2 >= n) copy2 = poly2->coeffs; else { copy2 = (fmpz *) flint_malloc(n * sizeof(fmpz)); for (i = 0; i < len2; i++) copy2[i] = poly2->coeffs[i]; flint_mpn_zero((mp_ptr) copy2 + len2, n - len2); clear |= 2; } if (res != poly1 && res != poly2) { fmpz_poly_fit_length(res, n); _fmpz_poly_mullow_karatsuba_n(res->coeffs, copy1, copy2, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_mullow_karatsuba_n(t->coeffs, copy1, copy2, n); fmpz_poly_swap(res, t); fmpz_poly_clear(t); } _fmpz_poly_set_length(res, n); _fmpz_poly_normalise(res); if (clear & 1) flint_free(copy1); if (clear & 2) flint_free(copy2); } flint2-2.8.4/fmpz_poly/mulmid_classical.c000066400000000000000000000047071414523752600204340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/neg.c000066400000000000000000000013261414523752600156720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/newton_to_monomial.c000066400000000000000000000012621414523752600210270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/normalise.c000066400000000000000000000011531414523752600171100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #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; } flint2-2.8.4/fmpz_poly/num_real_roots.c000066400000000000000000000075111414523752600201530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { fprintf(stderr, "Exception (_fmpz_poly_num_real_roots): non-squarefree polynomial\n"); flint_abort(); } 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)) { fprintf(stderr, "Exception (fmpz_poly_num_real_roots): zero polynomial\n"); flint_abort(); } return _fmpz_poly_num_real_roots(pol->coeffs, pol->length); } flint2-2.8.4/fmpz_poly/num_real_roots_sturm.c000066400000000000000000000074161414523752600214110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)) { printf("ERROR (fmpz_poly_num_real_roots_sturm): zero polynomial\n"); flint_abort(); } 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; } } flint2-2.8.4/fmpz_poly/pow.c000066400000000000000000000040531414523752600157260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/pow_addchains.c000066400000000000000000000131271414523752600177260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpz_poly_addchains). Powering via chains not implemented for e > 148.\n"); flint_abort(); } } flint2-2.8.4/fmpz_poly/pow_binexp.c000066400000000000000000000063561414523752600173030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/pow_binomial.c000066400000000000000000000050221414523752600175750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.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_printf("Exception (fmpz_poly_pow_binomial). poly->length not equal to 2.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpz_poly/pow_multinomial.c000066400000000000000000000052151414523752600203410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/pow_small.c000066400000000000000000000025071414523752600171200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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; } } } flint2-2.8.4/fmpz_poly/pow_trunc.c000066400000000000000000000074501414523752600171450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/power_sums.c000066400000000000000000000030011414523752600173140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf ("Exception (fmpz_poly_power_sums). Zero polynomial.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpz_poly/power_sums_naive.c000066400000000000000000000037401414523752600205100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_power_sums_naive(fmpz * res, const fmpz * poly, slong len, slong n) { slong i, k; fmpz_set_ui(res, len - 1); for (k = 1; k < FLINT_MIN(n, len); k++) { fmpz_mul_ui(res + k, poly + len - 1 - k, k); for (i = 1; i < k; i++) fmpz_addmul(res + k, poly + len - 1 - k + i, res + i); fmpz_neg(res + k, res + k); } for (k = len; k < n; k++) { fmpz_zero(res + k); for (i = k - len + 1; i < k; i++) fmpz_addmul(res + k, poly + len - 1 - k + i, res + i); fmpz_neg(res + k, res + k); } } void fmpz_poly_power_sums_naive(fmpz_poly_t res, const fmpz_poly_t poly, slong n) { if (poly->length == 0) { flint_printf ("Exception (fmpz_poly_power_sums_naive). Zero polynomial.\n"); flint_abort(); } 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); } } flint2-2.8.4/fmpz_poly/power_sums_to_poly.c000066400000000000000000000037261414523752600210770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" void _fmpz_poly_power_sums_to_poly(fmpz * res, const fmpz * poly, slong len) { slong i, k; slong d = fmpz_get_ui(poly); fmpz_one(res + d); for (k = 1; k < FLINT_MIN(d + 1, len); k++) { fmpz_set(res + d - k, poly + k); for (i = 1; i < k; i++) fmpz_addmul(res + d - k, res + d - k + i, poly + i); fmpz_divexact_si(res + d - k, res + d - k, k); fmpz_neg(res + d - k, res + d - k); } for (k = len; k <= d; k++) { fmpz_zero(res + d - k); for (i = 1; i < len; i++) fmpz_addmul(res + d - k, res + d - k + i, poly + i); fmpz_divexact_si(res + d - k, res + d - k, k); fmpz_neg(res + d - k, res + d - 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); } } flint2-2.8.4/fmpz_poly/powers_clear.c000066400000000000000000000013611414523752600176050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } flint2-2.8.4/fmpz_poly/powers_precompute.c000066400000000000000000000033111414523752600206770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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_printf("Exception (fmpz_poly_powers_precompute). Division by zero.\n"); flint_abort(); } pinv->powers = _fmpz_poly_powers_precompute(poly->coeffs, poly->length); pinv->len = poly->length; } flint2-2.8.4/fmpz_poly/preinvert.c000066400000000000000000000052341414523752600171410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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_printf("Exception (fmpz_poly_preinvert). Division by zero.\n"); flint_abort(); } 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 */ } flint2-2.8.4/fmpz_poly/primitive_part.c000066400000000000000000000021011414523752600201470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/product_roots_fmpq_vec.c000066400000000000000000000036071414523752600217130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpq.h" #include "fmpz_poly.h" FLINT_DLL 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); } flint2-2.8.4/fmpz_poly/product_roots_fmpz_vec.c000066400000000000000000000031521414523752600217170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } flint2-2.8.4/fmpz_poly/profile/000077500000000000000000000000001414523752600164135ustar00rootroot00000000000000flint2-2.8.4/fmpz_poly/profile/bm-div_divconquer.c000066400000000000000000000063541414523752600222040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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 c, 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); } flint2-2.8.4/fmpz_poly/profile/p-compose.c000066400000000000000000000105631414523752600204660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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. 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]; double T[rows][cols][nalgs]; 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; } 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; } 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); } flint2-2.8.4/fmpz_poly/profile/p-div_preinv.c000066400000000000000000000061501414523752600211630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; scale = 100; if (length >= 50) scale = 10; if (length >= 500) scale = 4; FLINT_TEST_INIT(state); fmpz_poly_t p1, p2, b, q, r, pinv; 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; } flint2-2.8.4/fmpz_poly/profile/p-gcd.c000066400000000000000000000045461414523752600175620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; scale = 100; if (bits >= 50) scale = 10; if (bits >= 500) scale = 4; FLINT_TEST_INIT(state); fmpz_poly_t p1, p2, a, b, c, g; 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; } flint2-2.8.4/fmpz_poly/profile/p-mul.c000066400000000000000000000142111414523752600176100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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 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); } flint2-2.8.4/fmpz_poly/profile/p-mul_triangle.c000066400000000000000000000161121414523752600214770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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 (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] = 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); } flint2-2.8.4/fmpz_poly/profile/p-pow.c000066400000000000000000000071151414523752600176250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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); } flint2-2.8.4/fmpz_poly/profile/p-pow_binomial.c000066400000000000000000000041371414523752600215000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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[1]; FLINT_TEST_INIT(state); fmpz_poly_init2(f, lenhi); fmpz_poly_init2(g[0], ehi * (lenhi - 1) + 1); fmpz_poly_init2(g[1], 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[0], 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[0]); flint_randclear(state); } flint2-2.8.4/fmpz_poly/profile/p-rem_powers_precomp.c000066400000000000000000000062101414523752600227220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; scale = 100; if (length >= 50) scale = 10; if (length >= 500) scale = 4; FLINT_TEST_INIT(state); fmpz_poly_t p1, p2, b, q, r; fmpz_poly_powers_precomp_t 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_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; } flint2-2.8.4/fmpz_poly/profile/p-taylor_shift.c000066400000000000000000000075031414523752600215300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/fmpz_poly/pseudo_div.c000066400000000000000000000032771414523752600172710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpz_poly_pseudo_div). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/pseudo_divrem_basecase.c000066400000000000000000000063511414523752600216170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpz_poly_pseudo_divrem_basecase). Division by zero.\n"); flint_abort(); } if (Q == R) { flint_printf("Exception (fmpz_poly_pseudo_divrem_basecase). \n" "Output arguments Q and R may not be aliased.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/pseudo_divrem_cohen.c000066400000000000000000000070101414523752600211360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpz_poly_pseudo_divrem_cohen). Division by zero.\n"); flint_abort(); } if (Q == R) { flint_printf("Exception (fmpz_poly_pseudo_divrem_cohen). \n" "Output arguments Q and R may not be aliased.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/pseudo_divrem_divconquer.c000066400000000000000000000242311414523752600222250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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_printf("Exception (fmpz_poly_pseudo_divrem_divconquer). Division by zero.\n"); flint_abort(); } if (Q == R) { flint_printf("Exception (fmpz_poly_pseudo_divrem_divconquer). \n" "Output arguments Q and R may not be aliased.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/pseudo_rem.c000066400000000000000000000034331414523752600172640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpz_poly_pseudo_rem). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/pseudo_rem_cohen.c000066400000000000000000000042001414523752600204310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpz_poly_pseudo_rem_cohen). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/randtest.c000066400000000000000000000027141414523752600167470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" 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_printf("Exception (fmpz_poly_randtest_not_zero). bits or len is zero.\n"); flint_abort(); } fmpz_poly_randtest(f, state, len, bits); if (fmpz_poly_is_zero(f)) fmpz_poly_set_ui(f, 1); } flint2-2.8.4/fmpz_poly/randtest_no_real_root.c000066400000000000000000000054201414523752600215060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { fprintf(stderr, "ERROR (fmpz_poly_randtest_no_real_root): got non-positive length\n"); abort(); } 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); } } flint2-2.8.4/fmpz_poly/realloc.c000066400000000000000000000022601414523752600165400ustar00rootroot00000000000000/* 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 2.1 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_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; } flint2-2.8.4/fmpz_poly/rem.c000066400000000000000000000031351414523752600157040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #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_printf("Exception (fmpz_poly_rem). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/rem_basecase.c000066400000000000000000000036141414523752600175340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (fmpz_poly_rem_basecase). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/rem_powers_precomp.c000066400000000000000000000035571414523752600210400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } flint2-2.8.4/fmpz_poly/remove.c000066400000000000000000000042331414523752600164160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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_printf("Exception (fmpz_poly_remove). Division by zero.\n"); flint_abort(); } if (poly2->length == 1 && fmpz_is_pm1(poly2->coeffs + 0)) { flint_printf("Exception (fmpz_poly_remove). Divisor must not be a unit.\n"); flint_abort(); } 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_div(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; } flint2-2.8.4/fmpz_poly/remove_content_2exp.c000066400000000000000000000017541414523752600211130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_poly/resultant.c000066400000000000000000000030041414523752600171350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/resultant_euclidean.c000066400000000000000000000062211414523752600211520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/resultant_modular.c000066400000000000000000000102711414523752600206640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "mpn_extras.h" void _fmpz_poly_resultant_modular(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { flint_bitcnt_t bits1, bits2, 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); } } flint2-2.8.4/fmpz_poly/resultant_modular_div.c000066400000000000000000000127101414523752600215260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "mpn_extras.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); } } flint2-2.8.4/fmpz_poly/reverse.c000066400000000000000000000025531414523752600165770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/revert_series.c000066400000000000000000000025611414523752600200040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void _fmpz_poly_revert_series(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) { _fmpz_poly_revert_series_lagrange_fast(Qinv, Q, Qlen, n); } 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_printf("Exception (fmpz_poly_revert_series). Input must have \n" "zero constant term and +1 or -1 as coefficient of x^1\n."); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/revert_series_lagrange.c000066400000000000000000000040171414523752600216420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" void _fmpz_poly_revert_series_lagrange(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) { slong i; fmpz *R, *S, *T, *tmp; if (n <= 2) { _fmpz_vec_set(Qinv, Q, n); return; } R = _fmpz_vec_init(n - 1); S = _fmpz_vec_init(n - 1); T = _fmpz_vec_init(n - 1); fmpz_zero(Qinv); fmpz_set(Qinv + 1, Q + 1); _fmpz_poly_inv_series(R, Q + 1, FLINT_MIN(Qlen, n) - 1, n - 1); _fmpz_vec_set(S, R, n - 1); for (i = 2; i < n; i++) { _fmpz_poly_mullow(T, S, n - 1, R, n - 1, n - 1); fmpz_divexact_ui(Qinv + i, T + i - 1, i); tmp = S; S = T; T = tmp; } _fmpz_vec_clear(R, n - 1); _fmpz_vec_clear(S, n - 1); _fmpz_vec_clear(T, n - 1); } void fmpz_poly_revert_series_lagrange(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_printf("Exception (fmpz_poly_revert_series_lagrange). Input must have \n" "zero constant term and +1 or -1 as coefficient of x^1\n."); flint_abort(); } if (Qinv != Q) { fmpz_poly_fit_length(Qinv, n); _fmpz_poly_revert_series_lagrange(Qinv->coeffs, Q->coeffs, Qlen, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_revert_series_lagrange(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); } flint2-2.8.4/fmpz_poly/revert_series_lagrange_fast.c000066400000000000000000000053541414523752600226640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "ulong_extras.h" /* pointer to (x/Q)^i */ #define Ri(ii) (R + (n-1)*((ii)-1)) void _fmpz_poly_revert_series_lagrange_fast(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) { slong i, j, k, m; fmpz *R, *S, *T, *tmp; fmpz_t t; if (n <= 2) { _fmpz_vec_set(Qinv, Q, n); return; } m = n_sqrt(n); fmpz_init(t); R = _fmpz_vec_init((n - 1) * m); S = _fmpz_vec_init(n - 1); T = _fmpz_vec_init(n - 1); fmpz_zero(Qinv); fmpz_set(Qinv + 1, Q + 1); _fmpz_poly_inv_series(Ri(1), Q + 1, FLINT_MIN(Qlen, n) - 1, n - 1); for (i = 2; i <= m; i++) _fmpz_poly_mullow(Ri(i), Ri(i-1), n - 1, Ri(1), n - 1, n - 1); for (i = 2; i < m; i++) fmpz_divexact_ui(Qinv + i, Ri(i) + i - 1, i); _fmpz_vec_set(S, Ri(m), n - 1); for (i = m; i < n; i += m) { fmpz_divexact_ui(Qinv + i, S + i - 1, i); for (j = 1; j < m && i + j < n; j++) { fmpz_mul(t, S + 0, Ri(j) + i + j - 1); for (k = 1; k <= i + j - 1; k++) fmpz_addmul(t, S + k, Ri(j) + i + j - 1 - k); fmpz_divexact_ui(Qinv + i + j, t, i + j); } if (i + 1 < n) { _fmpz_poly_mullow(T, S, n - 1, Ri(m), n - 1, n - 1); tmp = S; S = T; T = tmp; } } fmpz_clear(t); _fmpz_vec_clear(R, (n - 1) * m); _fmpz_vec_clear(S, n - 1); _fmpz_vec_clear(T, n - 1); } void fmpz_poly_revert_series_lagrange_fast(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_printf("Exception (fmpz_poly_revert_series_lagrange_fast). Input must have \n" "zero constant term and +1 or -1 as coefficient of x^1\n."); flint_abort(); } if (Qinv != Q) { fmpz_poly_fit_length(Qinv, n); _fmpz_poly_revert_series_lagrange_fast(Qinv->coeffs, Q->coeffs, Qlen, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_revert_series_lagrange_fast(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); } flint2-2.8.4/fmpz_poly/revert_series_newton.c000066400000000000000000000043021414523752600213710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #define FLINT_REVERSE_NEWTON_CUTOFF 10 void _fmpz_poly_revert_series_newton(fmpz * Qinv, const fmpz * Q, slong Qlen, slong n) { fmpz *T, *U, *V; slong alloc = 3 * n; if (n <= 2) { _fmpz_vec_set(Qinv, Q, n); return; } T = _fmpz_vec_init(alloc); U = T + n; V = U + n; FLINT_NEWTON_INIT(FLINT_REVERSE_NEWTON_CUTOFF, n) FLINT_NEWTON_BASECASE(k) _fmpz_poly_revert_series_lagrange(Qinv, Q, Qlen, k); _fmpz_vec_zero(Qinv + k, n - k); FLINT_NEWTON_END_BASECASE FLINT_NEWTON_LOOP(FLINT_UNUSED(k0), k) _fmpz_poly_compose_series(T, Q, FLINT_MIN(Qlen, k), Qinv, k, k); _fmpz_poly_derivative(U, T, k); fmpz_zero(U + k - 1); fmpz_zero(T + 1); _fmpz_poly_div_series(V, T, k, U, k, k); _fmpz_poly_derivative(T, Qinv, k); _fmpz_poly_mullow(U, V, k, T, k, k); _fmpz_vec_sub(Qinv, Qinv, U, k); FLINT_NEWTON_END_LOOP FLINT_NEWTON_END _fmpz_vec_clear(T, alloc); } void fmpz_poly_revert_series_newton(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_printf("Exception (fmpz_poly_revert_series_newton). Input must have \n" "zero constant term and +1 or -1 as coefficient of x^1\n."); flint_abort(); } if (Qinv != Q) { fmpz_poly_fit_length(Qinv, n); _fmpz_poly_revert_series_newton(Qinv->coeffs, Q->coeffs, Qlen, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_revert_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); } flint2-2.8.4/fmpz_poly/scalar_abs.c000066400000000000000000000012611414523752600172110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } flint2-2.8.4/fmpz_poly/scalar_addmul_fmpz.c000066400000000000000000000021721414523752600207500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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); } } flint2-2.8.4/fmpz_poly/scalar_divexact_fmpz.c000066400000000000000000000020141414523752600213040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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_printf("Exception (fmpz_poly_scalar_divexact_fmpz). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/scalar_divexact_si.c000066400000000000000000000017641414523752600207560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_scalar_divexact_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) { if (x == 0) { flint_printf("Exception (fmpz_poly_scalar_divexact_si). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/scalar_divexact_ui.c000066400000000000000000000017641414523752600207600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_scalar_divexact_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) { if (x == 0) { flint_printf("Exception (fmpz_poly_scalar_divexact_ui). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/scalar_fdiv_2exp.c000066400000000000000000000015611414523752600203350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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); } flint2-2.8.4/fmpz_poly/scalar_fdiv_fmpz.c000066400000000000000000000017761414523752600204430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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_printf("Exception (fmpz_poly_scalar_fdiv_fmpz). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/scalar_fdiv_si.c000066400000000000000000000017461414523752600200770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_scalar_fdiv_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) { if (x == 0) { flint_printf("Exception (fmpz_poly_scalar_fdiv_si). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/scalar_fdiv_ui.c000066400000000000000000000017461414523752600201010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_scalar_fdiv_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) { if (x == 0) { flint_printf("Exception (fmpz_poly_scalar_fdiv_ui). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/scalar_mul_2exp.c000066400000000000000000000015421414523752600202010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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); } flint2-2.8.4/fmpz_poly/scalar_mul_fmpz.c000066400000000000000000000016441414523752600203020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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); } flint2-2.8.4/fmpz_poly/scalar_mul_si.c000066400000000000000000000022251414523752600177350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" 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); } flint2-2.8.4/fmpz_poly/scalar_mul_ui.c000066400000000000000000000020111414523752600177300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" 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); } flint2-2.8.4/fmpz_poly/scalar_submul_fmpz.c000066400000000000000000000022011414523752600210020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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); } } flint2-2.8.4/fmpz_poly/scalar_tdiv_2exp.c000066400000000000000000000015611414523752600203530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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); } flint2-2.8.4/fmpz_poly/scalar_tdiv_fmpz.c000066400000000000000000000017761414523752600204610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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_printf("Exception (fmpz_poly_scalar_tdiv_fmpz). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/scalar_tdiv_si.c000066400000000000000000000017461414523752600201150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_scalar_tdiv_si(fmpz_poly_t poly1, const fmpz_poly_t poly2, slong x) { if (x == 0) { flint_printf("Exception (fmpz_poly_scalar_tdiv_si). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/scalar_tdiv_ui.c000066400000000000000000000017461414523752600201170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" void fmpz_poly_scalar_tdiv_ui(fmpz_poly_t poly1, const fmpz_poly_t poly2, ulong x) { if (x == 0) { flint_printf("Exception (fmpz_poly_scalar_tdiv_ui). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/scale_2exp.c000066400000000000000000000027261414523752600171530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_poly/set.c000066400000000000000000000014651414523752600157200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/set_coeff_fmpz.c000066400000000000000000000021601414523752600201070ustar00rootroot00000000000000/* 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 2.1 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_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); } } flint2-2.8.4/fmpz_poly/set_coeff_si.c000066400000000000000000000021411414523752600175450ustar00rootroot00000000000000/* 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 2.1 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_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); } } flint2-2.8.4/fmpz_poly/set_coeff_ui.c000066400000000000000000000021411414523752600175470ustar00rootroot00000000000000/* 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 2.1 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_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); } } flint2-2.8.4/fmpz_poly/set_fmpz.c000066400000000000000000000013141414523752600167450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" 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); } } flint2-2.8.4/fmpz_poly/set_mpz.c000066400000000000000000000013161414523752600166010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_set_mpz(fmpz_poly_t poly, const mpz_t c) { if (mpz_sgn(c) == 0) fmpz_poly_zero(poly); else { fmpz_poly_fit_length(poly, 1); fmpz_set_mpz(poly->coeffs, c); _fmpz_poly_set_length(poly, 1); } } flint2-2.8.4/fmpz_poly/set_nmod_poly.c000066400000000000000000000016061414523752600177750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "nmod_poly.h" 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); } } flint2-2.8.4/fmpz_poly/set_nmod_poly_unsigned.c000066400000000000000000000015751414523752600216760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "nmod_poly.h" 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); } } flint2-2.8.4/fmpz_poly/set_si.c000066400000000000000000000012751414523752600164120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" 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); } } flint2-2.8.4/fmpz_poly/set_str.c000066400000000000000000000041521414523752600166040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include "flint.h" #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; } flint2-2.8.4/fmpz_poly/set_trunc.c000066400000000000000000000016331414523752600171300ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } } flint2-2.8.4/fmpz_poly/set_ui.c000066400000000000000000000013041414523752600164050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" 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); } } flint2-2.8.4/fmpz_poly/shift_left.c000066400000000000000000000025031414523752600172460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/shift_right.c000066400000000000000000000024461414523752600174370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly/signature.c000066400000000000000000000057101414523752600171230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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) { flint_printf("Exception (fmpz_poly_signature). Non-squarefree polynomial detected.\n"); _fmpz_vec_clear(w, 2 * len + 2); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly/sqr.c000066400000000000000000000075361414523752600157370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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) { mp_size_t limbs; slong bits, rbits; if (len == 1) { fmpz_mul(res, poly, poly); return; } bits = _fmpz_vec_max_bits(poly, len); bits = FLINT_ABS(bits); if (bits <= FLINT_BITS - 2 && len < 50 + 3 * bits) { rbits = 2 * bits + FLINT_BIT_COUNT(len); if (rbits <= FLINT_BITS - 2) { _fmpz_poly_sqr_tiny1(res, poly, len); return; } else if (rbits <= 2 * FLINT_BITS - 1) { _fmpz_poly_sqr_tiny2(res, poly, len); return; } } if (len < 7) { _fmpz_poly_sqr_classical(res, poly, len); return; } 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); } 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); } flint2-2.8.4/fmpz_poly/sqr_KS.c000066400000000000000000000042501414523752600163220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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)); 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); } flint2-2.8.4/fmpz_poly/sqr_classical.c000066400000000000000000000033711414523752600177460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" /* Assumes len > 0. */ void _fmpz_poly_sqr_classical(fmpz *rop, const fmpz *op, slong len) { if (len == 1) /* Special case */ { fmpz_mul(rop, op, op); } else /* Ordinary case */ { slong i; _fmpz_vec_scalar_mul_fmpz(rop, op, len, op); _fmpz_vec_scalar_mul_fmpz(rop + len, op + 1, len - 1, op + len - 1); for (i = 1; i < len - 1; i++) _fmpz_vec_scalar_addmul_fmpz(rop + i + 1, op + 1, i - 1, op + i); for (i = 1; i < 2 * len - 2; i++) fmpz_mul_ui(rop + i, rop + i, 2); for (i = 1; i < len - 1; i++) fmpz_addmul(rop + 2 * i, op + i, op + i); } } 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); } flint2-2.8.4/fmpz_poly/sqr_karatsuba.c000066400000000000000000000050121414523752600177570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "ulong_extras.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); } flint2-2.8.4/fmpz_poly/sqrlow.c000066400000000000000000000106441414523752600164530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" 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) { mp_size_t limbs; 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); if (bits <= FLINT_BITS - 2 && (len < 50 + 2 * bits || (4 * len >= 3 * n && n < 140 + 6 * bits))) { rbits = 2 * bits + FLINT_BIT_COUNT(len); if (rbits <= FLINT_BITS - 2) { _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; } } if (n < 7) { _fmpz_poly_sqrlow_classical(res, poly, len, n); return; } limbs = (bits + FLINT_BITS - 1) / FLINT_BITS; if (n < 16 && limbs > 12) { int i; fmpz *copy; 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); _fmpz_poly_sqrlow_karatsuba_n(res, copy, n); flint_free(copy); } 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); } 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); } flint2-2.8.4/fmpz_poly/sqrlow_KS.c000066400000000000000000000043531414523752600170500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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); 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); } flint2-2.8.4/fmpz_poly/sqrlow_classical.c000066400000000000000000000036421414523752600204710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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 *rop, const fmpz *op, slong len, slong n) { if (len == 1 || n == 1) /* Special case */ { fmpz_mul(rop, op, op); } else /* Ordinary case */ { slong i; _fmpz_vec_scalar_mul_fmpz(rop, op, FLINT_MIN(len, n), op); _fmpz_vec_scalar_mul_fmpz(rop + len, op + 1, n - len, op + len - 1); for (i = 1; i < len - 1; i++) _fmpz_vec_scalar_addmul_fmpz(rop + i + 1, op + 1, FLINT_MIN(i - 1, n - (i + 1)), op + i); for (i = 1; i < FLINT_MIN(2 * len - 2, n); i++) fmpz_mul_ui(rop + i, rop + i, 2); for (i = 1; i < FLINT_MIN(len - 1, (n + 1) / 2); i++) fmpz_addmul(rop + 2 * i, op + i, op + i); } } 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); } flint2-2.8.4/fmpz_poly/sqrlow_karatsuba_n.c000066400000000000000000000060731414523752600210260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_n(fmpz_poly_t res, const fmpz_poly_t poly, slong n) { const slong len = FLINT_MIN(poly->length, n); slong i, lenr; int clear = 0; fmpz *copy; if (len == 0) { fmpz_poly_zero(res); return; } lenr = 2 * len - 1; if (n > lenr) n = lenr; if (len >= n) copy = poly->coeffs; else { copy = flint_malloc(n * sizeof(fmpz)); for (i = 0; i < len; i++) copy[i] = poly->coeffs[i]; flint_mpn_zero((mp_ptr) copy + len, n - len); clear = 1; } if (res != poly) { fmpz_poly_fit_length(res, n); _fmpz_poly_sqrlow_karatsuba_n(res->coeffs, copy, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_sqrlow_karatsuba_n(t->coeffs, copy, 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); } flint2-2.8.4/fmpz_poly/sqrt.c000066400000000000000000000025571414523752600161210ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #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; } flint2-2.8.4/fmpz_poly/sqrt_KS.c000066400000000000000000000061411414523752600165070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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; } flint2-2.8.4/fmpz_poly/sqrt_classical.c000066400000000000000000000105111414523752600201240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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 divison 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; } flint2-2.8.4/fmpz_poly/sqrt_divconquer.c000066400000000000000000000067471414523752600203650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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; } flint2-2.8.4/fmpz_poly/sqrt_series.c000066400000000000000000000036541414523752600174720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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; } flint2-2.8.4/fmpz_poly/sqrtrem_classical.c000066400000000000000000000052731414523752600206410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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 divison 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; } flint2-2.8.4/fmpz_poly/sqrtrem_divconquer.c000066400000000000000000000057531414523752600210650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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; } flint2-2.8.4/fmpz_poly/sub.c000066400000000000000000000056021414523752600157130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } } flint2-2.8.4/fmpz_poly/sub_series.c000066400000000000000000000017571414523752600172740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #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); } flint2-2.8.4/fmpz_poly/swap.c000066400000000000000000000016101414523752600160670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" void fmpz_poly_swap(fmpz_poly_t poly1, fmpz_poly_t poly2) { if (poly1 != poly2) { slong temp; fmpz *temp_c; temp = poly1->length; poly1->length = poly2->length; poly2->length = temp; temp = poly1->alloc; poly1->alloc = poly2->alloc; poly2->alloc = temp; temp_c = poly1->coeffs; poly1->coeffs = poly2->coeffs; poly2->coeffs = temp_c; } } flint2-2.8.4/fmpz_poly/swinnerton_dyer.c000066400000000000000000000060771414523752600203620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_poly.h" /* Bound coefficients using (x + u)^(2^n) and the binomial coefficients. TODO: this is about 2x too large... */ static slong __bound_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)) */ return u; } void _fmpz_poly_swinnerton_dyer(fmpz * T, ulong n) { fmpz *square_roots, *tmp1, *tmp2, *tmp3; fmpz_t one; slong i, j, k, N; slong prec; if (n == 0) { fmpz_zero(T); fmpz_one(T + 1); return; } N = WORD(1) << n; prec = __bound_prec(n); fmpz_init(one); fmpz_one(one); fmpz_mul_2exp(one, one, prec); square_roots = _fmpz_vec_init(n); tmp1 = flint_malloc((N/2 + 1) * sizeof(fmpz)); tmp2 = flint_malloc((N/2 + 1) * sizeof(fmpz)); tmp3 = _fmpz_vec_init(N); for (i = 0; i < n; i++) { fmpz_set_ui(square_roots + i, n_nth_prime(i + 1)); fmpz_mul_2exp(square_roots + i, square_roots + i, 2 * prec); fmpz_sqrt(square_roots + i, square_roots + i); } /* Build linear factors */ for (i = 0; i < N; i++) { fmpz_zero(T + i); for (j = 0; j < n; j++) { if ((i >> j) & 1) fmpz_add(T + i, T + i, square_roots + j); else fmpz_sub(T + i, T + i, square_roots + j); } } /* For each level... */ for (i = 0; i < n; i++) { slong stride = UWORD(1) << i; for (j = 0; j < N; 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; _fmpz_poly_mullow(tmp3, tmp1, stride + 1, tmp2, stride + 1, 2*stride); _fmpz_vec_scalar_fdiv_q_2exp(T + j, tmp3, 2*stride, prec); } } /* Round */ fmpz_fdiv_q_2exp(one, one, 1); for (i = 0; i < N; i++) fmpz_add(T + i, T + i, one); _fmpz_vec_scalar_fdiv_q_2exp(T, T, N, prec); fmpz_one(T + (UWORD(1) << n)); _fmpz_vec_clear(square_roots, n); flint_free(tmp1); flint_free(tmp2); _fmpz_vec_clear(tmp3, UWORD(1) << n); fmpz_clear(one); } 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); } flint2-2.8.4/fmpz_poly/taylor_shift.c000066400000000000000000000015651414523752600176350ustar00rootroot00000000000000/* 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 2.1 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_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); } flint2-2.8.4/fmpz_poly/taylor_shift_divconquer.c000066400000000000000000000077241414523752600220770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "nmod_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, 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; 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); } flint2-2.8.4/fmpz_poly/taylor_shift_horner.c000066400000000000000000000126441414523752600212120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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 <= FLINT_BITS - 2) { 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); } flint2-2.8.4/fmpz_poly/taylor_shift_multi_mod_threaded.c000066400000000000000000000141671414523752600235500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "thread_support.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); } flint2-2.8.4/fmpz_poly/test/000077500000000000000000000000001414523752600157325ustar00rootroot00000000000000flint2-2.8.4/fmpz_poly/test/t-2norm_normalised_bits.c000066400000000000000000000034331414523752600226350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("2norm_normalised_bits...."); fflush(stdout); /* 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); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_poly_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-CLD_bound.c000066400000000000000000000110461414523752600201320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("CLD_bound...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); fmpz_poly_clear(g); fmpz_clear(bound); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-CRT_ui.c000066400000000000000000000052251414523752600174700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "nmod_poly.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("CRT_ui...."); fflush(stdout); 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"); abort(); } nmod_poly_clear(Amod); fmpz_poly_clear(A); fmpz_poly_clear(B); fmpz_poly_clear(C); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-CRT_ui_unsigned.c000066400000000000000000000052211414523752600213600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "nmod_poly.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("CRT_ui_unsigned...."); fflush(stdout); 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"); abort(); } nmod_poly_clear(Amod); fmpz_poly_clear(A); fmpz_poly_clear(B); fmpz_poly_clear(C); fmpz_clear(mod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-add.c000066400000000000000000000045041414523752600170720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-add_series.c000066400000000000000000000070011414523752600204370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add_series...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-add_sub_fmpz.c000066400000000000000000000046331414523752600210020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_poly.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("add_sub_fmpz...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(s); fmpz_poly_clear(t); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-add_sub_si.c000066400000000000000000000045131414523752600204360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_poly.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("add_sub_si...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(s); fmpz_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-bit_pack.c000066400000000000000000000121451414523752600201160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("bit_pack/bit_unpack...."); fflush(stdout); 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"); 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"); 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"); 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"); abort(); } fmpz_clear(f); fmpz_poly_clear(A); fmpz_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-bound_roots.c000066400000000000000000000046471414523752600207070ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("bound_roots...."); fflush(stdout); 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"); abort(); } fmpz_clear(t); fmpz_clear(p); fmpz_clear(q); fmpz_clear(bound); fmpz_clear(nbound); fmpz_poly_clear(f); fmpz_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-chebyshev_t.c000066400000000000000000000027501414523752600206460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" int main() { fmpz_poly_t T0, T1, T2, t; slong n; FLINT_TEST_INIT(state); flint_printf("chebyshev_t...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-chebyshev_u.c000066400000000000000000000023071414523752600206450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" int main() { fmpz_poly_t T, U; slong n; FLINT_TEST_INIT(state); flint_printf("chebyshev_u...."); fflush(stdout); 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"); abort(); } } fmpz_poly_clear(T); fmpz_poly_clear(U); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-compose.c000066400000000000000000000143211414523752600200050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(s); fmpz_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-compose_divconquer.c000066400000000000000000000061771414523752600222560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_divconquer...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(f1); fmpz_poly_clear(f2); fmpz_poly_clear(g); fmpz_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-compose_horner.c000066400000000000000000000061411414523752600213630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_horner...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(f1); fmpz_poly_clear(f2); fmpz_poly_clear(g); fmpz_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-compose_series.c000066400000000000000000000074021414523752600213610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_series...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(s); fmpz_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-compose_series_brent_kung.c000066400000000000000000000075311414523752600236020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_series_brent_kung...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(s); fmpz_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-compose_series_horner.c000066400000000000000000000074541414523752600227450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_series_horner...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); fmpz_poly_clear(s); fmpz_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-content.c000066400000000000000000000031421414523752600200110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("content...."); fflush(stdout); /* 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"); abort(); } fmpz_clear(a); fmpz_clear(c); fmpz_clear(d); fmpz_poly_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-cos_minpoly.c000066400000000000000000000066161414523752600207030ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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 }; int main() { fmpz_poly_t p; slong n; FLINT_TEST_INIT(state); flint_printf("cos_minpoly...."); fflush(stdout); 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"); abort(); } } fmpz_poly_clear(p); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-cyclotomic.c000066400000000000000000000060711414523752600205100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } int main() { fmpz_poly_t A, B; slong n; FLINT_TEST_INIT(state); flint_printf("cyclotomic...."); fflush(stdout); 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"); 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"); abort(); } fmpz_poly_clear(A); fmpz_clear(h); fmpz_clear(ref); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-deflate.c000066400000000000000000000062601414523752600177470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("deflate...."); fflush(stdout); 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"); 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"); 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"); 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"); flint_abort(); } fmpz_poly_deflate(poly2, poly2, infl); if (!fmpz_poly_equal(poly3, poly2)) { flint_printf("FAIL: aliasing\n"); flint_abort(); } } fmpz_poly_clear(poly1); fmpz_poly_clear(poly2); fmpz_poly_clear(poly3); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-derivative.c000066400000000000000000000060571414523752600205110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("derivative...."); fflush(stdout); /* 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-discriminant.c000066400000000000000000000060061414523752600210250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("discriminant...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(a); fmpz_poly_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-div_basecase.c000066400000000000000000000065231414523752600207550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_basecase...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-div_divconquer.c000066400000000000000000000065461414523752600213730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_divconquer...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-div_preinv.c000066400000000000000000000076241414523752600205150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_preinv...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-div_root.c000066400000000000000000000056511414523752600201730ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_root...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(c); fmpz_poly_clear(P); fmpz_poly_clear(Q1); fmpz_poly_clear(Q2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-div_series.c000066400000000000000000000125061414523752600204770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_series...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-div_series_basecase.c000066400000000000000000000125771414523752600223350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_series_basecase...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-div_series_divconquer.c000066400000000000000000000126231414523752600227360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_series_divconquer...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-divhigh_smodp.c000066400000000000000000000057251414523752600211740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divhigh_smodp...."); fflush(stdout); /* 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-divides.c000066400000000000000000000107201414523752600177660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divides...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-divlow_smodp.c000066400000000000000000000056601414523752600210540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divlow_smodp...."); fflush(stdout); /* 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-divrem.c000066400000000000000000000123161414523752600176300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; slong tmul = 100; FLINT_TEST_INIT(state); flint_printf("divrem...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-divrem_basecase.c000066400000000000000000000124111414523752600214520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divrem_basecase...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-divrem_divconquer.c000066400000000000000000000124351414523752600220710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divrem_divconquer...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-divrem_preinv.c000066400000000000000000000142701414523752600212140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divrem_preinv...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); fmpz_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-equal_fmpz.c000066400000000000000000000031551414523752600205060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("equal_fmpz...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-equal_trunc.c000066400000000000000000000053471414523752600206720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("equal_trunc...."); fflush(stdout); /* 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); 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); abort(); } fmpz_clear(c); fmpz_poly_clear(a); fmpz_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-eta_qexp.c000066400000000000000000000033411414523752600201460ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("eta_qexp...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly/test/t-evaluate_divconquer_fmpq.c000066400000000000000000000105241414523752600234310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_divconquer_fmpq...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpz_poly_clear(f); fmpz_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-evaluate_divconquer_fmpz.c000066400000000000000000000045011414523752600234400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_divconquer_fmpz...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_poly_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-evaluate_fmpq.c000066400000000000000000000103611414523752600211710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_fmpq...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpz_poly_clear(f); fmpz_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-evaluate_fmpz.c000066400000000000000000000027161414523752600212070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_fmpz...."); fflush(stdout); /* 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_poly_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-evaluate_horner_d_2exp.c000066400000000000000000000067561414523752600230010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("evaluate_horner_d_2exp...."); fflush(stdout); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-evaluate_horner_fmpq.c000066400000000000000000000104551414523752600225520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_horner_fmpq...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpq_clear(x); fmpq_clear(y); fmpq_clear(z); fmpz_poly_clear(f); fmpz_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-evaluate_horner_fmpz.c000066400000000000000000000047351414523752600225670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_horner...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(a); fmpz_clear(b); fmpz_clear(c); fmpz_poly_clear(f); fmpz_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-evaluate_mod.c000066400000000000000000000033611414523752600210070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_mod...."); fflush(stdout); /* 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"); abort(); } fmpz_poly_clear(f); fmpz_clear(b); fmpz_clear(s); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly/test/t-evaluate_mpq.c000066400000000000000000000103201414523752600210160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_mpq...."); fflush(stdout); /* Check aliasing */ for (i = 0; i < 75 * flint_test_multiplier(); i++) { fmpz_t a, b; mpq_t x, y; fmpz_poly_t f; fmpz_init(a); fmpz_init(b); mpq_init(x); mpq_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_get_mpz(mpq_numref(x), a); fmpz_get_mpz(mpq_denref(x), b); mpq_canonicalize(x); fmpz_poly_evaluate_mpq(y, f, x); fmpz_poly_evaluate_mpq(x, f, x); result = (mpq_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"); abort(); } fmpz_clear(a); fmpz_clear(b); mpq_clear(x); mpq_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; mpq_t x, y, z; fmpz_poly_t f, g; fmpz_init(a); fmpz_init(b); mpq_init(x); mpq_init(y); mpq_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_get_mpz(mpq_numref(x), a); fmpz_get_mpz(mpq_denref(x), b); mpq_canonicalize(x); fmpz_poly_evaluate_mpq(y, f, x); fmpz_poly_evaluate_mpq(z, g, x); mpq_add(y, y, z); fmpz_poly_add(f, f, g); fmpz_poly_evaluate_mpq(z, f, x); result = (mpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); abort(); } fmpz_clear(a); fmpz_clear(b); mpq_clear(x); mpq_clear(y); mpq_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; mpq_t x, y, z; fmpz_poly_t f, g; fmpz_init(a); fmpz_init(b); mpq_init(x); mpq_init(y); mpq_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_get_mpz(mpq_numref(x), a); fmpz_get_mpz(mpq_denref(x), b); mpq_canonicalize(x); fmpz_poly_evaluate_mpq(y, f, x); fmpz_poly_evaluate_mpq(z, g, x); mpq_mul(y, y, z); fmpz_poly_mul(f, f, g); fmpz_poly_evaluate_mpq(z, f, x); result = (mpq_equal(y, z)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(a), flint_printf("\n\n"); fmpz_print(b), flint_printf("\n\n"); abort(); } fmpz_clear(a); fmpz_clear(b); mpq_clear(x); mpq_clear(y); mpq_clear(z); fmpz_poly_clear(f); fmpz_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-fibonacci.c000066400000000000000000000027321414523752600202600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" int main(void) { fmpz_poly_t Pn, Pn1, Pn2, R; slong n; FLINT_TEST_INIT(state); flint_printf("fibonacci...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-gcd.c000066400000000000000000000066501414523752600171030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd...."); fflush(stdout); /* 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-gcd_heuristic.c000066400000000000000000000230441414523752600211560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.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. */ static int _t_gcd_is_canonical(const fmpz_poly_t poly) { return fmpz_poly_is_zero(poly) || (fmpz_sgn(fmpz_poly_lead(poly)) > 0); } int main(void) { int i, result, d1, d2; FLINT_TEST_INIT(state); flint_printf("gcd_heuristic...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-gcd_modular.c000066400000000000000000000156231414523752600206260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.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. */ static int _t_gcd_is_canonical(const fmpz_poly_t poly) { return fmpz_poly_is_zero(poly) || (fmpz_sgn(fmpz_poly_lead(poly)) > 0); } int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd_modular...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(d); fmpz_poly_clear(e); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-gcd_subresultant.c000066400000000000000000000067021414523752600217140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd_subresultant...."); fflush(stdout); /* 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-get_coeff_ptr.c000066400000000000000000000030061414523752600211440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get_coeff_ptr...."); fflush(stdout); 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); abort(); } fmpz_poly_clear(A); fmpz_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-get_nmod_poly.c000066400000000000000000000031031414523752600211730ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("get/set_nmod_poly...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(A); nmod_poly_clear(M); nmod_poly_clear(M2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-get_set_coeff_fmpz.c000066400000000000000000000032531414523752600221720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("get/set_coeff_fmpz...."); fflush(stdout); 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); abort(); } } fmpz_clear(x1); fmpz_clear(x2); fmpz_poly_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-get_set_coeff_mpz.c000066400000000000000000000035341414523752600220260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("get/set_coeff_mpz...."); fflush(stdout); for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a; fmpz_t x1, x2; mpz_t y1, y2; slong coeff, len; fmpz_poly_init(a); fmpz_init(x1); fmpz_init(x2); mpz_init(y1); mpz_init(y2); len = n_randint(state, 100) + 1; for (j = 0; j < 1000; j++) { fmpz_randtest(x1, state, 200); fmpz_get_mpz(y1, x1); coeff = n_randint(state, len); fmpz_poly_set_coeff_mpz(a, coeff, y1); fmpz_poly_get_coeff_mpz(y2, a, coeff); fmpz_set_mpz(x2, y2); 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); abort(); } } fmpz_clear(x1); fmpz_clear(x2); mpz_clear(y1); mpz_clear(y2); fmpz_poly_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-get_set_coeff_si.c000066400000000000000000000026671414523752600216410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("get/set_coeff_si...."); fflush(stdout); 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); abort(); } } fmpz_poly_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-get_set_coeff_ui.c000066400000000000000000000026361414523752600216370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("get/set_coeff_ui...."); fflush(stdout); 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); abort(); } } fmpz_poly_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-get_set_str.c000066400000000000000000000027501414523752600206650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get_set_str...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); flint_free(str); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-get_str.c000066400000000000000000000034051414523752600200100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int result; char *str; fmpz_poly_t a; FLINT_TEST_INIT(state); flint_printf("get_str...."); fflush(stdout); 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); 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); 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); abort(); } flint_free(str); fmpz_poly_clear(a); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-get_str_pretty.c000066400000000000000000000034471414523752600214250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int result; char *str; fmpz_poly_t a; FLINT_TEST_INIT(state); flint_printf("get_str_pretty...."); fflush(stdout); 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); 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); 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); abort(); } flint_free(str); fmpz_poly_clear(a); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-hensel_lift.c000066400000000000000000000127361414523752600206440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("hensel_lift...."); fflush(stdout); /* 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, FLINT_BITS - 2))); 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, FLINT_BITS - 2))); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-hensel_lift_once.c000066400000000000000000000063471414523752600216510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("hensel_lift_once...."); fflush(stdout); /* 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-hensel_lift_without_only_inverse.c000066400000000000000000000131431414523752600252140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("hensel_lift_without_only_inverse...."); fflush(stdout); /* 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, FLINT_BITS - 2))); 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, FLINT_BITS - 2))); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-hensel_start_continue_lift.c000066400000000000000000000104751414523752600237630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "mpn_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("hensel_start_continue_lift...."); fflush(stdout); /* 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-hermite_h.c000066400000000000000000000030361414523752600203050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" int main() { fmpz_poly_t T0, T1, t1, t2; slong n; FLINT_TEST_INIT(state); flint_printf("hermite_h...."); fflush(stdout); 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"); abort(); } fmpz_poly_swap(T0, T1); } fmpz_poly_clear(T0); fmpz_poly_clear(T1); fmpz_poly_clear(t1); fmpz_poly_clear(t2); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-hermite_he.c000066400000000000000000000030171414523752600204510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" int main() { fmpz_poly_t T0, T1, t1, t2; slong n; FLINT_TEST_INIT(state); flint_printf("hermite_he...."); fflush(stdout); 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"); abort(); } fmpz_poly_swap(T0, T1); } fmpz_poly_clear(T0); fmpz_poly_clear(T1); fmpz_poly_clear(t1); fmpz_poly_clear(t2); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-inflate.c000066400000000000000000000043701414523752600177650ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("inflate...."); fflush(stdout); 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"); 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"); flint_abort(); } fmpz_poly_clear(poly1); fmpz_poly_clear(poly2); fmpz_poly_clear(poly3); fmpz_poly_clear(xp); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-init_realloc_clear.c000066400000000000000000000024631414523752600221560ustar00rootroot00000000000000/* 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 2.1 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" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/init2/realloc/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-interpolate_fmpz_vec.c000066400000000000000000000033751414523752600225660ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("interpolate_fmpz_vec...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(P); fmpz_poly_clear(Q); _fmpz_vec_clear(x, npoints); _fmpz_vec_clear(y, npoints); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-inv_series.c000066400000000000000000000051251414523752600205100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("inv_series...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(one); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-inv_series_basecase.c000066400000000000000000000053721414523752600223420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("inv_series_basecase...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(one); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-inv_series_newton.c000066400000000000000000000051521414523752600221020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("inv_series_newton...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(one); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-is_cyclotomic.c000066400000000000000000000046341414523752600212060ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_cyclotomic...."); fflush(stdout); /* 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); 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); 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); abort(); } } fmpz_poly_clear(f); fmpz_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-is_squarefree.c000066400000000000000000000056401414523752600212010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_squarefree...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(f); fmpz_clear(N); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-lcm.c000066400000000000000000000071641414523752600171220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("lcm...."); fflush(stdout); /* 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly/test/t-legendre_pt.c000066400000000000000000000033511414523752600206310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" int main() { fmpz_poly_t T0, T1, T2, t, tt; slong n; FLINT_TEST_INIT(state); flint_printf("legendre_pt...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mul.c000066400000000000000000000130541414523752600171370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; int tmul = 200; #ifdef _WIN32 tmul = 1; #endif FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mul_KS.c000066400000000000000000000136121414523752600175340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_KS...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mul_SS.c000066400000000000000000000127651414523752600175540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_SS...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mul_SS_precache.c000066400000000000000000000051131414523752600213730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_SS_precache...."); fflush(stdout); /* 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"); 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"); abort(); } } fmpz_poly_mul_precache_clear(pre); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mul_classical.c000066400000000000000000000112601414523752600211520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_classical...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mul_karatsuba.c000066400000000000000000000112021414523752600211650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_karatsuba...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mulhigh_classical.c000066400000000000000000000071431414523752600220170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulhigh_classical...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mulhigh_karatsuba_n.c000066400000000000000000000064341414523752600223550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulhigh_karatsuba_n...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mulhigh_n.c000066400000000000000000000033761414523752600203220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulhigh_n...."); fflush(stdout); /* 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mullow.c000066400000000000000000000045551414523752600176670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mullow_KS.c000066400000000000000000000067741414523752600202710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow_KS...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mullow_SS.c000066400000000000000000000067661414523752600203020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow_SS...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mullow_SS_precache.c000066400000000000000000000056641414523752600221300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow_SS_precache...."); fflush(stdout); /* 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"); 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"); abort(); } } fmpz_poly_mul_precache_clear(pre); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mullow_classical.c000066400000000000000000000070551414523752600217030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow_classical...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mullow_karatsuba_n.c000066400000000000000000000062561414523752600222410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow_karatsuba_n...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-mulmid_classical.c000066400000000000000000000072211414523752600216460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulmid_classical...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-neg.c000066400000000000000000000026131414523752600171120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-newton_to_monomial.c000066400000000000000000000032141414523752600222460ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("newton_to_monomial...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); _fmpz_vec_clear(r, n); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-num_real_roots.c000066400000000000000000000036621414523752600213760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" int main() { int iter; FLINT_TEST_INIT(state); printf("num_real_roots...."); /* 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"); 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"); abort(); } fmpz_poly_clear(p); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-num_real_roots_sturm.c000066400000000000000000000057271414523752600226340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" #include "fmpq_vec.h" int main() { int iter; FLINT_TEST_INIT(state); printf("num_real_roots_sturm...."); /* 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"); 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"); 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"); abort(); } } _fmpq_vec_clear(vec, n); fmpz_poly_clear(p); fmpz_poly_clear(q); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-pow.c000066400000000000000000000051061414523752600171460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-pow_addchains.c000066400000000000000000000046141414523752600211470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow_addchains...."); fflush(stdout); /* 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"); 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"); abort(); } } fmpz_poly_clear(a); fmpz_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-pow_binexp.c000066400000000000000000000044751414523752600205230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow_binexp...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-pow_binomial.c000066400000000000000000000047731414523752600210310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow_binomial...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-pow_multinomial.c000066400000000000000000000045221414523752600215610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow_multinomial...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-pow_trunc.c000066400000000000000000000052621414523752600203640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow_trunc...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly/test/t-power_sums.c000066400000000000000000000157541414523752600205560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" int main(void) { int i, j, k, l, result; fmpz_t il, jl, kl, tot; slong n; fmpz_poly_t a, b, c, d, e, f; FLINT_TEST_INIT(state); flint_printf("power_sums...."); /* 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"); 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); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-primitive_part.c000066400000000000000000000043401414523752600213760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("primitive_part...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(c); fmpz_poly_clear(f); fmpz_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-print_read.c000066400000000000000000000141531414523752600204720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ #undef __STRICT_ANSI__ #endif #include #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) #include #endif #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) int main(void) { int i, j, n = 1000, result; FILE *in, *out; int fd[2]; pid_t childpid; FLINT_TEST_INIT(state); flint_printf("print/ read...."); fflush(stdout); /* 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"); abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); 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"); 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"); 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"); 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"); 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"); abort(); } ++i; } fmpz_poly_clear(t); fclose(in); } if (i != n) { flint_printf("FAIL:\n"); flint_printf("Only %d out of %d objects were processed.\n", i, n); 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"); abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); 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"); abort(); } r = flint_fprintf(out, "blah"); if (r <= 0) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); 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"); 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); abort(); } ++i; } fmpz_poly_clear(t); fclose(in); } /* 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); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #else int main(void) { flint_printf("print/ read...."); fflush(stdout); flint_printf("SKIPPED\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fmpz_poly/test/t-print_read_pretty.c000066400000000000000000000151541414523752600221030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ /* try to get fdopen declared */ #if defined __STRICT_ANSI__ #undef __STRICT_ANSI__ #endif #include #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) #include #endif #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) int main(void) { int i, j, n = 1000, result; FILE *in, *out; int fd[2]; pid_t childpid; FLINT_TEST_INIT(state); flint_printf("print/ read_pretty...."); fflush(stdout); /* 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"); abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); 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"); 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"); 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"); 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"); 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); abort(); } flint_free(rvar); ++i; } fmpz_poly_clear(t); fclose(in); } if (i != n) { flint_printf("FAIL:\n"); flint_printf("Only %d out of %d objects were processed.\n", i, n); 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"); abort(); } if((childpid = fork()) == -1) { flint_printf("FAIL:\n"); flint_printf("Failed to fork the process.\n"); 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"); abort(); } r = fputs(str, out); if (r == EOF) { flint_printf("FAIL:\n"); flint_printf("Write error.\n"); 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"); 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"); abort(); } if (rvar) flint_free(rvar); } fmpz_poly_clear(t); fclose(in); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #else int main(void) { flint_printf("print/ read...."); fflush(stdout); flint_printf("SKIPPED\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fmpz_poly/test/t-product_roots_fmpq_vec.c000066400000000000000000000036111414523752600231260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" #include "fmpq_vec.h" int main() { slong iter; FLINT_TEST_INIT(state); printf("product_roots_fmpq_vec...."); 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"); 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"); abort(); } } fmpq_clear(res); _fmpq_vec_clear(vec, n); fmpz_poly_clear(p); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-product_roots_fmpz_vec.c000066400000000000000000000035101414523752600231350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("product_roots_fmpz_vec...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(P); fmpz_poly_clear(Q); fmpz_poly_clear(tmp); _fmpz_vec_clear(x, n); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-pseudo_div.c000066400000000000000000000070021414523752600204770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pseudo_div...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-pseudo_divrem_basecase.c000066400000000000000000000131321414523752600230320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pseudo_divrem_basecase...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-pseudo_divrem_cohen.c000066400000000000000000000134321414523752600223630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pseudo_divrem_cohen...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-pseudo_divrem_divconquer.c000066400000000000000000000134601414523752600234470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pseudo_divrem_divconquer...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(q); fmpz_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-pseudo_rem.c000066400000000000000000000066111414523752600205050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pseudo_rem...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-pseudo_rem_cohen.c000066400000000000000000000066241414523752600216650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pseudo_rem_cohen...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-randtest_no_real_root.c000066400000000000000000000037641414523752600227370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.h" int main() { int iter; FLINT_TEST_INIT(state); printf("randtest_no_real_root...."); 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"); 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); 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"); abort(); } fmpz_poly_clear(p); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-rem_basecase.c000066400000000000000000000065231414523752600207560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("rem_basecase...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-rem_powers_precomp.c000066400000000000000000000076671414523752600222660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("rem_powers_precomp...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(b_inv); fmpz_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-remove.c000066400000000000000000000107501414523752600176370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("remove...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(p); fmpz_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-remove_content_2exp.c000066400000000000000000000035621414523752600223320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" int main() { int iter; FLINT_TEST_INIT(state); flint_printf("remove_content_2exp...."); fflush(stdout); 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"); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g1); fmpz_poly_clear(g2); fmpz_poly_clear(g3); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-resultant.c000066400000000000000000000061731414523752600203670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("resultant...."); fflush(stdout); /* 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-resultant_euclidean.c000066400000000000000000000062551414523752600224010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("resultant_euclidean...."); fflush(stdout); /* 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-resultant_modular.c000066400000000000000000000063201414523752600221040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("resultant_modular...."); fflush(stdout); /* 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-resultant_modular_div.c000066400000000000000000000103441414523752600227470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("resultant_modular_div...."); fflush(stdout); /* 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-reverse.c000066400000000000000000000050101414523752600200060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("reverse...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-revert_series.c000066400000000000000000000053771414523752600212340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revert_series...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-revert_series_lagrange.c000066400000000000000000000054671414523752600230740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revert_series_lagrange...."); fflush(stdout); /* Check aliasing */ for (i = 0; i < 10 * 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_lagrange(f, g, n); fmpz_poly_revert_series_lagrange(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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); } /* Check f(f^(-1)) = id */ 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, 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_lagrange(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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-revert_series_lagrange_fast.c000066400000000000000000000055131414523752600241010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revert_series_lagrange_fast...."); fflush(stdout); /* Check aliasing */ for (i = 0; i < 10 * 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_lagrange_fast(f, g, n); fmpz_poly_revert_series_lagrange_fast(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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); } /* Check f(f^(-1)) = id */ 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, 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_lagrange_fast(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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-revert_series_newton.c000066400000000000000000000054571414523752600226250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revert_series_newton...."); fflush(stdout); /* Check aliasing */ for (i = 0; i < 10 * 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_newton(f, g, n); fmpz_poly_revert_series_newton(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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); } /* Check f(f^(-1)) = id */ 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, 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_newton(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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-scalar_abs.c000066400000000000000000000026671414523752600204440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_abs...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-scalar_addmul_fmpz.c000066400000000000000000000066641414523752600222020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_addmul_fmpz...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_clear(x); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-scalar_divexact_mpz.c000066400000000000000000000041341414523752600223630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_divexact_mpz...."); fflush(stdout); /* Compare with fmpz_poly_scalar_divexact_fmpz */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_t n; mpz_t n1; fmpz_init(n); mpz_init(n1); do { fmpz_randtest(n, state, 200); } while (fmpz_is_zero(n)); fmpz_get_mpz(n1, 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_scalar_mul_fmpz(a, a, n); fmpz_poly_scalar_divexact_fmpz(b, a, n); fmpz_poly_scalar_divexact_mpz(c, a, n1); 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"); abort(); } /* aliasing */ fmpz_poly_scalar_divexact_mpz(a, a, n1); 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"); abort(); } mpz_clear(n1); fmpz_clear(n); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-scalar_fdiv_mpz.c000066400000000000000000000041101414523752600214760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_fdiv_mpz...."); fflush(stdout); /* Compare with fmpz_poly_scalar_fdiv_fmpz */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_t n; mpz_t n1; fmpz_init(n); mpz_init(n1); do { fmpz_randtest(n, state, 200); } while (fmpz_is_zero(n)); fmpz_get_mpz(n1, 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_scalar_mul_fmpz(a, a, n); fmpz_poly_scalar_fdiv_fmpz(b, a, n); fmpz_poly_scalar_fdiv_mpz(c, a, n1); 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"); abort(); } /* aliasing */ fmpz_poly_scalar_fdiv_mpz(a, a, n1); 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"); abort(); } mpz_clear(n1); fmpz_clear(n); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-scalar_mul_fmpz.c000066400000000000000000000044741414523752600215260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpz...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(n1); fmpz_poly_clear(a); fmpz_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-scalar_mul_mpz.c000066400000000000000000000037431414523752600213560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_mpz...."); fflush(stdout); /* Compare with fmpz_poly_scalar_mul_fmpz */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_t n; mpz_t n1; fmpz_init(n); mpz_init(n1); fmpz_randtest(n, state, 200); fmpz_get_mpz(n1, 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_scalar_mul_fmpz(b, a, n); fmpz_poly_scalar_mul_mpz(c, a, n1); 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"); abort(); } /* aliasing */ fmpz_poly_scalar_mul_mpz(a, a, n1); 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"); abort(); } mpz_clear(n1); fmpz_clear(n); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-scalar_mul_si.c000066400000000000000000000062401414523752600211560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_si...."); fflush(stdout); /* 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"); 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"); 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, (FLINT_BITS - 2) / 2); slong n2 = (slong) n_randbits(state, (FLINT_BITS - 2) / 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-scalar_mul_ui.c000066400000000000000000000044701414523752600211630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_ui...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-scalar_submul_fmpz.c000066400000000000000000000057021414523752600222330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_submul_fmpz...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(x); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-scale_2exp.c000066400000000000000000000062761414523752600203770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.h" int main() { int iter; FLINT_TEST_INIT(state); flint_printf("scale_2exp...."); fflush(stdout); /* 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"); 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"); 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"); flint_abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_clear(a1); fmpz_clear(a2); fmpz_clear(res1); fmpz_clear(res2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-set_equal.c000066400000000000000000000042501414523752600203220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set/equal...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(x1); fmpz_clear(x2); fmpz_poly_clear(a); fmpz_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-set_fmpz_equal.c000066400000000000000000000046631414523752600213660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_fmpz_equal...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_clear(m); fmpz_clear(n); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-set_mpz_equal.c000066400000000000000000000047041414523752600212140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; gmp_randstate_t state; FLINT_TEST_INIT(dummy); flint_printf("set_mpz_equal...."); fflush(stdout); gmp_randinit_default(state); gmp_randseed_ui(state, 23); /* equal polynomials */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; mpz_t n; fmpz_poly_init(a); fmpz_poly_init(b); mpz_init(n); mpz_rrandomb(n, state, 200); fmpz_poly_set_mpz(a, n); fmpz_poly_set(b, a); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); gmp_printf("n = %Zd\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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); mpz_clear(n); } for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_poly_t a, b; mpz_t m, n; fmpz_poly_init(a); fmpz_poly_init(b); mpz_init(m); mpz_init(n); mpz_rrandomb(m, state, 200); mpz_rrandomb(n, state, 200); while (mpz_cmp(m, n) == 0) mpz_rrandomb(n, state, 200); fmpz_poly_set_mpz(a, m); fmpz_poly_set_mpz(b, n); result = (!fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); gmp_printf("m = %Zd\n\n", m); gmp_printf("n = %Zd\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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); mpz_clear(m); mpz_clear(n); } gmp_randclear(state); FLINT_TEST_CLEANUP(dummy); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-set_si_equal.c000066400000000000000000000043041414523752600210150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_si_equal...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-set_trunc.c000066400000000000000000000035301414523752600203460ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_trunc...."); fflush(stdout); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-set_ui_equal.c000066400000000000000000000042531414523752600210220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_ui_equal...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-shift_left_right.c000066400000000000000000000057011414523752600216660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("shift_left/right...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-signature.c000066400000000000000000000112121414523752600203350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("signature...."); fflush(stdout); 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); 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); 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); abort(); } fmpz_poly_clear(poly); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-sqr.c000066400000000000000000000063231414523752600171500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqr...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-sqr_KS.c000066400000000000000000000077621414523752600175550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqr_KS...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-sqr_classical.c000066400000000000000000000042321414523752600211630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqr_classical...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-sqr_karatsuba.c000066400000000000000000000064541414523752600212120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqr_karatsuba...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-sqrlow.c000066400000000000000000000045761414523752600177020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrlow...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly/test/t-sqrlow_KS.c000066400000000000000000000046201414523752600202650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrlow_KS...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly/test/t-sqrlow_classical.c000066400000000000000000000046751414523752600217200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrlow_classical...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly/test/t-sqrlow_karatsuba_n.c000066400000000000000000000047021414523752600222430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrlow_karatsuba_n...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly/test/t-sqrt.c000066400000000000000000000106721414523752600173360ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("sqrt... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } } fmpz_clear(t); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_poly/test/t-sqrt_KS.c000066400000000000000000000110751414523752600177310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("sqrt_KS... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } } fmpz_clear(t); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_poly/test/t-sqrt_classical.c000066400000000000000000000110241414523752600213440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("sqrt_classical... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } } fmpz_clear(t); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_poly/test/t-sqrt_divconquer.c000066400000000000000000000110341414523752600215660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("sqrt_divconquer... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } } fmpz_clear(t); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_poly/test/t-sqrt_series.c000066400000000000000000000105201414523752600207000ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("sqrt_series... "); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } } fmpz_clear(t); fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_poly/test/t-sqrtrem_classical.c000066400000000000000000000150051414523752600220530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("sqrtrem_classical... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(r1); fmpz_poly_clear(r2); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_poly/test/t-sqrtrem_divconquer.c000066400000000000000000000150161414523752600222760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("sqrtrem_divconquer... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(r1); fmpz_poly_clear(r2); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fmpz_poly/test/t-sub.c000066400000000000000000000063111414523752600171310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-sub_series.c000066400000000000000000000070011414523752600205000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub_series...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-swap.c000066400000000000000000000027171414523752600173200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("swap...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-swinnerton_dyer.c000066400000000000000000000024201414523752600215660ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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) }; int main() { fmpz_poly_t S; mp_limb_t r; slong n; FLINT_TEST_INIT(state); flint_printf("swinnerton_dyer...."); fflush(stdout); 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); abort(); } fmpz_poly_clear(S); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-taylor_shift.c000066400000000000000000000050731414523752600210530ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("taylor_shift...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h1); fmpz_poly_clear(h2); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-taylor_shift_divconquer.c000066400000000000000000000041331414523752600233060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("taylor_shift_divconquer...."); fflush(stdout); /* 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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h1); fmpz_poly_clear(h2); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-taylor_shift_horner.c000066400000000000000000000100661414523752600224260ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.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); } int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("taylor_shift_horner...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(h1); fmpz_poly_clear(h2); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-taylor_shift_multi_mod_threaded.c000066400000000000000000000057341414523752600247700ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i; #endif FLINT_TEST_INIT(state); flint_printf("taylor_shift_multi_mod...."); fflush(stdout); #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"); 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"); abort(); } fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(h1); fmpz_poly_clear(h2); fmpz_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; #else FLINT_TEST_CLEANUP(state); flint_printf("SKIPPED\n"); return 0; #endif } flint2-2.8.4/fmpz_poly/test/t-theta_qexp.c000066400000000000000000000033471414523752600205100ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("theta_qexp...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly/test/t-xgcd_modular.c000066400000000000000000000211321414523752600210060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("xgcd_modular...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); abort(); } fmpz_clear(r); fmpz_poly_clear(d); fmpz_poly_clear(f); fmpz_poly_clear(g); fmpz_poly_clear(s); fmpz_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-zero.c000066400000000000000000000023131414523752600173150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("zero...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/test/t-zero_coeffs.c000066400000000000000000000025711414523752600206500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("zero_coeffs...."); fflush(stdout); /* 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"); abort(); } fmpz_poly_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly/theta_qexp.c000066400000000000000000000046051414523752600172660ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_poly/xgcd_modular.c000066400000000000000000000147761414523752600176060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "mpn_extras.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); } } } flint2-2.8.4/fmpz_poly/zero_coeffs.c000066400000000000000000000014071414523752600174250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.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); } } flint2-2.8.4/fmpz_poly_factor.h000066400000000000000000000127721414523752600164730ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPZ_POLY_FACTOR_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_mat.h" #include "nmod_poly.h" #ifdef __cplusplus extern "C" { #endif FLINT_DLL void fmpz_poly_factor_init(fmpz_poly_factor_t fac); FLINT_DLL void fmpz_poly_factor_init2(fmpz_poly_factor_t fac, slong alloc); FLINT_DLL void fmpz_poly_factor_realloc(fmpz_poly_factor_t fac, slong alloc); FLINT_DLL void fmpz_poly_factor_fit_length(fmpz_poly_factor_t fac, slong len); FLINT_DLL void fmpz_poly_factor_clear(fmpz_poly_factor_t fac); FLINT_DLL void fmpz_poly_factor_set(fmpz_poly_factor_t res, const fmpz_poly_factor_t fac); FLINT_DLL void fmpz_poly_factor_insert(fmpz_poly_factor_t fac, const fmpz_poly_t p, slong exp); FLINT_DLL void fmpz_poly_factor_concat(fmpz_poly_factor_t res, const fmpz_poly_factor_t fac); FLINT_DLL void fmpz_poly_factor_print(const fmpz_poly_factor_t fac); FLINT_DLL 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); FLINT_DLL void fmpz_poly_factor_squarefree(fmpz_poly_factor_t fac, const fmpz_poly_t F); FLINT_DLL void fmpz_poly_factor_mignotte(fmpz_t B, const fmpz_poly_t f); FLINT_DLL void _fmpz_poly_factor_zassenhaus(fmpz_poly_factor_t final_fac, slong exp, const fmpz_poly_t f, slong cutoff, int use_van_hoeij); FLINT_DLL void fmpz_poly_factor_zassenhaus(fmpz_poly_factor_t fac, const fmpz_poly_t G); FLINT_DLL void _fmpz_poly_factor_quadratic(fmpz_poly_factor_t fac, const fmpz_poly_t f, slong exp); FLINT_DLL void _fmpz_poly_factor_cubic(fmpz_poly_factor_t fac, const fmpz_poly_t f, slong exp); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fmpz_poly_factor(fmpz_poly_factor_t fac, const fmpz_poly_t G); /* Inlines *******************************************************************/ FLINT_DLL void fmpz_poly_factor_get_fmpz_poly(fmpz_poly_t z, const fmpz_poly_factor_t F, slong i); FLINT_DLL void fmpz_poly_factor_get_fmpz(fmpz_t z, const fmpz_poly_factor_t F); /* zassenhaus ****************************************************************/ FLINT_DLL void zassenhaus_subset_first(slong * s, slong r, slong m); FLINT_DLL int zassenhaus_subset_next(slong * s, slong r); FLINT_DLL 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; } FLINT_DLL void zassenhaus_prune_clear(zassenhaus_prune_t Z); FLINT_DLL 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; } FLINT_DLL void zassenhaus_prune_add_factor(zassenhaus_prune_t Z, slong deg, slong exp); FLINT_DLL void zassenhaus_prune_end_add_factors(zassenhaus_prune_t Z); FLINT_DLL 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]; } FLINT_DLL 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 flint2-2.8.4/fmpz_poly_factor/000077500000000000000000000000001414523752600163115ustar00rootroot00000000000000flint2-2.8.4/fmpz_poly_factor/CLD_mat.c000066400000000000000000000073741414523752600177330ustar00rootroot00000000000000/* 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 2.1 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_mat.h" #include "fmpz_mod_poly.h" 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; } flint2-2.8.4/fmpz_poly_factor/clear.c000066400000000000000000000014761414523752600175530ustar00rootroot00000000000000/* 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 2.1 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_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)); } flint2-2.8.4/fmpz_poly_factor/concat.c000066400000000000000000000015431414523752600177270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_poly.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]); } flint2-2.8.4/fmpz_poly_factor/factor.c000066400000000000000000000063221414523752600177360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_poly.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); } flint2-2.8.4/fmpz_poly_factor/factor_cubic.c000066400000000000000000000474541414523752600211160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_fdiv_ui(a, ctx.n); B = fmpz_fdiv_ui(b, ctx.n); 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); } flint2-2.8.4/fmpz_poly_factor/factor_quadratic.c000066400000000000000000000031731414523752600217740ustar00rootroot00000000000000/* Copyright (C) 2020 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_poly_factor/factor_squarefree.c000066400000000000000000000040521414523752600221560ustar00rootroot00000000000000/* 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 2.1 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_factor_squarefree(fmpz_poly_factor_t fac, const fmpz_poly_t F) { fmpz_poly_content(&(fac->c), F); if (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_div(v, f, d); fmpz_poly_div(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_div(v, v, d); fmpz_poly_div(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); } } flint2-2.8.4/fmpz_poly_factor/factor_van_hoeij.c000066400000000000000000000151451414523752600217630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_lll.h" #include "fmpz_poly.h" 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); } flint2-2.8.4/fmpz_poly_factor/factor_zassenhaus.c000066400000000000000000000201041414523752600221740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_poly.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 e.g., Cohen p.\ 134. 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$. */ 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 flint2-2.8.4/fmpz_poly_factor/factor_zassenhaus_recombination.c000066400000000000000000000144711414523752600251170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_poly.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); } flint2-2.8.4/fmpz_poly_factor/fit_length.c000066400000000000000000000013341414523752600206010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.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); } } flint2-2.8.4/fmpz_poly_factor/init.c000066400000000000000000000022411414523752600174170ustar00rootroot00000000000000/* 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 2.1 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_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; } flint2-2.8.4/fmpz_poly_factor/inlines.c000066400000000000000000000014561414523752600201240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_POLY_FACTOR_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "fmpz_poly.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)); } flint2-2.8.4/fmpz_poly_factor/insert.c000066400000000000000000000020101414523752600177520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.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; } flint2-2.8.4/fmpz_poly_factor/print.c000066400000000000000000000015601414523752600176130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_poly.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]); } } flint2-2.8.4/fmpz_poly_factor/profile/000077500000000000000000000000001414523752600177515ustar00rootroot00000000000000flint2-2.8.4/fmpz_poly_factor/profile/p-factor_quadratic_cubic.c000066400000000000000000000240441414523752600250360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.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; } flint2-2.8.4/fmpz_poly_factor/realloc.c000066400000000000000000000035531414523752600201040ustar00rootroot00000000000000/* 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 2.1 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_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; } } flint2-2.8.4/fmpz_poly_factor/set.c000066400000000000000000000022271414523752600172530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fmpz_poly.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; } } } flint2-2.8.4/fmpz_poly_factor/test/000077500000000000000000000000001414523752600172705ustar00rootroot00000000000000flint2-2.8.4/fmpz_poly_factor/test/C1_flint000066400000000000000000000333741414523752600206640ustar00rootroot000000000000001025 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 flint2-2.8.4/fmpz_poly_factor/test/H1_flint000066400000000000000000006077341414523752600207000ustar00rootroot00000000000000961 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 flint2-2.8.4/fmpz_poly_factor/test/H2_flint000066400000000000000000000200551414523752600206620ustar00rootroot000000000000004097 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 flint2-2.8.4/fmpz_poly_factor/test/M12_5_flint000066400000000000000000023534211414523752600212040ustar00rootroot00000000000000793 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 flint2-2.8.4/fmpz_poly_factor/test/M12_6_flint000066400000000000000000036011261414523752600212040ustar00rootroot00000000000000925 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 flint2-2.8.4/fmpz_poly_factor/test/P1_flint000066400000000000000000000144251414523752600206750ustar00rootroot00000000000000157 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 flint2-2.8.4/fmpz_poly_factor/test/P2_flint000066400000000000000000000157171414523752600207030ustar00rootroot00000000000000197 -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 flint2-2.8.4/fmpz_poly_factor/test/P3_flint000066400000000000000000000425011414523752600206730ustar00rootroot00000000000000337 -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 flint2-2.8.4/fmpz_poly_factor/test/P4_flint000066400000000000000000006613211414523752600207030ustar00rootroot00000000000000463 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 flint2-2.8.4/fmpz_poly_factor/test/P5_flint000066400000000000000000000020151414523752600206710ustar00rootroot0000000000000065 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 flint2-2.8.4/fmpz_poly_factor/test/P6_flint000066400000000000000000000164651414523752600207100ustar00rootroot00000000000000145 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 flint2-2.8.4/fmpz_poly_factor/test/P7_flint000066400000000000000000000176031414523752600207040ustar00rootroot00000000000000385 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 flint2-2.8.4/fmpz_poly_factor/test/P8_flint000066400000000000000000000433361414523752600207070ustar00rootroot00000000000000973 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 flint2-2.8.4/fmpz_poly_factor/test/S10_flint000066400000000000000000011055151414523752600207620ustar00rootroot000000000000001025 435674500151429552033580649774189976987857299371616614314771969496916262908188381873136311175130150614817306293260335979363125662910934466774413044140006317929245283364806885699104133657167622402816511193429406570687469532954743393847953934758415746514765637827333796443784728519442615538247848091209265184549301263908052638305534959247423159286804423120836628427053683260660894653042827863797261812856379945889754260958984211716421106758775793642793378411796879805783756984234297797880509006504135482460138715176453610735650939769402336808201247068224935535303736279149031837547427183579629017430057770414933542218227865898500877229542639411260415944877078244362579634264220976459810020826273664290944298841935340864934697113749089910657885737866287217484390606009683251216844993678032617406904697418212890625 0 -1668630662372534578165219948454740423263432210156757446288509300894477535560042553527388507978615740978985964469741022165027121080717177828101385724643039177121639219009210233961617511011967286190067918239558642208805803649565747254431562726732993641769678471506044462088261078528698922189975440860726060690786610652901779004017080366158427376062942045168643214696862963477999344834079820837936023777536789516090379231101463389087054038775235372950631154344347253813341090708495763539672765693654048638173839616261490454712926143866733834385772912040416336530488029628331475401754141649060518626042082835996785159823204526104115068138549813885352069456014581673764692994736275626893712903560990894703228883217317435365492311278347336917761423385114245231569024003298932346440302990948287664121563720703125000000000 0 2067719862872061860019516153157994758832954828953975635679658874571303819781891134956617013123210035520036241446851796820520490051186820764201733966232407670629412559419599541986406260418012729915306114315522329143274867916370828977253114482933984004293907376384185691517548934554473760406701054287191906299471667323262707464531818006791782154263396496762943189800065036150636588554819726251560463589140746104686783155585596101227909967000731188458005836588125930377566909491376893874124674222853848451165295141741868263885239164238025784429747152992462252428506437809247166392336010092616994183098666913252990204255505489677520734101425716796403091619902676838153096040654820129037054709541235739737573426115870271617552562424864218739360009003645524627398658507153964970751899623819925523584819013061523437500000000 0 -975733990189353672370619023365765586940271521118362567187929863474760425076311553820413589940017833783735920126867100612219369411275375177856359495176408417484023875242712804035053541436724681580905647535235911076580106106548831510680684378767939268654720146182730227351031841629790827020257577078177272746178141787158397047794457014263162369759403528448988419412486851094665755421717071981423013607403446151253984493445574783183618650751196136926086225743056600570852046835253896040902378272325778856307355974287624364661336871383178183291655995437404743530851913484600273647466494683508948036836503306982119616481888836289679325553558064721314767134408607471696375735677740066721105675725625862084852413677931647375162708834035742388642104827217541811771151366282540455341080202430711331326447341886474609375000000000 0 228638558581718490552374120477525561485327076535854349597719076669167149860038773500391206639559913814289237364038541040588529111712517161918530950430296161570132428304665764937287277506349693114056144032643552555469474914011345100501238615021198236714083284225303979023787909528374666909670804866830037991477673250705129794596207970696346919560448933287889540630537018966989855652895871750853797660549947092816464739880395530457260794975756505076975533689317593872307546405020043663088497059773616164860544283055668297027061993018562971134396597946299417033709304776598261780479981259989239333921141887179935810054777683283247882797130190815563236976442943738885315674298302568500468362809309028894171800350498576535092246573166811518418835816282341346721317515736208032805211011425645162045555197755003503417968750000000 0 -31431248216203818531922017384682116762481536576994622218603941200636823701199232485431971229953310576108981384505774813309112520052296914101211558916734201021437845987579211628035681545809608240120163943182538061742712087555084069577935132130707924750210929664757071408194005413008405391173593578511474567925169684494089089835852549026440543152931486034032182506996359797748345476321465266356547377482855248577067600750404486345558198757436977459706553701854475764999506283483383946432966521583066474245863683414669581463790411060317085171154010020281886028195202423087706105530923020549549968855980309960450970028175127615621099098172909637992375669394284371318612343132297667120145918711870485654208117046630233104988244341273968871879461942454869911146373970333708323302177831381794824006419231724696566962890625000000000 0 2840730250178029129682245173518965995771282437147023034195199353131819492271677901327621212439944238263052183108784327723685852803078600662175554419106567752685748134837894984113910584063565784675892067377468930221778995783008112300624279241099842903131255394613763866476015593032775179318705572942776976642042661281733300807425460979946375947190165364613844361145538252588475249027778819006924973873792980588840741084269024965321969210592660486439053593159592158691225225364752244776706414927163715695628750830865780434625603569317335542104620840013309576538386299217762620528675127740331575269299029629966250859491355480810631625271665192333684795103892725711027957657864493201926380394597249603345051307665062493357629832351845247268978647811105115165885753063886966635169037558900880166347696488917162996036132812500000000 0 -182160891421652601173790755155566130640752211708715105570691723456100697014933688041938079132106995844600133412348333359935220332592553272599221525382241193654738618712950225148640666925763705584843816147080017416682350255332708140552292524264677760935683516934126108950852202788497279687044063596887209085576572906864221050705375845333603392472788436633355630970156830278056838302583231157398376414522337317269348443343051318096258903561776128949230350465889531139396810525083799933627920908466081836244590037825296021461896804203634380069830736485260148988447437020838133929856384750610543835930049183141546057850819453249908077928514550487799786692520805660062942971992446077254431208243535555399664215792167146842720475655489462565208771867092753354754636157532963912578815432683760727153343291260543069951041796875000000000 0 8738885594365711114194526362633476268042299589842724022498318571941894226104348095883574591597197506566663335457350384091439071129691370181976159771365185119092925979518436534812808489548814194920342459755750244638468482073118690017837621849622693918334035837471172057517874355168035874727602887288141161293543953724124615765575421665256540156501328591981085016537246877226115875475621282584555070270472390580500142032885081625608085374623762562720113336970214618080677018915325466844951298524742960443578643480659330617352849762963693648936245037606146690599515044906216681527602724770385290646527139111019769928135937238690631693381144554660884341013426847486602285759958848430053729126714364201585065070836980226872802380184080386606281753053630783083620700082490608079054765181687754924128134576621182613714401552734375000000 0 -325982955664451083654917919306338762632484587218701244757520370701289025005527523145836698872180250811947473593780547343193861919352199013223483335288137146908999726933586003073985435561977303543350203288918205206962298429958002027193736186740085874074520289166320767320765204165270626046808122436607478676487970983461105521627746803137513019271118549596917169214686096164071563276819572511195140172095856727128914579473437411167770593014657304818595422992590074082972811711395220867463686085777689916725111694239783344185883877148883772199324090491136229130511689161831908032171945696014678337270788983077240962741784104154278211444886723119594119585299325184730561202186958402968406653227092044887031488997315883536442263472380259693742589736000840217618014006224765493084451727428544952659295147185321966975594650578125000000000 0 9736031162037500595447111154214462188782239819305041497597217903706548972206619999877596480030557449870572884514915107496979749005301870734864646100600158247566760410912094040505411583482579907938703849929944450789593559386047578292178870017571439462632649653403233345042116205574125875604731471271748510263003105311008691099479809562567286446664556436104268938923958470027079760570942008062064302079994420084556762382427303871373982506866116910657845368412891245925296480307251012827977840914818373315522532260732200640067283957063571405814953988694937740494624444352481782485040232844534918982853253039078190412122370137998014129513152603347727392895707980916560885837750977594608303538055685188842917818203927379168076859237590404258071615446534892563415385095730223882495662895729693598919167597066753927282115909954687500000000 0 -238222054578243573509914445272423180634032361170730124583999964292762673802564535638244336535723921562143004056726776233743275993444852999426109838990389424642318454486246377569664637024254001548524922793121630835674102085501500354135804683023603644026702372047361582201990673580034963133557463393556695282153758326237754733355329807313675387947570225677686021531963590558288745971724704953564100545622962801958613718434532850875843159662236192877944300724435802673298587539138649879931064939695712315948776083458914413233215734446336991564675031381460185461870243359274083709938936745687731647395252812913945296525481996681257529082488975818309480884281035821530938499894207875895960697753984084490650860251214065562053341214770325355099782944631076135630468348249723073052638180975919229549574907018512063449496637261804375000000000 0 4864319703422912750620438535005239260947314058299152076799152046439630360950594349226305375807163125500141428999455716957722802440914437353827257252591911629875826377260020041064131292056846123921669257036044457812294414289966772442189999501111710960436082069133188334316908082722669340934822939221131743925084877883829168725770809487961921048941817231152682090882796846899729240653963553635168497007114592275746171124990260859883438095167277213185696051802584254706849666875643072796808596760509073138734753300644297948206760722822148997367724344964452793309256761542371032651991145120037098485354435298995043047561227374867433694133434794992615538622745177207361980154181238223659010743192693824908029921902114740911950546340431742810621532520718858780615361338982235984013439694764821074071752869226185381673775964934483656250000000 0 -84161515927918790574678385712286965848551820834720202776743963955116239971306207091763860759633200194711994775803516632264063601472881247578215867161405934408980378547644504566833416279864863741308508184089226955353643314894521240151930351404656550237651204826846123944824493731103808190480281476837903033756198139908200780861628425786752587420303080850422348097011862383224731567028007798089730753266996834130832153313083819044201951806111814613688100334760828234866586882272355397611631581176415612389420501248707541489595957871002544650558121119209174307475104624680455912604223874986097743044113826885276968677487808579445374852021867454876214326459783353666597137033014266949309331588341976895772180296327212345240327453414294178770487941240709757559840980503741191374193004985880988279964611815098331610060092970841954425000000000 0 1249686583225555164587427140265086298252606041730500858866954744500168620649138111602525989298012754168681944393766595579973793493686066652035174548998132871279968434323153141752749287129832996124789017522531719590909939283667393086456928826495524905174757356179530106841854445936857180003073305879467383814715576581755001508674747819500417331804464954949002178767564061929748640233386850177508218988129650533033693173694417789622128535058412296635132039199949559749091215418541914532369682085876508813114139410049979837224541798872310177294768209993765838113218713709294010695781880632426363804595160110655220050886513065515894657162065103346411123122738391433376717302908593044609233822339351854072356456031589534913569158435168317388085821483192574373280069731984485985536739205440297494136054746476665495490524721620774747902500000000 0 -16099255579630174207072917621564365903596050108010395307118522658144887244824535179770306003024499335438918036300075566547041159817234093539203427288036843982609960972656319548817662290694505402121488223475120904320698364770019709696742887668961730050291604058224215487417689098202840360948807657608633356627341123816877874077063717698249834988384144378844473681040012396872700826403138073765877998451571395554065707037533858095787987226862174020015154803766461546684311785842559815807018752795203671297477032879125036995962199495748846950737899348510374417211543663767221586239931510180706012085654880768299379406355003845334015892392021390299913627082132452079168789481500994264288710354714292612751288056853196162233688357841019546396477291469829225839945964453695220496553953094337241205812742609075604210181004370006806925507000000000 0 181634397022206486371600501878016570586889777437145257349210853534495520971738103246846736168396807721779576772515325463333130470245385492900516252444064391226605957827102512456825366461944158281598524452466719228933944854111492288655763798299629749923777712147275552023394412498304869658003433968615028110703283910283646705236437146565435765850544243923746190202717371397161573976410142034538413818606128796039572614715363685747489218592820095609784157690268691800741407713852642041968903251064113890262091855105630057666026361705844155194219875439545206280006319086683395799976893683011569369853739167738846800729520062053784228321067236077288125171611162547852190527635776096785873024159041062760133518393626996711947492833668838608679933784607089952797448499906722318179423773932717882965710437129144625126226065567604367074338787500000 0 -1809360547960855659998915804323641885073408648466674492027819606723780503263283086553938042116401671446667250542806024929446353601561304044209693346824834250426356307415190240252535917011380262394299624673099192719851885945664372600250017544906905946630706101087768923837077546813049703015702751017784002430616634666477178904089975230727564583440514293030592434685047926479787209241497213858884560646905684351721695153297810746830899995456181861309466995743520967407676865658264375744323977707215095070518859310947718264312345796091125645856368873645260254243057370262072669818664354143326491741636950799688910030289842706850018606257159711215169541808793787775430724241557607004508159354698307308089287431685249723110119268391733970564448850745270320744076935794880650844480086427693135876766915065985928258746729212912330190934124680000000 0 16028987901318128371789358843481865339763141963198188464214874901568296807119224424478329047650071335903814360516152960972788540476128897636304278616399557083605876870835780189666644907659569061280566596963444393471126549147584068705025921511962140317440615446854950861994674628632119628916350460084537652648949104261686575607184996856471482856781560338270436753425634883177697462727222468275667802229767275443196385712286397501132707269895876628752419585962931538864911142037064948713536276547610730983749288781545772873961189102713188745574194767174392696180527632247660620696560762161987325693705375153357591561563154326892267611264996717397311911694430195119901561218489810544854332318646190445733714632966350403602725088044579812647488087203833421951648979218242088820369542672037041488508892092760019662492947299544232740377118044000000 0 -127088342092466208401838112097576805279448270169638345170020848628805327770497787480503141060212932525502889473533413927642926900884482026167319810503157871106388510689831299396549570465789311446095679716431689309681320743917851401832187847971342610370502160716774300320502893137622653425149054257614254610364528220161493144236758525377331428029176513346185145130645364709319585992431123835479808154955591385517778496537495148992979235310574521787405418417432992326766438064308223819545762142164820180071815447991079487377494476513951352609364982410554071186457393454628010031087524797190159024223740062734064414291443546834380546594957554488791097403574953915309911106968339927474164643854107076034575283102690759518822835708778915058916177391878775916028886124340015964036899697934195152638197877987538669426435719983559693605234735819200000 0 906966608169203743147506894258225635749286291377074848592361784481190647475567454284396782534922953911955862765665024832522663566595897345990719000647271119586541628637919683673219500065760732637008394886911199788502279875499314934696237125602073208648544782803478773866496337584924743229745622292551970525696327411397327776902223860762662788469166869163708394823408256029707239944970967179888510384549385274055435091029153636180035927215304912246880864001652497922412076161437893098049009968334747899914150969686517476958989759975393644414718224417226186356624233835218029908049854976114460465782323717166583086434578409129996382481044438651293753128891765618387524544143351599433256250634679106439321816121210706653147585382184765010790832620325035270024141413488025395038803392218679710930526156914345989408395920896371301750365532440560000 0 -5855693635950207297259245318751550600907760661829867876309256507014486368111079296429211515200234129407949248987403091747812167232595207190000367543342424634088174687993449858942019031304885080609079133064492950788955157664388565888453701716116669477190337044891953063390401555102416689980193233660402957301586568180435288959294125826726815484196694869053913966124225290868427411377382755907007924363448957800758847766772830551374467373106655210747840645350308664131213968033855179153230038942410095757628808143198795169359557882225907803356161898193971666554924463641682182323851195706467897471607957106616341247113499814094686723028934107468005628890815742177893700978980512754995433557304053258335350450611111843652571248341405623495215717136742447456572621786887890363422003621830533601238727392739187568622423174081859542283655454795328000 0 34361106360149935661435089214457831321312222650654572017288029566817227308549663142684670173695236995634527076963026507641433510852016321694021221737685568184644175299875590289705118037837321167198054603492383198312292429884072845997875230638000528293614497694585566652664845099064930072345774168185827099510306360338006220476550732352621868469972084229018559170435523060621775039799118535347315669520797866320309899305842261012686996635202789555066505406179757430563016665313784694812881014258755124628302665668792667306976009234410657404401544284408069635071869626182447198674060151298288219918809981982376055564747572425276853762103488377924771195204643079507911478193298482150644784478979189923757376331833972852306169804642042531984815523382213506380423876930781595582707166317186831590743666538034203295779169359493103325382608353340294400 0 -184023213014737244201197840750339891800296795620247420246997329213906205690480305005640527963592636979785976489512447995608229691031862590039290429770283294854291481410408605495906983810652015919160047587940219151153010464387980819839286270771181630505737765180971088187516856508978467005231367485808679859251621638502728919411994561079420110430546191220877038353943052055469606074583374924405179976186431652240399400981355944463148564699871863122494650863407037106295752398624383341223969393077943611327352133089320176514457985644686436618294239872352329046068077661983000252027550774943925727239426526315010933394556184844971427421165400781549796808968888694039552148378285998031598929106636608261452176544595592029210844453576181698953059354765734644825332910041256142210777105651570263596347363274258528110791097731116716311388649962462891520 0 902919386880457038027029477893850226146691917474062869291563551910356479593829481809207061967152878183598049267442078134294940744920614628696766520714673713836787907258731168544657297271301138826946683894816830690446117133075887955996721435405049630605471218534468195162403418708090139510121276416405771774466039224134015520471236671215003602219372817602168072499446104914855147468040245821862566153941513063793085308679757533603225016427108089816728935090600443829914371379992960958315957709608193591319782421240635598585498317438436325709101878272719159082938758411568639478357268439694520538226939593520597406181167666817739614310491711677558281566499781482998130726536350101288525800633303972566368477927344036369626564305206404989189994932251966694829214372232708756512649744408000948554665404632253120563286729180532075342184535909801481536 0 -4072960951142217290509360989875812185004720244187599315747278453346191148189769051232767923428088184912766941671738492853036261011174377905552695279853868811258056111582067046590775920972993098494337275880975621105487845265164830197835847917588817965284915507524262419830462861373888642911416626362880972172158078105611561533714474940522066731108092541109246039824182745042121285149634414492677968810405895186344946565966417785837049568666165086667562697280594095226398306369058986317088939019269468828895060510374936681672288304076942588641154302697733003795438854711190880173641528064425289731358588939021519992864765259294023539775580644106294030569779850105638772122524916553684760927540606326960396016264332163410514744961129661120906553368530544355303222199059122000036364485167870163889765650622841255974578748203099108471869159420491489792 0 16945227141928274841310071007751947718372335435528374550525878261850139522802963376947404777606200932791029968339857764869001871442715311635464054062851444761725976146810906523702541988042296353769460053291477466540724288520402096523604557038542522395511529476479388642999486283740683708150818474272017102750855133668314163294669982819139592656337721115164826896270139227730157825485002942693231326736445110114275817688132413471345401717296734487796436310273157009893609429436093796257713544901525271937300499833019776735003035004878087121612867522871853592021399437634362236927909278473768594926694371766645055703470931388785853301330620541558730374198446527302316413677806192237399031471736134245780769159031288864376322836485495345614125865954132746135248668315164999047373573024910605131734435353606314904300537592606809392924477611624104428288 0 -65214312594999292560216209444642119264610418724905037044403356064287862861626547572436440424656875122964679526187514118430467687860380434215535482935629562302649980240679445814113885121481470685653707212720878349569048358599908540988516855211589228807208130007588631662761109276477908909990606623360900986359390035266063693400318764424885900750406585960516246009721029658243371000151979180442932902672099340848058870895961621929413873950566613888632963474393139048103828458644809145811896322552955807568306779885318647747406934630379669998707938262141722205903732880135756112425439000681653634752614241342359547378810797777006689736022897464433399255930101188695088762917154185396678563278579785994573265578671077509563262709409482824377575848489228007789239291906413659938197849807821330470670279207889021887847734274096595174961616618419405112832 0 232800124982744154726311873103861693932069198254166395700794259792505121519471016809505299209641605428204112030541944557950241346290868329127472900085813093280594933807754729721962017385072538004318658285150187445664630382913948101661388500159699990656408694784603699162997670140974119814257670167944119478534474407514082360583872410109908127316991294729577529199201005482267235949667414820560366251197532833928497490341750408454138385317254999830618898944247675991051465930474075809897233898213382014398138460465138927581856865408683338356673675078039457007493619731687053745634202700824517689979518862495507921248351521092956422286037961434256712138995162792653070104967984260569080881529435567191514270405718186253148423461392769886085176302136884182912249098680552234421258281705024840763191943925808341593331508706216502864307253353710259932288 0 -772803561697458708479046978662018298299074632686910000211913602547610995155085955395626635218306601207304681663126351922941913160207343596103193845537674965280179422036796875852580983000538379652267607069809446023898282469426664492942345182636117893421656183890308631109844494807700892912130646215456301413103225667024986711168608130622644711954677430757013314288051716479801890473437088206157889958407309117173934527086683172125609295597303642381469983644478025193294670279111615644892143568568752028098632941981112054836801054095418600452664124445531900205456291807313894172435768883136542831262419029450318363667147549785742357782999987117944979447154951484744862131337060043961963749301964025023602338732877436802204935034489874059865754683131741900817153583743742795980840854743590635447949536859366955650584428264291453290355141499891498621440 0 2391250483650373548813273366233114236315603287405048990769723642312340166049571828806453947643940409974344589829855982585565053271357517101024854813829714728832141709681711910431300100218314661834117866812925223077102888649732553453853244301804728840218237064335662704423517129889750404612293313180436678464325421086905949294838233330984627245430227456587341436598012501028578951982078807350939288691041793639622814113802815532077297161748425386286541588542904469759009131962974897868371713521911103401783693795602823734113922243018769699113664892853965621211947850744553262839843976740319058170906367497723139924437504483386150727405860425178022310696736459947362872465862694361528599190062631127080141724078329247544448439832817264195878842350358245209078937481374747556124091866799324529866386835880046448691826454641782000586779423127495270545664 0 -6912051370084339949714654309956310642702424882652794097957337468648778843950713733313398249642013626257588442502150007105581485520539746408210412790876876559987336416704278844633387939570103823627209597590237055688420743961688807618399610161400444280073498943565679859511317368781247361876140221638140070274694716487131950534579454666623970207476061177765259762184122773815524336091918401871227891710506169463243546503364180731858944893321457939987344245980685587603066575666722831183958621158001622108823540562634157531681380150410114244356339811762538766472903591422389172241711039285556416188903157368413913072010873215233728375972059170710761628369748027764382890369839500558073821157744854148984883914243053518199781810168660015380619127765322600992523418481078504377144210830559239704391565337461264385147151697864819879587118997007562467835392 0 18702899303903433806219604493900636334237881531034438304984920488487805305315872263187438776978987026865973314269298130127789451260194588380184280407254700986132153608217218191990892171479003062631169280532271049422725766594696305391346910373810003536636252741468093105119049637126813077376077701466320009294021489572914052438589145288472642188382223100280438652424007823384056589366263651028592715205200321593355170044148923616455475403599269318654254576369473800373816039807956998392098517499034716752869401182182209344375755361200271610407341755427619981093986061610363705336453272988324833486885607494328069100689201369126015047259799384317309563891474134151897061874749853044684989932029909159942780468358850596931325744744598006492162089662218825781228098423440118220039988242649093942536261693886422620735554369087514774024662759899618504509936 0 -47464554289424697469218720903798165743996636680296836472268764862883778684287737584435593475238827417503046401035674024836529610774721451093719813577912072255898139281923408179876019509482769323985429331331636597423464479770468548655309539747730429177784685450974289791111342906870594588472239144194627702234040421600715923095180170206984436710006923435982674783539028094450193520086161138290220978104436172521871195393272439210025683460099392428800205131554894954438409588446210233746454909478765545862718324102152182773090632022734998333239395933546287903118401043521394837738533361028803739579843175766375703473580106172386032131231963557550668024048358595263694685097836323364642369416922381550425373138798344264584146168287649633317630730243631962979427585883796051403293012255199917968744494212970922466582930901788530293692473930731089598018048 0 113181703016228731626665685321084275475933712602960598429836742124527993211522608117891032315853502149319102877763131251256097859914715160766080996929843718759751739206452424180228296650136028861753179621356590242991615352737960186541699153064678463101229529515459117494602316224891907808519843400834341218955802358019763404587502052271291241181911541496318953583730454326930265705746096792593734176187544916112648405118289457320963238049778145628612475144271960307833712148501458113882675392052194389204788678600040304160987905314659628106147660672479186479395044430803230923877682032255316786049624080859911289995915983897161202834170044740016877064773530586257917811500146263160439741103316698056694341662364232249473776069590746387925395416147754819630252893124356081551350867818166646588634186786305672674746621055019979139387797267843044414269184 0 -254021965541689539043502185037402164712778344627657088534479978930595493308523135644410733146355024704244600385191227448451270156455231533377641522533946924265336416322092994429784295375359628446730830070623867947568953998449789166831653875571601322594233456241802958258520042110959427746921768906408057298852828607754874492767696122052435652527551695302291452087381752331005021363803529561334615861071596001192740123450424737982527069227589558681490851999706531066815375199725771328947826621117847958182179629137689763918726678358047689023419254580043747567232318118198673686438772306294987262007465549245541166938608289076308423330680532200136891256785069366527051538141865284210746897281878417030019155268785604443031968947091713395630649945752583942944823872648026742672810208092441485744358320452046483771156974299488461708030171618947145246217728 0 537470339329675675050627912535508584811499050608838140033577079377980287709488670151959931908933799135405235537212575366611500142078469462844900184697454047563412027910629357050761362334498586600522406000635474896534250364482083652902482259407996808565681657372440308463434925087057493788159356269084116104417296746240639417970222459649018185044074845603365794801236097225223322548164918986766514589560512217859809455321428633059880795884185678331130630195158717403440303843695191002260064983500007948257321276091784603489593237008934550730909793865051998682087419095011092410847782472957821388745250006903669199079822438456802570088461163326610144745430738566741526612525326982477167254253772826229340725612238415233154310542663345353271673049018729485386295373395586404707097535349168226819921326649621799206574624748082708871820484089410301089919872 0 -1073711251504975261690191699143949618678519578973736448472387314778623436469071615349539473475525157506726577162144937130878054301425594257291232502844843703403393198170713738229937527130369347327236555832743565696288108881964161927334129308243121736116836347654126020954319424956333484165877955073435203154452484544073750305664377090317975610976284769849754814461635264997128508938028901308417074699280119391901367161468693284414797565142579414417081109876961571780854842218908749807047994163532833203761091897043540199279564830508630916561498630503962369188671283847237569798881259822118067592314082079556270270392167140428915932658574065949839221986571965866899284952379434579151881430500281626971858959905344434896645635215836383829986529411483771058914742886608074273298788778992562534442612398380856654113234957876469174765509479775688973467036160 0 2028134113466027265257670675496367648288435442837526656572296599747925863808593530100494380480346330768566636044183089548679821551606901922546711288692976778612212642743449962994707445551893586841795057338192519143394429841439791157968394468073777659974644552086580754803413702728867473737269016124853924080623523786570903042622841962166676017855840782468565490711259882901273707351114403742229188693387986237597086856295155569987059303469344664591441363005502188924097741393354305342972015045601091552950274835566372137219213816081973438591403553794228659377078763727646780278795121706211833914222049096929446643823057583800296778145442296456643565325268921628973782190599353537009666299197842927565500529793408957073501462957641534238945333292334349734333089038688110864140981468894652373670102861042864619408021910493828161205172453443274284911852800 0 -3627237685708789426350564075185607666984008692521854704298830834059840678349329910909084857828795743718693651899329439796060059744670779149834909573133679691549827609779279551476534181066249115804918490622908951000109586166373216279737749787383097253275969989416206583180579253972745033181487567726272524925724133421653518801309114597307438647048781926401732919226985979982122728866007591854012973003352744731787675040203297396481785523832608657738551455528271675588019809550808256717428529978982174852248250002429838789682650521679760858153643229780819731822608821641392330896217947065352122549269454261185701473171691980741226574997565057601869597695089811813940452020773165221187421941272610692478216758777070171654313877572710475929170849596175879460304499929659888031269048808425738314749947767216494714595611313561322451781791167650047826151525888 0 6150206427004038897584325666909537451510299474948462691116363025619590680344434704017745743131658001952175004966890267720861300967523487257306515386998801337302384027979777292824644320841533012575705315442427762578311342182282246788637834507185059061763424205904187546865360022858623238123821636363179987451894726277254946278089999562825701863790249625926180141256996207265515801301348034111248265027424900246496342350644064611292809023124507047596570238799464443782453077314029708494538671369281917014214686820284687341230206268270515719516530655185334950552939842184276925090469591926954493187622835333165305273589870044944167497650032363760022174083786508630810147478206342771952481232395969046965049552746374726449697802353974632784034648856846317344220619750688502593382176799871722201626072828444570558096201543619422966858544193556601943863517376 0 -9898610812974757936372074169606202950936508501379435038174495078377777949326651223016013342214824758154575228116432210889289147467928125098382884455738881656278711776620336294089388810291782543099701393887361991563490438602444867578526010406272548037610745323011950230239131998868107617828714123159980470305897348517663742252636000208663171082130133752923864662579057955986091499581935914843336707513372867620081695749030111678401753885465804456982662550591403654999436926155537121590836338081444594340907211271767553420585247774179860949866655909285184001411689960105526974756641438546495519462141908711547192658007308922016948320848118072905776707764367680504794154046189766182510155289379321606893712863433248575201251801828828748475424400115800862993214574309506571086523138279205079967835731132069338441739346139220124020809190474054385397566546432 0 15140514946569165530322827204261084722306648370651954167684213888768976040002001484151043415344477800507471660498201061549393732845154785885191312560450705447220278720919898135633974858545640105586517204132919728057324148230498557326689150330261665206716989561708416533871175647008039100098483525166612824016611459890368963510437976181463027713743060772209076841636448004078049326888833046535220122835039131280234943589521027799768603986438220071207188588497689713640264424304154767196246643011081718728001504135175241582813873205969684080076648829390586447175158269164299443697871268261690583991110364229888861278566445003309924358572656261518901398688246673573540199092113756267672570495940126936630528917918787186680208143060330697629294379129205894559262677244198726046095981733770363851760473935382065001415214882726385165477490618248583739112823552 0 -22033124294180602334449437503928122766083834411778919666615986120969605837081602784986600685091393502062641440906662468619160271831944817320781270085779070722362914712017631782221708453904430395165912738063653703254486590103377615066680512546311612690657409499025412122330466252900559408491474954912231448610427489694658101730465921108380424618766595631343363478040988191382366426958499880288160802695360209586779838078684270123109734894677566276280521322280815199017654901935314523706881010505455376149086147256008743429686442784967639149255324682583631581456929956078552451957940583258528364544695223724879711808116280142792228734352964471775944607866582279644200186556466757069499821526431518879477241088692720956061818405238672944844972902274839083103796395758860115697011239373458323019186220557171537581718499430260019656210718786432264892565177856 0 30538355734309762571748290762616602602853334605116395370101615387440507012437573497421206951541302407028312990754421384085389850772728945615412529245461495693460500049657843042322610254619508889833433774041037704568285437063441299070171634860041298777439963164308601644816012726592095366985302517255623152878382220056534149570144502667203201224768156218322115841340786160656316142496906247830849499267502693309630607612292257490242109241165320742806762898908370578452678139305135724515079731982290495154432598803954760359153345464557362960214398309315145241154618115362695443437922627510044380201827749273328292231727003824107542357905176006063293048159022281414664141825904925038535080316971853506198251455513615959383538487633461073669957376606333411211755310781748970421257629285854285043009410954313680156109824967626030202338191705577524521107771008 0 -40354670469169481396556613149738590004400416097543383885238826840230843031664981353738731462377916638863378667812283871443744730023808886901611606666274249159179566938836400038236246129813756687678613693340488001888375088116579410346258380435437296646026126411604322318896020956316384844521441181973373191328603982281152569007325315479124021470967055701412257912750919894360925554162374308517763168831207101451001300427677596446243127101268805522048446116455738203929978362295136560086140189978914336314914037581556295508836109135680781841240110554982157361402918980433643871427246229284915072522121386312407679730087898753791835709432069836617288623714729550808485010476020971457380186088113626793283176304582317849631020112699352532566408934860367626239840483666166281859438947791336430816445868904246954910385762375017092388260127693184169480702220800 0 50891557812149284777443995694451933636104018358101069040064836799177501587001711666924626427358274349483818380416199943126215757633605745546234783661671814622533161871714269637141989216056121900131687468627332134054004363186551391414492024251583415312774280022421103915283156689296860371764452533976937722899382392046251998924864696399517577702723263276099495553142246488147746246951588699129101031601146504809242497542578276469493408279518290932104777740170506935115269965186330262485773666065242180830590496593419134312119526271594368802819917028829920114182160096233516707595759208512215169143326770332195406300270068410333916952111972987816783718486342842969640876917805392690762636892045460452714764731435768984325349367590150788908318258479210411034233525893734668563833736061906407473496656999028679088006145613491319268987040852645080233392386304 0 -61306797136537019695999218121253303171977685326604512858399466947269345869665951038698395441809939638566890290991218121778888823943113943306901449653478092980847499823005380762005177186511310912124643599534616557228563288378604190621867932587520507896402462602641684987362363019602533720492931097414368468278977584971691295536439809113801654963912677915003007209819227395350247077678330685286318848639975405821629380027963642462581402407750733247577934796840325084096562324474138619780249765161078252148150073736728722642380569204824152290678573786379477276515729602959624813514786678234214591322020439221852892645088820485408937166034056365881442251423166959486164490712316597796010011020246627705145796994894431325949372520377312099284595542962224629396899489912441325467616645796797892770141565435990630161830357339283785344151013898521773600338804224 0 70611055403252997128379220208620276984702312680239484383583324523318485973584768435082777032536362261605691526339716027191089035714026733224609527874174962227540513282814048245659558134563768692320508363962121033859893335227581366280262927472327906862995381801163020152174906806496558065163212477200659070670890451519620059787700199574022756163256329925787178027009755652729224891938179166106175137598685642822987520732386745369832139481622099205486632755574062444255287907772411772537697838617056822631270607085075695088208627971507742738265726252616095711642832275600099717929015309047289050207956041663881903606190682297313150231628766929657177166210458258061892550505407011876782207886531653847434086099056546488035391481049635639557432496470123488593134224780792912862296174440524998536181819192308995335596778035116978531681013311376205873459174560 0 -77823783390923684601894282420365506834606115780945336216974881069494094121181939701574520371865161521988939825586333507990612112309870560429212887093862883972304434362803319086294950538943290831820917455652643727388209805862333409721740992514830329655443663645909561762199895262193423498645709577406055984138516567133215594398298268020396637125081579334666418634713860677710021920564748440409435998509646373961223494425512728925520941870405802873570282474346530405467024422407881815548084835081670531194153725050541631876696366722550714094880125676437309296891573533966348404419495568972475142718292318921088458498777039072701952638738889445315038678822444877370350863979862574350168897176746078189987555833451796154579218208752430471138864544889786279392523127710471754987150905709733952000286472885782307803690705044055628201346378032206800655200686592 0 82146104934830462461264255468848237898698882162939085392111522509170057203527205335379681277007685821633847613814107869011440113977883550438425073711808091399742024977141891684197913079011167736858168096355104934775638117007097938930767863306686930048822664251992750140624845851857001182999414892098918074141316806168202496986286015653837066397170036022443883049352277877446098970753418089983124437679618792199751648226235044831093285480784860221987196453216391925476169865359677173853155936476805577146500361288140867765820051976896382820206472409719380781988111742095618788084736513668029620955242490516973529951865280931151978050150086591655526340189443382506329617805967168539962135807940573226762152236645733076614904036947863522985495601535303170255478500361573884989345896313298465960668616107510764802586558191310962581204866759323020365993840384 0 -83107837097318378707619641780529094077285721556075352734287715584897510658185156223019514124851158294830391510817614982524711684506071701974337675641216077810326310921413995558155584392408392546334883661080490780955672688018943033932854431355904962393838572110777435518501296531101489787726819418897632884152040255330211798286945569692237454878886786442038489628918734374752882037808218612326850496090050660213014909994717941612674413543088765534793223000662423106719810723526968292759684296606087934804396186119676105461687936089122782824918404031065705124407455999292250060071516736684773544846067221913192567982249750154904775390456843137106499683060760600441163798060129128966776594302897464361060566865802994899443818586941653209515607578589432416244498066051970128349760162281888121941526917248754028561315585216245184327108830081239643937794307584 0 80650944653795746780438425000287233094832333923761943162969205124998630676050173721057544059987129136285927046634729456204197536197446289190811135598555876122525080100500709308795748153328860072067832108290743641903405824632870106069974400874394601552649787830895122956586774756841640406013375969622696419958719051460926372738093795334832958958813147449482461436311426576618632956244996034915818675342114262324627009351418289978119615418252228843599462379200617511021561342639561597818192057096928992563088504458114056651977224430414675324022910590724124121574281044798098532949605418365695658204299771187692201689247834761038312442316569372860590633681779259198006116604797339705518243182497943212299178409569276245413543072412325704258685433276921297585027218607765144464112395679410887764428369765696877096132437134547017480553021434819419089768652160 0 -75129239383974238942156094488500366174543600505997693035634450196198818368433738631315228217684942002051378077221760962193390973963872563633161811036721047120364756346930735847226654199006451940319782179832821839275562609710176969976892372470795944175157165718250810979253872134847754741550901428580096528638220285643412753634827058107296216396464954200332969292458639739108177885916402494783716936387155723622700762932887570401944967006547668846850845954191157682433581311582576277572881947483598216392117065600532035523531337237791248953326782045924510770448120624670083827582430064929450938884438642393358763304267251710843083891129350029977508457234219490401651331542338704516259927562895845877348860749724708931420385936996527776235941411272538595266916598317679088273711693803704120133219070007535051860150622049907591698521546838603694937908955648 0 67227710056049121899297368981987344767950622950806720260763444502077650312824831139187681784932406062060219586228136325129850965937488062145735017190295051084075848638605241996786181367700202931533175693178818997084429211184029104897839655420388264370282686763135007619961150213879263912441858425638804323106312110448522230922824730395265907880154878067628208872466706635970745693176281027015667259128562849430446880735310777637803364155423242220767034961312594868882286531304310065663384869818922122483209256603992543969057569447936078300872746103384364034508626488791961598591497309699587068491079375404914405044918460866037511594860573391683460113297828968112016675329989083212550742008625734483643819808713303456536659100558619626134400174174985173014119942687522407574779338261037609156683448798164610272449833018561860261458553752231163242045269248 0 -57826108616707686577856883327560446574837691570729614044316449611142238801209902664729648385115424427259964523289149541858892409615867932233327615328160056408926336618653852613058781842644326769033248166715275723044727225710042199985516845606600726309589963688350984039852365071121312465793626545182730905253394382081026434810514410728771407998873839367639988668650009700414951344029036098703509778211624019962042883152136833544054219711968641369198001051993753004619428346400822999095468657907797089775953464946971441868756099028234090962997371423496314373897667212864084742246926972854924049856276537244249206046603071718805167680834995973145769071016935374552395676615249937529075117786219128548674167437915106825901168379433221455049192710358067404483741325550224871581955012263052011731168769621896211020286568130386552041794581806253994613561519616 0 47843379605778670959189251110841525764827565250985658845074788887564865415059035356581883030167094318261988607405882067079300995574821778904435408633622259030233594097988660611781891844508706037860717617555186412954518629060550636855418293674901715745409276492812142597058190647557775746273954007798614624251533746930143154840614125641380316105330149172953261204733680097096419397165753682955183440446761729172754129986081958923093931620162559249911521563393380717177360046019988720087599711888555435595745388827681865971462438446332651287401157378119059044949727858167007709007390968917752656362717495917648130435342562036341523452934861447404872744611349830084318770761611573845796759373182155207006046551955436653834929274046387227212462207883991650502282778078607119167679796008106583967244444435996284909569781453319837782591092142720374714226308672 0 -38099370835570522834136554849520367209367686810810024353319890598014792142770005783765924429402384858047323715183134514178188168475613354455594623711247678004773440441666572428152460851928606346667963915672221640298534868767042239856055509080092632819580333302881276866912769407613742732634058238062971216227903501218825727518925997531657583299929774575153286110521701140794975513013437648798177068839916985507630224283914435387075280585745831463935475996890729680282385019727326387253209523046044340944110945337806026501903786949382907353849041529292336181743877228674501862733504938540177039151216202806337030157544014219409589533391441334016159127981196245237639756604529786905021614795377464487937611563638692351518601743308440335805623620886053482000908130699736806515310953649828916277201234513987592157534240621607057166604195010134591203492643328 0 29219858211865641558684737544648537103384554597974699333188723528120757207859398092350364165328069215179713629736492421936273608400960600946949797801978907928176456153991644966396748335758529792432735311547277602169562452504410339629175807536572638830830029986466947247559681109333885668756917020168908348233023148258835438382966848660972251470161613188304275410714772146586691348904914204806029108835002455646169963567898921725954002209362244239397952930036224553482484176632335910248629993079548431003160129019296655436344161048757157380421118544651467128291888169941828993618343472340245846218162659380287504716355934237074371544957034577222681006685591399140946400678012729124231083748675067390194077088270125311206194704805267115147885410495780269819261910811794217726507920690262389630396170742921684779588337651446285912478594947925526813945545472 0 -21595334715173766596430258959043520217895928355865411890736869581579506793080220264920059973094646294955776317894148518811178224090439858868506795296180566010668161146182409051102009291019779589561626490924600359535627926817520508524531440911802696135606512286756571866812553309370588884169436526441722540620553625670617204908135225902604642123670077556229803209155493859825747148118673264945440860083458336449998719594128136230864062209946206190319288717085834351488318031264439585600782177871256009937223392388483053785646923610896290657829652341913149684009863592480007086131644302159151048938621418445733205332626310732570872132642923048876163609968903802216003165142397983803291906166208045708134027613109844745975767909999855400215370229738604387699673441108261151056130557211067102396813866699500903978986571554544992155717638059680712015110137344 0 15389051637916665094098188856554008270073131604347454099188634439338980637767990706709402621449322014353266028748492635623363617025605301557550865682291666184322438037243223526503776461397589939863268861249626406167267985465491071092917158845599233411185418154094115525233380529011869144988683900381113784804974687516227674824928888179498869043551274347852141231132838369067745027775295597639287340017772662480367614808697356404887830485217649516009298729821809975632439665331331138989821968422501536829862107061370510396263628571583379064082669890487532277143423387440379152244945942986573249824854577801256383147186078989763688496270370152897883598121914243314202231062324587075107629492290119875120771848887511963176400129385280592441381790073611439665774592087503530398397857334406397125690659365168617711169859655249885413187860740951154876299131008 0 -10579720047032996437549060863325830584103681927557452914978502707489191103046041969639091249439357123536812913235649008267970679536992504032092755315550114820281296191631647027239398619893092588011847409752925910643422061606270118288338253259019532451951809239905454943058838942463365692620926897300816177973407041875722660198330600466338508210247641196431420012019975561935387623014302645259769548944751172542755865739303367483729274749752537655417558558047701212736482198460114704447593465599752711449430802393770230732815834144399983145940400202970993682845180928084055060435567942554358141950519382290132713377034590066761008355515834198965566029793822045989350365132287593498234052541299218710756036864425380564447238968852962737184094211451611057926119607556419276617337183630193764830025059004935972267736513375774481784860389073773836133935577600 0 7020683258509978153197856156842904999589220205427971559390947571352023019781162396441282677810345295989860804122046901737317577066305321533460471804505891684125938402470420828714873942452088774467503068555807594260771707057728156908505351022447317592072612493667345905138622601336452521642922578090446191802780805063832439189584821994235751068420604867317437542890497409301356751504999104645107316854284095229335064811071197249703175798602944413852517871826052403596008702356345977625652825622305107759487303929677208178957693372974044302866373654978097232545898518631565204121680596162299329758223745637285079868583833620449894489289417981347594467116190041833559862927790737613532330079268731801555488635029343258657658588682109168471730068456527503989665141710115338642732649646239473666403752441327489570879294163610452846803186050900547383470545152 0 -4499378015883175018456009237160367164043241743178206648028226575311328059935601272513716327862175028820597740210568840743055578800664920214613989251941598416850610980257395612634087642319804600909101071107755757596314641059428899082924060700217119300379569606102073061243174284927202194496576181470253185982520205490118799224709795946170797087961505289869793429444160111700936160308593877587070073557627982438171378284561227956394222034698008419613628529622528157963346572968759918645456665524943265498294122747193200874979574878232933886928325294356622551715534934192505566579661094816090431679693943161863131776137495174710633282481159761810005609877345983573625966746328988856384530258880102814446465547575845069205751114211782752891358618117137465457190557486035965584083131825164749103996060377720114802615159765015190140622725645685171937176690176 0 2786194087882105298850545816822509881172887637654693330398963765407384093872083323125427067380223900218345996967106687263626906765010696716431846167583274930768515831666774512208839585123440173533854350164329200156397266821802771250234139492693495223001931974642240239169976395710339013308261043183217359949278876084056412190000621184293406523058463627838759577798402934402172888688091035011389474671450020099216756303139280439272522396562880272829848810922692709688363682857771750363131480369506976803851299364716740577919504897686102362460323222338186665984898070337038385230490240486919909354942130116740469719553570586421536793487660800835321076221949739977811475414066322407928478018910924620694072777590702755012285247003491092220663807211682688253571785097715302982509216318827671247157794217415207834160686987673980564439647691693499540995671160 0 -1667888878064895260844777998464438362988688275990142283174765013159885415157034241541932423176306303084843142465956351158564702443388826247728666859312443490442893155593041235865889514679443637704763582383687645383612434907169295023748734548465974050884160057245782861383572098631003366921974987250615570299683119427295407350580732476151226215601912820641679669938411330930276081665490748829626064719778456040275847826571046570843984546607638992003325863995583907089884633352396570697854654130663167865512349399064240136449776347111612629454846448083015805866269616046665728866334443328465085623385742943137400552031013368782010411553001188704220798574506071965427194072677127313321367637989112368422535018562097204162924579372855277476606639277838305644031011375042542135253262519783285602010884305036936982002428951169088888762184030615275583222669824 0 965660127064823429860867716589641055656603762660623524754652217502274872383482744512001549724307709294759283299600744938266374269354571877122684252601011295878049467987464490432310897046655319400784322280010674129271534740837520735969761009050810996937045738611694128012782859013124841649741512382030390786559981943623466473802018663552669975634785302925121819074018084351063035194744110838362006663847124550339498481848498599068288208935856815561900206217254568988226056958924903017037045054076135480237770562501542707225766209420135299029071366754150184467210304937128961453885785631827637636138418583450616174302210564665835637233481610012279155051490202183377008593079363488333611565933504407851203740249132255833416605812029029750043320655187810158215197653991100921527095554453707003719597273676285692786901993214670353196333227875451401870696192 0 -540980099629141809053373413012474693679026308385502512951039306489554363758046311957071804135472575832654191589785268055549402670445981931888102698965516057496667670942977882863671663706301433865942356116451904987048740980606506695617609186896624508465602657091888631726857877427122968519654149176894535317914598859198029610528486590950694847367844237764808771983429142366169256129435987188007631164624324881650719099795245142593841490572728315704920591838855561779040219065090104845880045715493707524802617819005724605078029164199718062218796279243083290362728712917081862057864380042674304302782501331960280474785628895884300696929839171724350580206506926356509246878816788061863107777876779542563934331048437125622864318297500413474022864072548560645478624508747321135103689584721172659029230735189029624553152683873116048247948442538961299001206272 0 293379997778927585979269504561524134305987049682721345829146826395073000399771106356109604983175410902657688654670232020426799121245963073457718952822294711489595073890947913346704384171345055317021311960871599268631417937060183160288889245888657721078536687554879340600598901915190893997721629072433428014680854767096687948659869816458280359861767986254731486120702752098111443428714125177530467008248499812717971838396048329812806442098686140387995839998492357789553058024692627636587030758003910547844649868958701094940728260498751975555686957524719231595111877801519055582719149485571540982061148786273891089064635106016281247714498544744861553466733655457860462773978299021297597106788572397037021408253818861155416196822521893827132716410060595896262106773298321403574834063363774942052870463910010011033094890371046847689310091083303556457597824 0 -154084396129034295501144209152802449721237249319755610817240283870154225373933440218411447105730841740856657503128331678322326142130388583226225507182798483097004547947866483586525569214862290150924876139643798495889731456038477366921736995267784982290724651055313141674655569652770550141965910164733011373981294519165827876772525507875328940229014474391495869611322350424867507336248402382974341119056179210335521289887802376958106824049171771119435496351883110149987501047400694307998876882747539729737142938235996787119271868327517243330064075828121473611581416276574063866783285070833170843906166818580133599568573104737976848692834094797625889140996896086532531078438450058771670790458628064587982935825850537518748977203842833494810188884132096187269321635112420051344802400383266253959578453980105860145980252288762599609176985348325524796234240 0 78405593307614079560519773274014739919620205520645990484902424095061934376132027628883151465776432003276790920045591071427669089972610230896083552045437243536940098340649762434139825125806342323482281949348811401535185144090469380000855915734243903585135855249526974226300234526507675976160993959912791904431069219310375093437103155830100872744276270202073902864940373731820776768032451947270126596030183863273354879172261928006857346335168117363301029766470510105660513754763638746379681911229727631846851342230301114590689135595690014559551500275128044193708344809159488811077338242288054791758015494228693466471479220815568070208425332327148916659608124221084690475788670332083599418427862989471291437461792288464939138688578242036244416800139349627058022846803156334228797112819498625543141792799391571996546806502332544759360825074521500668708096 0 -38669780742625558162801077534014269839062606881724566574532470573588665726606537751077009610603855096928422468011959513812923402473123951957725817929164757676697144562671257761429198099783187120632935712003009520287063557439976513785996683384384944422011217694009963344359568716056736762681466776794114060877260905782190017136584694172806447416612662360573450638639755751181613141432553707810669326859825203204283929423235972815845351424518123021902933052413847711901088515563194705513888246978370513544593216827238478695611716842913294256828919679160446654045592411694297858373886359765786064379764252183716791771925140552042004396417364515564318044321377454966165864165979107129629352170953338205118648669353393185324937600889071178793634488047613780532293722760880437112140353228107518020231313365352553663444828823362621526516853422220664885206528 0 18492843710475530408720836456217785208476776967680747078231195995064313479399640178103759427628863906027075726162693386273491807461536932280092825479901741819523053935398350558242703656310303913037648646661866689148395655047735416835550540050988691771843093883738828631543776668824328461299795842411718805890036602026949698753362797659446478273638426730067803588896884249022616714527003324014915165933431826918549129876419277298679508893210102406547339199197417172864427432313545323857326277347138856924514624023264057688759647771669270132335778228261934029674935960702449936801023450458629556170688553086236442754575824373319423540508670699759022737196553664200568218486401327525425866653702211000283290986569410357031371878420382708896654091385174397727088633187613606417044050110667599340277350409246961139934892821169931983309600555378031299919808 0 -8578458545163528934137002218153915782541261644681993383337681455410375550392278198679314166149321842464333167026600837985126651881801723505185283309136307413519236448666908274724082199368770518722295547539022324145255691835415353066550373049238782829357407008292725124031006791807666479533571472241994926199255942551280657865482493999205326138236735340028984723687058151100582765687442570686854411148304131128298453536398972597622120747624534565476512810880057631306862496849802246722070763315517999730491193681191978838525504586630936202777232051033010745318793253828330691039112257940652240947477401645846571780564673709928207733159239445465274223457012470801561892181211574431785284854880806563524144654757197262039057953681263948641387004740364956756600100752699996416363055743496842852986808944249286998866078378179844554798475247718544071266816 0 3861446425817778318219808235993254776813449000388540226838999178412945065118711388510777919798401458988483076350845640566321517106251365158955551174276060831588376105487339903511482467860904100144029138745777295754109878725875493019243804848710805926679284843527720099385943943215636334360256834255835075036089157754378445015945459622309584784786053187286120272417073413245167920162663348991001020586609798445197087797971898677635211876318893506799858460993775168782902973449543051638056231652816134608717258849941377189142473977235011129539006835504807297792902563587753469114795374755204408208646762472533637096596770310480992323500953905964777946776191825807302497932043235411840643404343057124625824919975489363586379140454310761558011170264608512059906278290970225347064299394390630824473920366356210369529805467073602778828694401529737189798656 0 -1687264515696562629210021597892869984211453424880786652127071184855410756344300224744863130335096569148037118493125019094409133966121135095295172048509295120083680577158915585055108086694371436184217797591217063505117862480716366674934299081073415870122171598950160788164531509540178030053237639685818184160131514144839064092510818826907260732570366532603562397355835982935560688824383459811137879485140295357073721582141596557553629283557813251903319391668732491140161149245322046904612330688893066499886862318191877661025825839937093418422830359867718242712636127914523965692725116624246289702908164494010984613324394606518458307224897555313141012882319104971387934170981912811484179880661449210719008285569516743730283303821212661463482288554499061578291055273807838119553304577560535067715692373829466422144257865742538449966656863653737430816256 0 715915365541913915399750755053509256542035500975538423326863388862185711473064071955961911464870266548796334338245168253592180141610482097260446090155068354958760342405998552605879883966425075459094553647047489439940292937396856558041949458786013887452964703637080880511049822932471920836849061960163411460799078527779630195574709331049371434491042846354858303202510208529647520235794313754388508138568728539092257136816186334304008412720403347295391017362335139115051840317963232374483958312685120221379376233008350877657753016312372223083550700405885131748124680296575703362247868706387624029998639534732028523591549773229517660220201826228067567806492053057126758309891553361658934079945190364304786246036577293580414924885262070560723268863075217955304816582956443266488486760733303002597910540365365305071143101115024124847839127552502799027840 0 -295076351232804122720260736054564713902134584893424729831598874092393945876575606050744392435818163410725141689928762228759524113751041108477075438559481783257199381116369337795421218944470964872800253371452216196145987938244885484773292506662579627928011547039670486320237207579847467814308406198736319054486137533969241795925601156225250556909369730878409104845079623799651523029838820757606003929347564857960673189054767933740945909376413233203877412478124940711668608976532326907229947180992147900636053061177215574351963503547735976419444235787900343581671303293445550641465802410631551442429879113280003291207782877294927801502168345044778115709731054761286720355359380407759735386556837326125098950073164166650426579776933123753870586728716490841010190623692124438873236190671008617182238273067257150344976289184391277972561639555508503939584 0 118180619320813574685261650323777090872209416101048367103752660665428331635124227959816886975706433325921109530275252223872523731663232927852838682073643163027773965536459469795918405402820111778403575971067211523410715478415837052081650657520479137219757566103630053796052489601139075913029982003463271551056748318718867361084739579598557250948860221733882686961583080981371226117380734029011844785964326987863746467390975218645952366403683244082805725303916986274734270631590797655541167475042252260077466295447529187492509979072654708894949129175547253313963931486187172477428348862734773563233813991334891543598770036971978193001083749877409059449977978073728763459653707481167803530385823013772244542741519211516756557912404300951126686820491479018510296241877592933340545433247256186698136933177112929138825111326909151088711598128816613513472 0 -46008534094637649141446208731559926444000453510302122433262424398382278373333259288150948183916146353855938670550201576862273717960035179770845189159323907169336758278574941797371781532268180172182381250114453700017478158720058876496162708939378757173129094964683697613949191538369354608480561609470978138529590284254908390037317298862315095024406566447008980917661723598678043490149768839456238373245580679356382102696468451113601618045553869252364716081466965673128835748646996357852213458639271913615119801411210661527449831166724064193767733873783614121930603183629175992569585046251824243605124591594033219133695419074867764282202636777843330899624827121449155464205351831810882562778871544845783667536010750121430710106933031597287974943874076969582433620882754965844710573302273307285604060502993054640831386046676171113779684343002588679680 0 17415995626843377911128951794414610007335709324646417488781151244028650619820192515163398352218424736782512531829909633910494675109740956036976070009444618274572216043501476917878780120123293552747989841472784029991490575664949946214108958059348247160386329414233288729902915401354073956688931913796669582401888919857882813592016471515333411548686559382988932746286378378970246042188180139279608284958191358024971822257045164400607767407501180300683498553534442854856594531674960905170997669502719984383035280977269080823784191663500879186059233324774744897339848399629573409711574411292670361138642406599221478254584180101921798264773265168435066610392778983393281527634510583869316466453247068097148511057805966091212687181901768036541271953647090995308852679200124924060850643216500839288338923199079145618576171917989692694501032916275232222560 0 -6412243180009173874020311225926915468157901767180994518496535639146217437183286893938604563087750309838065225390991513714361721869148429839664602860994961115086824392418018219020885287492406312892486699554259441853040999026761885990240147230071862333660380922188839926607471337312780129711931258307266875959980746420858917441105664991619677496540393701077091498457107653644383196158529186138143247439478850096916614239531810704196343483607508176801260206657945840272705158294486841414474194594947280325000259893437812038949015852586609779372364843224682030526472643399270004883250172795799398937028661122960666717503983719782716349021634211731370609474520978573543204182552503465704210124581837254489123108271566102041366630120172771885065543062419172395255414107619223778361240725668755813928535148700586856758464024196576469048445417533992665600 0 2296963205868202163847651545705291530342369109567177890986859958880433151587071120767688095895913802989437913071487264647651978499200113071793538005516685229665703937577274103126650761245840661094499135852456695370678886258236761014736545224932916961321832564896954779617703886860620770225611202410959133696787628886808236927677276678075590880800459272677753938920583859837033041498959051078620302712230710439430543465887774717512785341162596927352338811367502853345988611517767468952128579714474633840004411531660743551125778862499913530946056103552311393336666898468343757747211703604854749122465092927646866806873045753277373826275596621724418184381570581864510897711506376308880179133004451042318859534996624374574292941913860331063236164876262058134069625220585535189598913660661777734337384142411087151478894959751753737814894310135456286464 0 -800770050423455341916059414933615960117152032810278882908016062020806087012163091309673510091583389818413213415019452521485296231550961326474602820036987376155815992508121920776680581803140908330921133503639210602755188032104783206236385819325221257904700320027651586640084436179637023670987002365323890735791070821652551030839014684482338931072389270549014312096470282311388663084007791197383034554236651250768150654020419872531472795930375029734168011664222731462225396084211135304453107668875171863802472787168397448183516268932677953755641647765650958513025613987951807755210784286645138375465846792897973232242385913933876735090778551412473293632802842031537152313470061818819482828322138722650609799466045502628948534785871394989732719322517987318603807453414545584540593653779110468655450121937369020247371742513775568822431030037797635584 0 271766264506377555177627449872127768937005406636950466045692446765828279818012676242660944609798997520653596472273235828316947633402173142820221119258782673235813970341470030219621574335414253137231208394091495787156356791726635933822646378085037911076439955456329787377485708855295795018167746014765234033605101105833568641174608938508471264873000037369779217658380779099242312325085344257795026320269021785157812875900056340680874382934696006399782109064664095894173826866831447972810112827724758063823355100578726812361068263153386575087670623128246642365200130711211021238466567426753803644532589110493649154334096017617055863460407413029482835420576738458877658697613163518908790959837030533352907908291141270334906035189105700399526107286227596985356073707780722770819198805909112782011174341173946717655489705008744602732657022527350318464 0 -89812831455249765780284274376588260819335955230822244962504884436099284728546830517715102152117137762259344909992155565351535275168457833770126788994245966294357883270527575090769359934763452346621163821796722638959068781819832160368414264626579147206030665044315049524928370436126687553188030654270815276211631074201003061679477923793816518345180844441556633253946318761298200801179080167255103779692204172980716233498871307139754550305583806645867043933489438946350891247443272484874934553964375307753872955639794993662426766643707468348769956092051555998490102450475102083695460302287288609553553771654414440465555158440134881875244077279379651138160367490739375836945136711133439021350040727020005732988729203146413103430646079473508585526751291717375201841378306587707595186530789865792759508107913053303132037412811108819176873239595448832 0 28910433726735318778231157963824587051396681838907964043214100565922527277852680930776621033435192574926608848162341126840019587888947055798798881867668699831546615341664215194158850321681174133004272442358985354662548981297216064217729159740052700482954641483940607677178939014097275861417303056693079554230460189392710959833703362431159451366558226987402820961116883793332459438756759679129746247760669864785054305812772064043585022530730808769454676462394198385243366717379424492448072795305813580408500223407487533373503784820950161540692984213751311503462550808562541471074920554305754972622169779620199665257706776250430327689533493585771132750999023178856864910271283918229000852166517978719581896449003898648284889586089085646448862721790222186718426496931780998359970830543589204994477168870490500571860061717784223631193351904611478784 0 -9066916863944540714225029448921177396091556023739506913538675281854376778645100813733505272642628071991865010679779842433951595761828390995160646742420343775878022265954637894752895584144806153717175637287019817243133650101880434022341363663905032333187114834405914040967174316083130470552469812393481500497317751757977350424577306681983385603406452329455812598773336307095286757407269960639586999194475465647474830574371149949056106584755645072171231245600114538112279193776169057463441545615259682549424594459339993893057842919033166795459569647912919291202165857628502110372838911385016761317607537367915528262478842734579027298335598227677608545888112306939591352640401986964493029493949844535710131568861677891065624362302797771814604872414538827020920370098869478083092164402015394929102595443961987871194217068498642845697102013292150272 0 2771189165005301528918239543273685894065364627716548491854782458659595887291992968017124790551439446900548197089212076273839394668070883743400976361482611578488091334779774113969782131342244447776913323181993350262715520970068089368699033070873815707646016949933675501169108999117520313151204798294292817469616567982741201395886650841814226020877341385930882603583970627867517099285961242069647677741417915315344125563691984872587006299725681364711831283859695044941623807296863993696575202444337806576088699535732609346988217502576254904919911403650092281438585485029891008390183787625184099013678980686094113145674577096680823777528771784018672177439548954005763637847219903711624883702603078213153528232694932322581838079026249740262106720707277450319490913664971415832154875502250887415232825666545232759292647373771019959002184805022337344 0 -825627771887718985573213415828486162382436976100541195199682916255905125972080740272310246530496534698467080104369632264266159729774948030032959557592416121751849590404807114709193828935784412303443886049968560762998808453813227565841355172153553979658677893822323885760506413546474401129293382284493636851049610624355284932995576096894972944443468051428601475354672245533104735848309546218724483647521304119322118875621962812435819066380758469070931446801910750258855092260483661991430883566507760337614987061339835896556382437666944024253615809300092827079582797055410234385337414715779805859846469902182018068575881978592846750980358738913382807505526484555871535032355387338164364195468939145228271034302024865848154258469622731897133963063971163485334726648495049918835117001716587139324036297681816308009927798280219305098062877930009088 0 239839946585710200495604714617743259033664496498422356134021138934690585726589575353867602244896377154005218914570692920603908632523102137394238296853579605948755470183593758514378461447286009647386499156431710830298080211351461211668551192163284775366823785850150437414317809107110748370006726504161709742373498699119986755700642694651028614177490543832251930611481961225800015619411086557883090616835343371215546955235391148889569527168182454937721740708574834262572090752558412520630931707838781121785948711991543088240230124902681462754116826104804791136199310914471763454096825983119877917743865865295397774731566720334472807351214958750280466338157324326066112507115568448192264278409111912057923204614567474130289190440238782980296248221093014537589687549717083875253642682285407390346348594149251569145014988381486471255133221796829952 0 -67948975031591295182496125425884140472564585626357695569469219610948392364769055257360819297017093353469937921919002842136792927058135217518095179098015740558230801200633503658690348179914563144004740376171029890183586168883405710213093461596685829779813179303157021131212317308583808482448650176134528958689882857092197693496805625591126194119415815752370875161237011227283526920672745041638766521239596138408550867420134993456790568042999547979712800660215834314410390499143065324795695062330411381150101361479585189798295544068221946939070927562903054362435594141171235468951822044446565420593138925408820847129303038446412162167817380245592546626041625957076976977717044561289950268616510415881527132470853558183700828856974173728016855804295520427011332516052554407622878054028261164903445692586266510170615532744493546931249743784752640 0 18778943071377497331375744821677401531474156626282553146775276377459551881635773972476731525794700275420871393633360705984051873063580583151731535557417840951848641583048549564313951098520886682035397112638502889506017546686198267424243183629970768964779265941312476159420367544113279313099626753543156104478162231125765879800896071543624884324626413162215787044055337290221756844014307881956615532986253432486845367181425389647069394614660794044808639486946117147732829196939123450468076429844374573215507345349258945247789968242693327523207977476112412971737430020355269734002790859825589361706780220800886827165862375001771032456746026623147053233143204921756710278358914910373344906365830481642786524302959964355501654327659691186512429198048415220759416207094521489683270940084652427631780050191620915994785327236908827165908080749504640 0 -5063917230274998830362070148146696039183835288490980477337927874686422129387173392649821881837864841658141448705213282399011169977745083687289600815428658170657736423346115783010676190333685144705534425343420415254307694275087424583849662129163551480902928520168812934479879845453208994656652608628091937332434849065533206990209727987081924508643492843388895697160464084565954261682647739573987179327725434854076873656513692665229335077399092008199580444148481116137361304611303086137593933015348163053896430346952064247827904670304767561028053618109693734407995739901558275279166649112390093213155106585118800302968507200431563447699861024562147459147899051498707408832840980943146988198997485981692487487035923520611988504591958990440794963629228734333869306922885059262311274253543325064698717917450568550067735367891204415535604721920512 0 1332684701805961128587838542825150619372792032329385939009898418048132713154414409109442738836697420672141725512272573910730774374301809560730509546687510335991836789693162739695997455137825579547676876938954677565880329661398781029128257517859700504774133370218213975415346188909326265517458597215894008522747691934738025190861629242626565932420149856806032118456317714324154181163118230004690884975569169205117094601475630209513946528832049598245137033992285208195525143519919053821700136961251498830717987671272282929719075434944361951257473618441384986322883223640245318704346915925999480788069327331629838299791890982837779781967907298745900659581933376600554932592746920556037635427451539070140842606243410912573496517929681381291447095614819552328731524823304581277273021024472814491849866157345347959570568425453307664124310642000128 0 -342365165058918120773251400766940391666750799154663151218787438354197186935773130909604460240494266112403759267364993298506627341620923354050257155553014776668675043053524166397081150123557429805641386120130065548131151329707760547284220057884164174463824274684662814425635067722661304235994516909115053216616566545945941135381001509642387381468218180730557945888991525730902589638488158969126067322727516837235773954403198099395205575912592188170823922425522158312456650288077206599939612569078949287628155673198571469846230768430540387519387590538489478344231031317019861452044995353835350697331196043449055321893547370155815189150111557083039126884874226193104693557208143804156995538350535684293567755838204577816959897794136141296408866774312393947020380383840472593650528379954797197547956312176778132539967378356293788263951643487744 0 85875041684840288710850587110998531984081926182338455029247357585793852078612434038551697372495087920876829473792530520790466425453336442332830524455744329677611480318480119360101842543922305513195451167953447526133485848864115537315062131359675342118760920684970661836266554528631609502177924431442022038542330421653145545781583062605795357331630762353481627575591248741568016283955280200396229067455823801215849496989699425918544091284475317551423940426644785316394910570511475707007840709409812088325306344206965809746281945641474950283067472954942546743682831491385487955027731156451551239016449818549605550794896153838837067186795941287975520641142529710519625840541402908303795571799261463286891921858368070610735444451703308728357616383337824022396574109645185849587731189946561513476344818799537441560365933919892235009608689777616 0 -21035432657042731008068291351242508606006556931184697274426816961493150482687532305233241998711342915139987915183143628303193684706363460453852836384090182096576703235016158595563746852578440556426093857256431791508934792649415146243677863573823063627736483755587570225962638142125551449627105272756884801309415391578047847156503067755942291859567658951908794542095750673908235557363031648215574481637652849324165514132166502882537772727854908903207172711524534334890896337711476631433271592723228829033594593548352075442107440274344998312973075164628957984525326852711176363598465954731299144295407002589428503438045301515751891466974764643144044955662860022385441488935694381448815647457072929404724260343005537908074707397855189164981470623580569381121057584025686740510563354563551713081350639509036838019394676925087575528974286291456 0 5033069554882098909030338550205556582516634677865975144310770222400183393293395821357900791404220323114456570558214815724052405205748752020022370892413741273447199672900011738198054079598114194611311883081857495078930244673981076075885335316207249228110449277120499758802673969998579559734615494395218554953875031357136701749561269795648702449309242424612721328122551399841381379056799843409978841324133419023777049256451833202467675866317661975300662515492909903657134608477113766616053071009404757492433574107715796389090161148272522189850255606973922163945943570505568273562916138147679507213114687082828323994023594708763900704018518470738593701428768039477009748899059433688840472981201931544621828180760438918302213993751634025227482107444521931565408457869477583102000839376743914877297107770604855079112854038082544522531424419584 0 -1176520241265820815604265200536843692004319272839322710763192779723720185455186838948976099470730490710844696655861819551477315838188574450734938306258115874629578948900804785296532848151774603615235914552069908674158810499349335739925599414718730382696637460113580240145761622852984637302964247937486613720911941063643299229424413423866526710071868661332997693166954966012492164416099975993843495274614816397585504657342269234872584674008992983418363750892728522569487565113010011109726772449553387370323435174757460161951015281831760660537090642195955243148222414798600245271563592345849942343554644331401110558209993296367946108322934388776482748789593550116728469649955958294164600100171985979581347945741924119178119630573612122070115532629036484915196128938278309180679001951154250997858740416159869312957134637934091220289175242240 0 268742905063021845276750876088991684169987097097736314519246504516949142173592389247309494756817929275108338312309766322084523766568044355275531115115302704129915755923435226435442169553334210743872800233235797095727988072688013505873648692231665407199786382792652548012856468646121792817390229898861936063938933597499213420340256049303149011503440816000124151028331162719068552897690514752816395616984170659991140554892314898472965955268561992602255748034150257031039524370841942905497617803781989992043916242948481794993435938931838308879896542824973321566943356388309244541532072847636123990105762799971596804944916946884178774863724965594611134076453817006437197756100043841552501146814553833085406798327434815503130410812141406840940104536759315127249005608588044525781644676774573113132872043124944065081884152315996059497087514496 0 -59997077639927334776769442115724559119806622793086729825111092802033298928855705123111884338855695955830777056600739529498627975457940002188645306526603727270439338796357397498270915012894383566675932947319973429606434773534777775336997033803567212741302182637801365349596381851957412882233074222079474693065200710011084993286206004829543329874561769407709342146116319131195101601118868893514616003578095452513737788031812444711168035600634032887978759351767254189248930112313258903917625168284165789516431211872748703267671323401240892956875122777390013058905818743391912196696536195097221040530124653261547220840685791218594750817536003388743835104387774950528244660271870154279448435621391473063235114020818517643232162667862584616859255499766750850392168516467313228105723234535617858376942702661978641929098873381678495381655190016 0 13093666793504882272476353083854357234726754770817429068162114532216822984957900836675596416624836821512827631677117517804284128513345113221123996129319635318283396166957468707644188964805927128257071490102794873724600914874802666283231600967505514355959007231239293729075485971260254076280421161808667125979088889988783031459362812479619999433485733565305780784310500181707802712685162810756692969812551097930639219634934386807108364254426844944940781166121890659730236469527893252320514775596296870946564432724184487766302607758254189466884634269117027757287350390238664838448240296722816346414835956724324610432256555403947509525309732850608238979150683709636653837578820207266497243344224665247728293474342562318858370621444474067890111412179120400068587039089991589680431464524600602135989570683972678518637671529361535548296086784 0 -2793904096078170767331570020082139690480819908132549997961746697440198629424437067933839724424672024977319830240311639338121503200806507833512534570747465644909802845172555607094368173972092568130775591269737158776794701061186887304244801446450761474339609691762727334497990461396188643291301249303069569714963804539445184403846178949687547527843704670374641309918011200118360301439517612143902921812527840979704072635413174238137543777965052928007504434293225589901304843315627085749581135620632346610134471173857389813398156042788438090322585682006666171704226877230003328206968726459495856833792651198194179878977925563474536881869759361702758145698953173202986882044401026004099866526606897814651759768737713345777030758192858300910143325276775256919337235858904289034915816711174829607392803274323870536271312090304716350906121728 0 582988528835134233976250666043226018291306451786597717738691879241322549417488674236469777774286057120839309030091228649460491915394149397340664824955210957248298514982017695625625967600293587679841463234219430502774550866432260652941829104083917058985703712557369452961809521697986898927646679125373395067167310656430329572169077226297366957261694259018178089576826818415429618939962005032600656467735909504329621081056274761965720500288165461857092439020356007420897491051494533156127964814140934326233681731733884204396764175488128507687298509864653151648002958993716908525926692984425404265049363252924280444730094254734829041093306809192929557263016853016147361238329674418108522001842196757020830398822591750934281197142369272358393124151115875706658132296571692583754513038620253443846812598461984144524749582814857053073074368 0 -118982892004825218872351446768036059425105676922962092000637666064665481308104726581413699305918096119931042159417071798799466955486068197677712212430263784826259897376302978073717459627490584523196570223173619361251437546616772738588649045118852201741582969002727233832787019258417917925882039062077972424659184613032685186403123916485729423419389272277238396535968286008027319946943738769504523496774998973373762477108984310049235224986617500327860579165106183291995512893275644272541506637362529391352042250015240975529957365570546819168670364331538582827288836123859675503840284210365894033101315432187113933275438505856491201332166724105070606617693591548424992190369883075151128442167980286128117403707691115672913814742716542975119732183488354601397199077315441774003003786343167657299852995063822144157029561927833885298012672 0 23755335639013661076436415044453266425564216626438584023726811049746468594413136523281594958070479173775496985471900223924684403963146955153636475092908896833568244568700288410700159430856821824043662074631602461000695915623278554272159554357704230322994101832452426022598012806335008693032728121066616514083104345383753815833659165072752207395676697695907330276911960355326569266066509227100068644354026052550369853994832748885048369265681138277451484470508461396663883894224694810821559941432697797462327102597787267920560166444249307300431759165587842378464329919026984579815362533296548368347092611624162482120257919191774255482742136740968864233553777237901986475236184748131073046498724424954439598514199514656482359631424358122160306474566581136794736177370173496717822735511056028290089709949268700357214432129602090776154880 0 -4640498094046565594013167439608918001103021134423138196000546255594629116986932204392840159156537991376324475778974381025073958197507495486822290529390774726249017436911785588375397023058893853779292261809632010278527672885872838610601483014415015017434301455053740880416112983840335736524911246897014870871401230274690326288984882851887045139159978619163717129228379137179944056535470451485559232365537811268030985838614232012875451630607659333546792741152803265398392422222121791108351857554205204731168854998416027840550819870179793550974835949025249106576535618915055643957037696220308561634418547887095598773472287807689425098629245946279955012107077231574505601533332333052784140659450432613984327374326599948975377428897539750282685676965317416796891359745552698084705398022484753742051091627591239626147747152639676912137728 0 887090604992220621577602536549300124367761237686450560991184662883716213748347614667536480243108380850464452210333231429687491244370739899909478487155431606033024853445812206835562372395023638345919289598036519765325449355890854210944545609836258303936724331531827334877739205994815302781427650932580386814481133138492890357651367868024315693053156600999772690170101720240817244020168231550420622364203969158554308650269771767389963369967003423951439150161597319448996473052983713485172944096769155475736328122880299566953149591117764640608548781180549204486106657268177710235928288435515418956919900364092332403595037035162438030373346793321454689274983961700474680930526074228021134065192528483136268334261063538038253797227952070202318717624098728347638082292304621732766646342853062375856925246840175782845759750776291293932160 0 -165975149319057916007372486134697188337257206154881038464452429169907836140962909055347478474016652299432728667947757859921344779593713057990373059245135703425089841433728398986120566552645278202617734601154323143503823823153319307253374608185108925933078436417036405027425451429161423916213254587605314454126256565146575269858025842722032058795654507823614354526094689969486175267956802564783990215226994992012630031091232883568131640349590674235929930468965525574099253916463076516629747250230706700786746630869026637201432297104620073806823153291668326004174085471130050955894070127600418957655840905515044411469946645760122215551862000404365963518441494766057729139272308273640226733168818468378640942629063023782353937813833165731045606398954223478154963338904874993377479674409858608526779430022427735423422940528339029797376 0 30399065553199472810369437621015568689120442366251199072316381817240301311014193351315275165709597472855673462968002206329489161378667561036584029491666753229958293836224112963660682646745160824058142179240648579183303894512361156076186929069475019089743793704919219227896267173793423990691213096676632479786227611028365519154109471044181922085000571483534941600160461147379399575061737160475849354353242446919259108041639474170233098428066395589244156534810619910051935380953149220620355417259433283831630451796355964808466408944379524791524282939578782444776689679755228260702084758322641358988610825791019986734438658149255341019919461224133392276239758742209433939544109631271910101078131696007872401975058291581169431779423680283698905082174312522594849484889805365532815127079347026036083034012432018407124039319509874317568 0 -5451154631577918820783250374657363194952567351653244143545321398446511188566977624784256140606176487413137201254324630481829923548967132265795718959600565367404400556610924102600472314081631844740883467482950848157079798317433789512041990890196444707967324486188112703603388818408237520918345047433051336326711420371511036464756038265382864132547823657274540690199134682504952668424435487881239019342945466966233669157291324332142512918319444393064821035653776897196975492006937538458133827453110376152614043773972992506934988511804598205738358948285235904365837317506584410010192305245324798871028804001774612951190330718489171733055853197214163509367661274084041677665268536235608536496294043737918017845105341280087960766265915481116465869920067915449450829663729122092147802202452691783660864358239680294912617152998055407104 0 957184342755538685421312343750293786398393594177677928486121122935558185175422854146124951707727002213214901952254718646801165052002318619416724325231105629031356313839817588950183747564293122760119343680274387248569364599373220859986427241905080226708615359729581086527038626222179209988298064285310809756604789080484716167941419399054497060652077698046116895439678576610883300006365869108765046039498043556805981061065561453375734497207182715548260937301626895714093352911259994706277603890258567612399010370870186742454760075769999384576284236324128928579151102137487990164137322204237832650943349650804896657776592924234262669543023611434079908862612315490155596101728576927648178560790360040091355265508246541945031590818392298162926575472704125940512501288538926914476456263395533529137425932632903542955758151366819836960 0 -164606858252716127940616793533662883145710000416122043635455661797947565627761690350955894739546517821901699998035791300335052382055044073538248999570528097634980304805102974077275375251362298740971393057585357777686303174202529593072636720682811234556001549952446481151573207661487815964863877776618321257027478097057571557754468611970787838875844901688913394275166065637712789339940735507861888334423083103831933475982325770473966361546848570382581077881029789312543948935079979915382794037929151368664098925347665911117239572653795298970237397655903346968170747541201624067405678078638274584828169478768026420852462463701123623701148758239820719500219685387821935170678302945280482115117925834844879713488584989968543455766697667381293108320871044587816702243622439763424377732032262064117843397729821436503013927959954760192 0 27727500320285295987252057044183236556724518780866254590779299794263476475325705765009777295969478628634283506703010359267514176151004019899409960398232695358860774943136745631173520420148799810014263339091590161502696609894627914364208974650417937876291978171407819402967229795384456098417902071382061642354390566506197813974810911525000167296771744975656326625330932189151696558252161951494283772230534342679688756498159032013877323525056081231401847938054156404400006888015846605067110068361972269953501571380454949968847186757464497243763625228172076585218088943108475438188848374548065047272892250376772951720811445361493762317989471853674430635124546205638627200900324290017739879032450385413222384200061964381212733973092089572048218302786050910272279058026806848004804507208689496932987738023459298189289466271464089344 0 -4575598968218901583790848028501303993331393576845426008980915871713018121191768185980344367290380228991872960382213563912193901564626588295407172558753610468330284524561402010606494013676200872642086498374624899079162309727816877250647238659971015621677478250965445643489117951497925610373195155388856054891389897181002615764940792679212282563244450985868011956351784142332190788044105782232224383137686364985893960166694971329031087732441055497899451351695517310547484464511632205664738990189318018980117964146626271389996116286466931323850016619099136064609693185131142727904363455302099455986160172912015853594476589484839191832790801120349483488135752920267214584574708301987952950451001149777887417063465855721574926350291443047257663672725888153653757346615807395306845381901643051966308021189118408363374442101684758016 0 739813818631684435579060670026549103393691822260548611873505940224674592300360848939661987186041075730451257933602433125277222319286572154097764720424510259718043352894606854921236668763735451969291981252834926880425631227764076532399853990697079747375504125276470148261173761638593223210809351546262523206163070786947767262613881082893026466509076022010534556134818015207864320659646361555229795746307334934783620824011152468565253528993018494253417466065939077139300124497439353291771901517044889926661966330528770679897761697838032237034604447607487512837016030808904173718597719023922344781955452453892771119557063214237290941306450486711812638994624182001338191877502306448130044947620917992705328673652953171476527227076965441350799571155025470125473422937704234671791486792462135192487860035040085466846383285857284480 0 -117218413129578200043534293517261225202930600713771402388737365400833193188301580214464221374397946027437187700610728012347940767811320906710257343251419482021606172773434674626312146293144346126299859358879523787264026753932231146728433028614398897619201749343193211814618471213855405725086467767860513735545425766423375200806819477984863266880270451884188865148518160674342992664317772512613602048286349729215032132935340036384185844451957188274072428292093184804110343689340369877133666856526617144949526129806039309575031658548889108261918445712591102901304126549201700154134775670675297486515035215469608444411140876035527827073215705786563780071423990284990804788223263753167594683762119171482928321575240860953260278597363778044853731907012667643515251373779915061442101539696687777833542590551644749594997777876523520 0 18202401609381025670045020999290083463758701459249911892433751546764214394256997722935549486510285318371085647581904476529528828911445405662867998338085844632928147536911621968027045934818864277120943660810096624064180396039315424113632805548255367372348372615778510937389053101458293901857601202370669865478714773896463049292730980491616829932073134687267632789080137419937547855787704226135491461285903465646178032516452480060587927074308633857637654042436297046540964292529384568001979335495922260259129701166214938873693362050514272118582486489590091159059842620028132067771882714054444013396519388533803414987305650313274364359329098446151565554205288536141142308617600333197533842214051560973884666596148263767955012673957556027436999401004252245534851289240642637823790780541903848974906731593015254695796251026713856 0 -2770642260646337238101486715538275979285669459385153256088431125518058244846223926948683424269605898946897912776327307027651501983964363633160947339726081098137317036228624671959242005914301762929908258123097730550011159607164139217313660136652522542820106979646025080039023751584448125610162297457420213627164290136891291836231166268944357968681919023364708492844662545766428497686419784385235784052070640903296825634671844694802219788725355963962044264874967821532752275838946288749103833086256370623219029689715913424081910192315602197817140620053942614350272710221314651657718883023678794091101484444833803946236502115800316322949149367480208676196599797076896993802473746289908535818555983957459351518578320316632335526540498069634503487261641446661281976346240465731091110076430801942934730688122065686490737542618624 0 413437162806951604295692834877327620833025956174009743749108090493433588383074403405853909037652996969076535264361300550615295137035841470946715762129886265595428690328684743504508895941482030212235888791751796696374453032272015489574175856729491441786259172037409342239125238252069254696063344554640655044743829805214809152562597282444504625485160884634520627645032092804836561984951468117139135556675675387006966273752869664042544771730758204660399952362341392280207918265342336829324688286998764165911126593918338086551568103817562585210077682774591066247227320444012732799073049211442415887458197355695237046885323886068160381014338335304891470276994053299945484977803866877724841096287978202186764703463700738768478880620792168632580224618267600476736755024386986833184220870496450768944187526495657801698598117923392 0 -60488555670190158069497770079097431941710005863322420743651373849230446156622318581060764634306883819939646046353885515596810593511385533407303939722338011639334179238470823772830503990134940615474558092362087483479913799331910312884610389150717525745313402939264504298445220706163549246840288385965409337702249953561747891569563294744493171217486335633572368376985490124034109961463111448050981656906159083161705996762546083617112439664864715716302019084545242311004755367982642223899711092007191727701424162764510805878887406278027175984735522184547556336494129727852046616383056593123541293358175574950703490440812058488229013460696697128686265957378591598560578509075872043804007275647922840316846197025694400628993389955920906715412594789704482627493280021884682573389124614803906946053385078669806515598206296805888 0 8678164956094171383545450894867612283850953459449498030562262072755104549559920511488976426841092473053113983878256616430614526350804905832412768351182930988824706639209228335371427672427546498710490279441859439791047648072896546878014417728443422128879070102980678337289029924552070025799201603155971658131968117934562343580295724906392719183317527707553622622548627325608616993937377086287453437643091363274958943568476409514418986254254269335453461610907047926403194543197261565641758836766145465555604900040221708976283465016011920003761602593925180501072441198381485222007743897601226353960462190383885463057751549898834306621367062754002032642544030597210392680775554611740221074300651976020903520240338014195830011764352440225607177841820533943223664001850538648138219340710842650897308861881738289036562476022528 0 -1221037271135405033736973843809647024599715573834414994958443007611490645364912800670525551637101642098988524019673781320379346778546652598439691792094434597266087053161529194181929394703466677750359483306435839840183772282734874538220713702107051523774396803813065536026435134135964113390143104454821741025099275119687166578120005437765307457102857508565221207388631364398683540322342170373191822200861348437910773590499566244957721873909074268246859998522714924979444926747819468056366053331302051975157698934940658772092332804106692240658801657097534942528103057237674827069453780799754788421514604645122163509360070538486848394196638674267203734484064048203014097204541481177657706348828887652816684421557861074147536783639526676735147640172890571402760004026848887844050471359162928243717793915214624601024307205632 0 168511932501482485472645697737417899315809373580846055803970880155784141897599894621296217305039548355984389435590990737522108091511699357854090059155488547243905890299884652778461455175470832340134212722826845179220142121294026553806029235685514685317290720228794539868862846400831401901111992539083186843045171635918034668208936644793994735510493827414376336288386233708133141869610124482121977185584132157189213735518381311093684002829112562432880342655137060571223450286055467294123311174837656435322103999533369091140536343641147277568191409850127964164208342074581661498000584449101595204887424177592877091900011291212920170572378665898036269260141968869814653417087107187074211716573802867596127004590972816831565377212951276601228572098145830449675647279524295245212230176259019636322423977707869967181413672064 0 -22813218541994748476567890541439758281967789752175761541173688009158311899118149170909906483872441802422281875128229280988951919798639143466753101902413553195565942379700925563642525596449532164770872719592279111285383794878983022835388076761091145071781350909754186909824067146449793199343960801560069822986137313326226670977762826030556476438049125042263281156479355928823364046355209838894201719301201661334818539177494381167746063858353248309108309665734524748415978738270473495304977639187648558551957761676034760687209512842576397841066610640840217443038015723265873737886261691220586635432008730697023845704913602456457302323889242116550484468910013089726374435599855440103503717794868503554590560968800530950504651243079758660457578207741061978130226746303903812337591852512158814951731841581086204618734782976 0 3030045506786258771253735419456579190718315390092831177817698256172174530306695824070794396542084113435905842032935242173926390297369409836264641267396425579932263465163646852574449858632274520647232830644196796546816389730520413758148987330166447752117698530652623608444523559155583103993588251869850630912651949569973913925622083289303015235455697472873597716709108629578550500848796979033536554316086556591622756167989488630625459797626926077521717351419359989771311351482567474164606893236287913073825003660863360492695432996754846085746393731043676412129856084226850008550382684955502690806243521573625027635332972983042835335787714763587408196201577284697558977058190980152719510962007365565624738100227378286889511303579553240438461852025180646431412554215460609780485616043583174739640038210710668430666072320 0 -394884472539702538926497091280432253439899620183473207351847485528640035581166872516640908516728593233103328898601655722877268095753037813824889957438233947642452419719246720261366673058917376221739925411445523346525436466260597013833296988665768169779499287933471030408334261828928767049554218870797057749642924903227508662603771181070315176792682694612617290197965088577666495565588765900218472461088017072842978315736828860970532395611039899400709492451358983251925485567374456698741960138811675508946365108494889406642412470912281619290205235085579614174078007879099628317469430926123199959067702080713440337844239453327824095366829614770147275555370968450590428786675183600764055698012959539639758544599385291208273703072537758663357641868753696811764489486174413057373551388091311838256753285819579759385218560 0 50501005955259752443969646542715918349478654216877349656909409367098674066307600234329670632967593345939918700226384150249794764096452855666944621005647053118026539677335210125283883679708557300025637588216943718139343518807455382891707787275517720328453361419569913529588181635339537789840180257799632942259600823774891370304748921315879879428817552375262523414834877371733539231765329732379054353130916673628396972310453264748302520162569694506736796963137908925092737007764141931428372973622667261802870329926869445980263813804798654891057330729203891964460672923694116136368735580805938447633078861860970215686366473085282543926524265318570717643547960526717564871741627473243397418393154284447453050382879087015949494233909758508510075100480251542878615988875281718147424175567009607595081167729241086623217436 0 -6338535998063705431134418332209945352779027606921252415332061779162602316681128323194088443432192280889794826519422464353523906291243054253256678565283933749062477845008039758808677473761386386370442722150154345254978616727646973014536728537886776062175867598161010518648949554837889983133714805563264408325846346368526136999388828900433190607017087110352276386270383434750772134818628677587719347404575348493078374360909022830255626021550285206375077683944620215567293742461087192978311660396044133299179674558871771851607862512503351778647027601385273872225832284406235862048609476169543056819317648267545649522684950917511484896702658607659066416679556073608439493750383691582364429787219734464092091925434633681836896085547556346083256449163876221901224668219756070232766048045047892412413521983295094725835264 0 780882893633183458938809866699720561163322709870357714851200853687697071412132246095057508631698261659535831623991907092588556724527590909738172313755091813824948777519314584901559235893650769939199110987510348828244045081538915754024111306649259093415074480056398850393532689477529030742768816171444511438180146725095414939721759778395906585224133297095472067225618880977540744669863698223733512558300101461567740725113719176103010289889351376544853246509549977454752247785441877733852581676971651911908924741485215185179501540239795354949325803998151714342123213430419743003517636575512493682240589436756413485003954915176766788925540585981103835265460634120234602455649154145866816376596476082334831800414203352881916168559179475113428752653661426783681589402094455117550081603019272921093605837820851124466432 0 -94436332060044933478891130407705442387451620155546050743743588103970336579614114048663449620928518382986207433076754002940861173989068320308900491508512215065631950754018275984164883256050091145538145751990563846296194578656427081489405760145563952979375157406741887939753808729706150078092371128831036805160580959985759052771477227342995350247396396896977660780009865791719782486457231197780729471367683421193206861366484414976366572907950342479423177740335172895054564857198155853972548823170663297046318210475093663958047233899520738647108170737545659755747840039164572597579078513164166283266867477332177532453127267894357889723351435705426740028993668918767531788669134923534528387509697450222824925414981426696421195288749361547876247804426887807652284536504562468630502769347623570546943313636998465433088 0 11212333396557205768858972049320407501551120859433991842057427555920736745639992212897378411965190130675165009867040978580849013473140571872907985433654098281384715710962375218700301137871763664689152301622978584665850327326780632564227472774879263689387608875737759278662319129997573574381281191189879251452811755850690541860645577828416796887609140006632547341432438463213814835800224729676164588744469480913300316550179562297094986810592930371404172756001371362011804000125708120753865595811644244208197589572798673380233259931473921905696627329847496762476210891131818251643418930114915651958732079487830751615194406360033768039216256725468536280920155255076085850323882782932905535054442179115499365446692953257443260811404711954820863349772787481553812890681145623752149850064766062520868415981388157123968 0 -1307083224699262939273443215273336382809778225412130995671480558418816743914362586098085146759383131479761515780875479764173778288135179592691209510785176192895176465829668673720945710009142153380822795741776696561470909669199761599656581898960553485650525896820648386024929035049210655250589481839369053310706508109651685805846674625733962174330531813840182951538830177365493940108632793909450309629972560734413446342639147807531796765161165578388070341672691565936514067283637373263705261023633923884764605537264370507305969742974917725552768339611057394986546127411865594562998422089567579762749687337206827502845516955828600305874646943073771099611349174065849435751126193158356879426904770970830176015025644256593174307167930987158961900409527399225510226843828548559755283489854815035554408737246282322432 0 149625878659386644710079127186309193157360525607448790882030744706317590523159606797254113290560895583606643016226195534075098013112994517480365034111752991388051055700808358114982677161537289722162173966089926954093519797258021791811488550914798976208345831397965536131316890420863279611462514892008523026866280219019178187303198699437539537308094253674010772577698986388078670917530361436056900382723668502991779828710835556659238476489274272417146110314178854819485622562387091303298973266373392473416681335702691783221529910640455558934199931813148282745160641815898152608628649791115393629027684008728077878904695361478729823525665733428586431554780714100019615735390720625054855520912379917823082043832655766483763870346657763738341848759894517110212703888122973762931610310270532526994594250278598156544 0 -16820990367812317741065887732321103984625768194547040331343914682401281737732642886899219453142424397294051818647600970817848322587488275955501840303868318428131983898766751512623465230571844973592610504256695967115953645477054452440248919804206256674273305812239991998538020937320930464291436084833450426089823984186380440801421712982776659420010486818462188380530629231203719235909701189347925306130865755674785080572983336813097545362185208604934298480115481544921053341627345263610500591751018935995242533535818952720285845120281334572648294361109912532437458722315637808044978605224711808763366349572680000694430060809354238735412343379670534370686568298349779394203027457974965750332646046977552892124544867315345882076395912784432867348854776159652991981450036814454689985772641611842901405608040121856 0 1857300578269230138707832920118605305511331807016177366034470184367544107034152059347838656233658149274622232534212076078950600438126287982371418009780958136622081130710310811566739000370782633845915743397364754301715660696289916136628169369844710124713906465486041404921434025279650066407215136701738655642003514625925821149361890724394338718888910520347296877326176938066420334234083974559233580978187211457090137533499234524460577495189110768444424089074075639288799639632213078557532540385363135925036517233296354892881459503292077517189378883776397109048374344024101126275891642344889851955568172016072108238712028857025480884119839967346527557048155028411765630015898504696450190746868428880156679952736745655591057132752753786993034525511581820270917436258751022411345405167108728636331225963364013760 0 -201438417163914961042347468794601383052064918930029395315257016553015249589077689226282289948015228603041755917664978625114665950889450642251539702825021472071820739386052000058685483454122273999055280986563780615716042222154608124019857190533154701355294109067414072263510876387540746406076818148404610818252745293503378248866366024753186375609050806213047925437416175269885654051397316345893704690331357752686051030592074414195052667527397079026088731417266178106319830008994383333788425398320079375022288715702458783460242153016146752323627887176583904293458587723417625772436868836509849504380971139713221259227399558757043662795572084240361185784717467056943235411488553755540191496763884767015958365432038339094353661042202046920804976129934913274006144325896395170696670069607272167644943500928903680 0 21462231263449537173176319589317862825728859206770689747052948701679431936540826382722806841329821197467113069476417399765518767811021682498758460921944721876789278091734020382471021498147271140799941891423112950565659930806312283006657818191578400771850257937811923863184629346701766778561108550788915892466010289722459049607870113773360768418469840789800749263189454585158373026386357194439486341392428432871954445047798028786364972704655055403043695480359049899671966643178233347674641060969443565130589104349605658991359277943965790377829521101375590645054850085709126562498754541047194531453263566852571192659512396403219549796429764772127612484975640207577728394798304879003300091532684198045668849861811786223779074976405191302893673560910199097865420964606517163951380095917677650722328110021916416 0 -2246581644588356451046100406649315525224402654650619312677498513892958867857495303974333811788223344197668093803650445327108908774475388685483303959007919741974882897751598486821108639674881661570687571625881899088675010076592990313762429440784972344353030686891520525078060997466815529881081037859277040694767289282419343363600556252859834355376658845440065884719467784120173230217814123227248062799076282808947854846286036506451849701697902780647545630041162679662392116488510725704504504795729698320268821810867621190640407166705087889024168587704796445776594057294561907962136300062436182674493348507831861381200967276643491997171519873393452135408570064932399170284727143882708276457956394702728590537853962257638494396440662290825040938789349281904660615131671900738535396499634940538761180596411904 0 231060621793516070122716316534574708115667188379635908187975959301475458599921198027195382867741777509768942768285852705789627620358743946430439351187134152318131494362381944968779491028991421722549507330486427174127396274656311160064860978679674556413580980060740661973047262025697703881925969278736427976308558234041163881778368802985005771076166940051966784879457230159875125603198222736468953756776540769629732383834412248866238928550989239038554581482965768609767996762517612672679580377142148708851571279341375951225397720120945453168685093862277925806348302754140982171010646704217483173094901851443932664761340696847594406715761688408353341541781723044170510529182845864978671635299352286024146837374691192647056947640410175557769464775849615518876287791259144398335745693269308879671227194778752 0 -23352158811101625691614436170480408798837561556573942673965199859974157788565324479744082689558181989787289031327759540135628189156889985259934143193904706883106406621432116494197299201877058949841796115071555360902438704431936853200120444201260054112621400881339693975155398743830362804290883538939994173183271728667688803746170036283071342925898919541835580030675134144071364057276539948413041642229819664931281435723062491769932756746906319728664518120659561970692353825010705004898562052947469602059099013224864365006810769398329018749211277375782245769746033433470963832426414090259423849409195824075266948636601645043936493612445183318224524881360858586898350786957825436528879568974018148250271309731878913566008172428531749322620968976099790931188272069246887150067508606385342118561387541856768 0 2319347514148595687744553180659988383648055024533834094253421909666261281389614838693912109564597250863235639812521832933823128817928445840841557257870260527140040194873482535923278919070155107222566923955886288371969712099389352930997132559060980982397940152553568609599448718898304093580680387975829234517213978793655670894499960083999301636820880861855016954637668451529141903511082881191616022964167546488941959540234114028739519104642234670004595422017251333520372853617991821907482332639993997476845538872852947568858324188376919265487889748666828839026017739967500696198405901859729549616896444930740135457614603822065960152872980166642117414459617732065780901014652903397552814229902571191918277971463448550066036375577417490015421514826094547161039897671213271591207952882175172821834297419008 0 -226402907384997941811157026581894634804814751300479901625007644006516713566380839883255758131727440404685996781983746486779733837685361651021216458749192319907952269287981989290176519391071811738509439206985979302013361155781563889058358999302251848732589135282938383682544337743976097999364921419466386956148275687452711518174317118765584830770887411782967795040121134608795093857689357011463338824213901405694684191308423070914660750681215131508904723531403462444688496886068952282976305347057758467900951013427199821661806690927849887134114239390774511026813611359264432241545874135529893017807470016918790639141020066275954239529413701561529082274799119313648706287905751175120051573863613046057943822992003245564834638127519015259266131745461225989633066646411295280157201418356052130367663355392 0 21722741444246973442313700343935558328509282122431328621575354507060133154328194709618759801312562256486680702297677496610296136070661361151766218719483692093215168819208081549753592691360087542861115343280655697759962136088943872030891390784742793793619725374275116313346665534995804340225667126032820989259460290907263877323476355933320939628786962153549437814782167431669158669609666173461462065325829348399256566049075816317417422157712280615427453801707211886192366881288738971483866916379602114007608254185104281564207951235887585468675586526728778535576953868549219198234994932734487230727857146507504643812306907546278206219345604319998844234637121588099817862094590528477750521579400369723886624891428216346924006155545926716405658046887308983249260464324472339648418322243548432185311093344 0 -2048812390968177611241017015770805023955798185443003235234644410345565284807568862586843525731149187535242394643256416010291150031849889979477950683239887644547538493986359553882836570049968996822975141298608816606947514327424033787707148325714157347801233097822546570360082863764342808181360993940102618416446003349610832465822892447013187566652330789418646202943759058650036433389196571782618041024839666181166432616746193997470714491893789413725474481252277683962073908547794083291175691064004105141132707041800282860238185228252886253784464124653696278940558074077575156695782586040524527900439606256374480890513113644198632266836216162119811998170895153868854482818842739437555920241388332714468555509395527902826827394945990028648536724815174758924158866842979270526129175155892641813820381696 0 189968917632191773085221076790870551725278147594241967989640305057968136507883097808021994086551428266135900630660303304914999146308628064884744142636416786266812529763018239503213311228713065683854112157132807046676695392930026063276623946559590938985330294647203724240528797117265532770134041907009374440122837487215702162419807193295247124307056699499918957110267453874476600276648151299767318218704369755225965076986396281240394059814324275664707286845497363049860287265905962903530004148473337939280992054760827671838417831931259236871486657382575204160228244894918926809939556755443149372211975978968788303283190033143106018969987847770777132921474415595385588179947152209472668673595802459154785601628126321669883093273328211010827524066811794850925774523071368695730250353412674542959409920 0 -17317810781334216423566586833355922758185612538394086801423994077905894179731227143069114917363626346402857646098186097388727224952151851355321097428897115637891263316712502791274270458518472274056132958220079248738958968194906967864538238806874962757291250168593780352158688925529879287287815952552900769614206175429739556278709351293283341476864960919046563753472650676710428315813651734547094601244120018643787494467881391529724448167458215884403152283493314297636259769056189672401747188769886796169413234578255012236189202878387128534253891847028805897212853212646872867008310030534356199204271734745081005476094244941101339088394995472806600923548152480866111382510758673664446938404263469385631876249286199693349671884119117923656129220223491366880973894768658980366388114560762274458979840 0 1552280614263880143174443702691674530372088909706658580508829157951601111767106464234560651305436778088733679176697196814659004649916348969931197410646889944089939864089157839770279234329254049592769179456307798551602302715082934110127699682045281792376514769541970043529873526552699489627790429564851585851104366749554140189435219822459579289606497499740145201308332448428140600812795276638135695035050400743643714541505738237818256724017554543801856975072167360392220487319490092703930364959615572525016702364829482889706892830459158631070300056425166862360543792081482572326944750228711224420414747904726731307047730472276738826821084479419494906816288107369167230566643282400259627599548634586956922010727173421094905574670346186578975975927144456639923507704651906256350793718322345494400896 0 -136820267338979394518862152641178159492302764537206049413719618916620491621551995693737998089813566170174575643893589378258494952174244000164198536288347735289542874475073931033762735042144696647970954972576546354779925280076711697965116098974270609835308331444605259438052165755031682084841944073329745301332892368343929301368171402435078063920212808134299220885457492358320029850056311828977647994255318080103336356681188453573417406574976370627363928823988399692890632830372701755063180014189764930766589499257249531035078364802545398726137689401570381911190723242966602951072778642713657970822217066900123359769613381646468819865669640274866061749845317976384709672161623413935567605332266937025223192504308862246342546270641033056747597648797508441644496646897954707304786841381596208247296 0 11859576963572110465065671039889853570121347381827540297177134684155360247450072609803110959103401209734350488908521054343105159547164005111811296399157511203818905011230479040921005606657284126856872859470425172024120842590178500597594537056128089353702343659498284737974127998360528468717176950781823277103954738347991193896568774549878494736814528321215757063356125589717915152675732679239311795401612003547517165766146974906705888078514145086826052365384864685160104417081965638683647179631165559048181560622697938986962767310039785049460379427080388928092802512059350347341648321210889648227957515307352365223577248807868797278426351385096238816333867598091349563363567653204272685681066213538958791613579228573370275843779072267915188005918715616629830078781398059215315229790578308475136 0 -1011024287412542086299783928123564026773266738110848003255851699914062257848149365959066576565693826263916395521080569179050451911747816286485888858041576485499536703617726067694870649826759097986389027479331634467838841263855441866254251311572018521806249559133670567868331848843588474778907261967164368786860292582440938533052156841760961719637863768110015858493144334849188678635766789304740824501539320226774031792116650647862299623308860708856738476422073537232318277911341285963630025703644906732885655177938562817740717194350032935805296556566304839468095389418669439202714618086816123036197896811550813959066424613661129253399131797720769981106299244922358706662124125542628441188829263273844013910253756322725191925273842163164670716636596886309650654237099433014090587683959742948864 0 84773895994557907130697152118274562634971388483408205177633235245018945067724180770357641684739398055468290771705550879468167067897627463281610377652091625272081069164478674757353880044028129448563220595469918192222490205117540605944113911439990121486943194948934460665005542461462332104331863690684391618672285198943537722575731578758357844182942136736477800435010800874702189009147761552807545337449820325325550805587960421139646059805226027398982197332042863335620253544050314000772020961822866637341162237681848513616637839602621192148522102434784756865020415007608201325788823103630108737188763212572984608510317438175666766753117676442879311808576658006760825399616326245589357222547607063352011751869426433155272001741085238925898036533135204551836864505539100774488441926516720255552 0 -6992055649131856745626749185324663190520972610537649749294225987893099835044738517741962159703111191073561286906903284127311058464656784283122031525703317638676197181475263541649665072548988305436926335075834455742904741451709191860555835545904082831447768802891082249871609933209447398247573314388153069551983294878468612728070307655278690024243902589368660661042313041572492157152880076985540441059566603634191766773020283666362192846447623196717989815233755217688881775320597394175986636270551489228846667183771421852389832624938627905974527251744850729828902483131783857909933752130096257429053457376171072459133894995175481808529252272668486118819478922383455583132430430774097372851280785420816045374624610931732754655875048642485991579272295411593916848222291084904239354030392314368 0 567313730633009217531928895843458377114952813144452481518561518806464315515092678653166887995408255262290612034979208318036967793137652699623370679391013931424305120251568945392448328821326712523282405859491983478563781947449174504908985016184695733261852680376036570643783811813624109404004576087797257951837435858841746901704643408777766171885602065717324559844103724533401179660373802058185609307254786981942401813944978347675575745736627303084224319406306976461418363655584874027014709073400716853409808527624193248343919894454158454507580858115466726934682728111749612511261212263128953204970169494856185179585188837402032959543870790640715279033648817254950283188889767472506361252930823878864796745097144017837696899820503966710326373033020955503196886231019333766428439942565314304 0 -45284586247135749404064735804307953909918536512931810479513521647443130566197239116657671374004350125505936121674825222997217585269651072279793198317723538093740895152978465463799957688235467519076119319995075925532444608076556548706541919886585204731508450581235028556967343693030407022819250416753727482164055480964760259206000355316697895493822648652597837468408499210927685178940002088823393784094935801234854428751288972180014905778938332206182618406032971665769762081124807795686482061134776311136828107604601898150076683171462148804305882566858034494955865886354547529666509951836277199790183139801136241275124510382692256285859622157236575199716846660661571480474582427967264663820160358133387641418119487548064763832670545345291177381554835571943340058400942786710053254556204544 0 3556466459821625161209994601999372518533536325768122959995834512201944433003402788194158268047235204901086986880438880511214227109276957191056181924782191510265862185213161833425119694132941834298148262435750469985432448064587153010937343369673756303109013985735386922916785487047569196531948020791065760966121289412240528763466210536311773261148389792761013609793406379034847843948530548312620760824214871315725972539457362033830550283745496966026685180678014507324484773247104995849941125096985433095697769914581591264135230817345813086138648051638348130391580199570845118933938826510986034188313725310273857723270110974122268267908204200268876487187592683965252323617478282789803772749908196062741224807624620228498580078060592471126095796068791393606355803874548737803193278421956224 0 -274827549523914605512984128585823205270160418045915333144840803378206068772643793723551051385397228693899320040956901337188464675642402043854164937195548283563482946766117278122633291509601086294451922619438796965662385588285731654384803080325064029484618390837330918494799366377390759192475839905540744598810711348392871432062176336220020567037767752326207487467639798528049339903262274220870796133608191103360079152890279620239640792653823192744437346577855093190498537284222813702670672008267310981963959969121940128531540235771433040819744888441769429510304739511477021122694051637470341595485931193088573279727241262278240998725801503343937519964392867698993670611209984575731950389019755348996669958425837310580850604288359484560362125949087074962916296624295387050284676593459712 0 20898090495227445185619411241223460997059204782575754242947250078381227302955170424101382406588157401771451879198797905887945874452953685115856973793460669229720374591384738578748750479612145592398647496956370804737818561620588807656588651499609732634017111218902074632404986854296308028903411995224019102088110210667859074088959237623885567212488176838105349707632196313790970042790232524674404479840303458546438177716089110376866606478761380335493181910255686609700124200128318032397588343744423211533054575639020254778302263281220747077299888857425100893450444541115988008988551972322336355093670098795014186585879636028913743385432363897246760793355107369365798993367934485764596988287598430398730592092244257295651393060128896425151666960613437586276001402624270355824639244840192 0 -1563827436475561910159136201817542822543620922251015466721461193597533851853260017122533373473816004431403332047527600437549322463926477469410992173149927460262996582265616946826994098817504219359646522488456431000300772086716163790538872932484228005139099947295574863387400290436067771846864123007155465748035837421510774935421840328920894213225285290424055063762624647286502534120476963941297964801187201781133813630844888876433906442655366451830445386177504011442614265405026623114926512368230319853485587050005973871793205083833788818455284868892833008957736523020388041564143747144596815682139404758493949145073803348083940952203159205354883885340109075660731820220855174743564162628367542592061806710765058995310771978868659784511495079110633289557782821508039157722045344404992 0 115169522899767430877022785159259076713018803039930388026890229845650637783955906364135182854159741054685252088354660990336718247203647479447376413589551341228062573943161781884595044981324784177471518170428572419991837056129506977341863384111860764960211610721900835576893707118020720285860219877168452445609920339746095030282859626129466950548096603046465241782350448857949097028779912652877245792807764101798776265851718031662811944988509695491816591594592545860899402523085749692030139272499455370242732753673783956996120334351277044266033709030862651018201336138823497757815581292752481071362654807217604117115965734053941461079335915493014870130681979127054908836417819770220280109800356611490293794561135998559810462223345133209320650554882071642004346347348361414932704872688 0 -8348010910044574583620061272249304862942823647624287351836829435425693524053205410923334144828378640793026868783069470017237795999588934736871896149743309135613392134530123789427929163770143066590702324612316693519365294313014523496611494710509973308046883013849755746751482109414800007977729263228791525282306499891569791238211031390249834617325173736516925256956856513039502603484690466922086347664135340972472893806055817180480014578331156392792038375284656327947407482503966506564679370613414170666123978684303711881174285209303209300827143927466878483738469290742342401825563539244092748396583932633645189053528128529629610019721952197723342223223274493433745060772812426529707231246033415689208140606800026277837498022840044330915156526800538142657634412347578285649506458112 0 595600277715940569366099297111854887648726599366015876445667310520222601761808975849666623802004009315995755309865563070084514340520481029125978773901825596745096326205688064033292095760557856737910467616613835081396525527671184409768159979778162933528879752767069945713865240932054254082561591333582022456125858708808819083926783042337645389948339738799598855905306878733577298049430934063626903355152383967562975352543232163686648655957950561005631068405374054753182580445551791630705791071418985518092011144090447208444118534343175627192913279138484699416469449630726646226274815546084560681532075761797240648189220592588343724625101469762566138164163252390267236666232123477845630140899144045282100132666594753559886726831321000875254420266424721425260630934073812484580373248 0 -41829485904785398363962559586647392564343547562627700221481777203598734449480030902052147362290972212081884921682783874481239884364532364880568447196115185840055767757616813079885940010525815714065178309557392905161659648532435676556301936639039447698346113319070401249634316175279773048062352275215543541221852498171399340522809251123666555153560327402315711926365820695198657743460870233978871706108283535276374197575441182216611421146114116501731559792281144451845851254803867098409827619120485720691559309723649519773525095288307154923295302836211208974485915116064970529321484194333136421129651183021341102860408002818475481273670032505949747571770721661589789155090884755214686799002788588266711600686234361362211911251948933777837989695776736917512013787539073548496031232 0 2891976742823936490501448728672481163400971964315980314146767426139597704240363405149083984660235869433639418422507090018084630622121257485850516666634734363359546145120499862982114257416954133766912788277534046213408604926451816964270274342630853188048592724272895392889867698161383061558691945402790854710683151649208925305538595202906005863044218323448108584693540442786446285592428425495687897532631484960670721415560894778398377956136293652675025819620098355304402231355719519588665129932701856913941231463520549155074352076939694862283420206711277345753891090272077367339156920836741359029682566564773172968519207542308919036475409946801238803321188291550361379835341863595085250620539060250806638220275034307537145556225778442332167101410481697188723160897416690649450880 0 -196843084143318989139013401776430153036305105252494828456671946826102505344091821545763213756611559428173863221094687102249253701130960019951282644893438396798572834167190119545230885289932608736091536910480657832439015741346522911510560023647953362469378752155993227094311705077555776264810676762467920635501739750000378325611165986288360375884214358656962356941017115959495624445702034893072273098172226825556611459750581003914523613878779614669679039667849159584455819600382182671051125406007541625974426456457236979637778850710742787533968213221915276150575586003969349906429372096533636806165897951332050101407228887319239764178780793062847349551582067546322212205624500927688440320502495615266709410389104388210836672303873884454607038990707184103337287007656123311190528 0 13191271880612196035952279654007934652494231014946346405812651796076374605446194952647473622299454297805524035062135741778184926805008514880196915062498568486045974166617189165001328987158668235723395164695575844541420115045425050323339115984446228584435916699253442675793074804822748240129861829103260462928573020752665811089319515337074346904573179988580901062055729675340912769607946061379058537593252802675233148893894244948931341333359072887416671090832122056600047914219135243843183826627467612099985752035501692201117247736617449886473105330454863870156157728089288683340423799448627616837594584585026198622110084088998393143149939073076661089494372553039854292395206312629588933683332952820007779577753350029232745978225586916179804784259094800215897707105502476894464 0 -870406192073251124971262361088177820485248323540700055865299944791036942591052516619930622161052754176747149680893292199050384783370731293772568396979441189157814335179100363052900801541705305604877288525978325328660028789411953439897153557446617907591801443933098750831272287573321014816297313935081491467595060045359922766205140002029295001661697760401240718393143333526898610520466845163730891817821650634262861503458356502137472105712219275775465891878428848694084089288946143603481944135555749024438762364334784131736046355445307382878991327675260797648340091430987412227080305131144066647053103340475369336056461329550599966869011959839016854135193148034495699877930128406408137084060646706343257610615238992332309541015576602192111105829943936167183607432476446221824 0 56552695199547775254043915701263029610548041957694230037162280329454357414154011279099128565920957690146521644896025666612062311544363203884116313299308817931439364775240570144078232266938000959384379809750519832069111015116861915448183978833355935644072841379156073660783927145051419224238039346263890381036862312071361874096179623975270429948131721952931184690020406890219843229245799984594795095814523313506326160641579909685589347024938485378074396197742893374033518825699878754213950500637357179234336612908954731946837728052461164834262111232505232428089678145050362032633774820790059998678057094861350409618887036343458253943155528383431563033791465198287962789407585816326512177473347847029995542039962933827678782881179109328060455456376751769735079297560266621888 0 -3618324650146603077108644216808293048159555707288151807051890574722600846620696368811693129526962520264830493801464968980771996905547498409581244031229406517612936353178963000539960694794041630534630368712182162209044610660063533607590800641351564312875572683515375576140845304369848306682744601983202406858503209624115166737171491993353357397387741882854247172477534075230561918596141750483272608101689473613537102985317720035401762138855279573589636488047197797184423900843885766272505607604767501433077921883181027708217585545000929635727167697655779650294652978144506201420286704159608319312274316484327787610921957496818464112582894910255978356052382309629436893017713356889190678837833543847290183025284436742235377810460258298165236379399242645072781173119089297920 0 227987538095198280437941941996468488379803831497622082565884259760294867762220110236199255789944623982974517035906644320065658274606067482509693516413832379645430476527300589753444949439770080762536567356170497625168195248280580737750106441949073133328974803150617890202525209499172526822915269175159314097983347101668772080016937396630700814658465697098612548087689511495245422241936720507027279488051885030595910821571156721797057512741962676486505688980604401980130718655818693381016729732876360577687021321016790963446554660344747556780869811233048828695934577075852450346569121360139773005339277176977397739366793077084227088829716256297756599896941341497241032680783260035979794367689480578474421134074367183087511780624742229081389275507811009135659494753590376192 0 -14147839634434918467929287595964884961310937035480358056476001759133184829236743348700806331675677773771685647658568263151262506353048508224785275233519415805167496186571655066768892785448416982294617322908349032535276714034866745019340433109487784150143660308912669262117477110818038118127263822423648355661299609713917585346854300414684303895559614255176590714634064923831379782076546671471951435533637090962803964899246587784556761978123694868276784590577562004115656887071244910403339866465589208232232307173109302372252563226907310773450155084157385071360805112364395301561104113723101902403669556641956065158319260875609186642229885291175914907734133525933593302358747566563768770117483346159738081598418338845626374390659038019894090459443860078027913784587173376 0 864709643696645265534391751067836909503669458874674872577410017657632596778414241195112620146352730571859139169386636104579313671485203081108919067919602767473913469038129650027436785293933160992012770927147995775964893308941315421517900857693001031843417127111201302649432406274902637188269817602494161191694331531781887837544250499407519211599567537434690843477962147271622891318243018766030605465066854605659316603390781687877208201065808619840672206829127694549425558707765534061208149477213784412909868391303020756734494212759959727023164479061247266934585143178674973600003825413919430593343278820183362218110760543065883143004882892818093238125188835734059053271343009582837207530855425224002874361815031602347840797312995396922960652742703298139285744713924736 0 -52056741042952213861575492412206705455107535496571942731891465435664220337913957572466587037315952849648809398115042366384381948899428330766891014129562930872369631947053317192759448042533885110380577919301240406675420094109378369797922853238169833586740690116113840239823792310769724446964342504066479858765096935649051843550535690477726328541977097469910191091664315564839401045544727152933075724437981199441228963754436367917802808957731363860670546010377741497130246430532382817469519995832273015592595318006490830384572338106737515389795860199553687163373737374320294240774122649923500707621639341693322247566973568617779021894598650915361666572409930119703571787118530012160440918156581665693228738440808018261251797266845376556217199590498400940500423554130432 0 3086989356572232010059274470722715471222277078690086830577621288567232369122303449866311108916780303726337762702260696887496614116097674057661928425271185255123486573107339864350376912486000096001241897712843183361048537472655274468176364340993006105380072782603187576749519245365644470070703907924464043208934591283825116767037970679899146393999972428579887728489242066460093544843048520674942286867653289103264100496793408623959728264315093637232200419326862445058190180970659534060297475020283684665673065855148240385971325898307377727930313439656228367669544202038039803229069825436335644578931195716964338293741279816571390642518722425949251764496667789158503699398702453208957898420315242121518176873221509214839001082268380422030012385527335739776280899503360 0 -180330587204219500663399068480421078823747391097758566119997054111736322305403303960557952081072552148079578243122360290574252908242911539588691396095414455597344042359536094698833109306258999640877675760136054693921045660721102911216275399555909233070225185404162490717828906256105133532322813689164926678034083536593677683020046171985070585701061880023747841687298399521347100256144190745239736307886631344232154619460839571634517983972985393108358332165354832216423123433452593184944430813412241729568681309882806433424070924576861926944306025116209427676643853004460940108414068043765947820775258964179520515512570312892039675040832441202178146375567860071435250295369352576135007370924136858746684048458787582556129494751281178312709087944582698436574208644608 0 10377770101530756290373102189131546273878159094092815424727236858493087718621507674953935310634880504884305307891656599998072294882134487471324922092141276003724731834098703106198154560746572751129179045751028015338546259317309998322660852156268396400371987034659539061306483255748399265807600656579806795925836132525095969643045626745251094684891969119029771354954347793382068730253694809613289174593810407157702598042079534946051598634381447897281077269827164627350192993946000074993969462378714036123815879684483084207767271500039177421826821736417971836109607178423347199977895771881880373061732882412713941929067392548699235996747087145447228954442258331416789849846801004942761651882112095655876120988377518802451736276057851406261763848514680826975256079904 0 -588386917180037033621507436784569934580601395136959170978998567481606066476396759008978045913962596968642555577331194106373008350287925134098732492642322091735683805363350384958889959112988901748768768895571275799167357312203039864247226796533079123839721054482278186946868934209427104929059770488013494292264808536365683211108733172063105616188436760244638259475260892302303933263204271051981558648306196006125224720955372243974296078723027089071944699529678022054746437096468111204158587537241373023455849800163858050106431621300967978198679520812157291595214134767273389448626761069748975082531848826776252248495247832212159867891018051546815908004698035746611880077971646324445948017323572322276089018150375907468723375506209961100560101205342862732635503104 0 32867742201000320305714036339421762567871172916155311039957498990618640292300347974933735408920174517410737105001085290697301611797456092334366938776034926590056240224999755970141343149682143379847569783588882294459274937062333308158401898712626577253618097903650052541614312906464860774667194551021440409091922424193250456956221101372421220828418887671015642515749132157151024657952693432707291756386046434502737617418939926383971762744115956618651847300741592413859845606449181526637326885513248673596700881567705759308852988095265233750993672371494321340000548769871581983645871082516048722013302641512212344827894174176924490003308760386793163940392683234571296848775293212145947001050717444547502539504476467001884485923734277363034780840044857171110165248 0 -1809038843003746579241031284381958038072837846077044668327017870622117749937993820105052504286000772911247041659730438883067903371732025493813793096391739537258967112440075756484902963000628843945345167937577172895115726396967847796212626571366721947655224001247977546500749020606580709963986013981204547248938473934038613511825298639053847105636317393480100812166294901499995090792494027034086998257204283074227518853966420157974361914747139543701601246378322020635395847303378599215586154629517951634827173368935634787625039685915580346040408550257307811066929407414434916330930305558557988409096772675710422869738037664200809662600897943681222611120208017590536147985521775294278453743386683863240968435563871370548745764875054456510257394753366794202672640 0 98111516984858194560480650935896061055826326673574215976995280547739258804494352773384189535725128769095284911694019277762288749785248271353743592257854119865813154964391734724707455541420784546715266578252121221928393588329512342019838896263980222561891536076413667540634917948903062104634600420647058313620028411547486867788248124614163192474102064810327071398134715383515859269635488055680723209614133425265506141071755548692861559479421269689732362514547460337361241357205101674091941070075336256660314866377588453879395855705187830241999855340255448026300784113212659370152394694427176149454013742501538802774997263352455691742365335290495901809234781734762376990558656153241999446394756836144489710583461332289831712013871481268953512311370989245168512 0 -5243349001622255179812264029918913634856641407177406156991463343380402352450299174043176794218584875664377776153408213868388939529722326893177200109490468125491107984270781762436580606063353996250001820780490429397076021329867797517724044059106720936863015517040137923668823922282973361573886380166832845403994705672568317369347244926138218325473937661766542893995360077537967372272360202947530872225526485243568958410311467150732569493393414023699428340173981233450012522139352930089175024380700813035343619245557108699674930468661594888671102180474740308909751697444552044185387428661109541558343192542359099480252699155230900599987382322160023009418912437334750778879509053248477949968374218825928695300111157640897851928770507406727556241328303909474816 0 276144560710816923731331775750027599094055341087410090496901054637929926468259812968938380832410296954280878439006825940602323463682385376908813891003707332013134872180054160206125955991649399403153731789017217283394927244587975625067936057128387505175522439960161962040695687644439491535788824015181950626978721958712824463431336549386551254229630150735007694015309045396933340113729217198028613569309124686604164775106501844664656444374592117074484856002277327740085734336481096843067642325026793275778382875673818549263565099244876653120952155306898959026776455936369914614645713738383702473056649287776918651412602405539261835575962858819880594190630603917346905680345716305923920040222081439159508922483731369727296810051166873141968705724930484275456 0 -14332605054327969228696409559880281442709378093285526356107604826784051358964821451956918221919878838626209135243389459903396126611872889296244890445348718937433522530819343836397718756997176528765032184100884590056945743274065030751526754532331856098464039491849455153379291767065744155256342877306750791624386847998555328034152179828645881270137348011510514334965329464790744543404342200813184406550348978029170474909103358964556002327071795153008839080090911502181691958752320399672690810516742067868172523219126757628567797472864836518278377623094427532283070763945452882762078757543022161737223997695121635052636959554956096343760880641967680374969844240563462220083201256643782582212171221566273655248239740365132948532243041572448241383936847447552 0 733155903112160061695722369795480561824655952987773393753362712133340832120271137715225529247649102384772309558760820993543192351509422013956433001805443813842335519520886322687608401517907842887535340275374634960696896147585311979343083669286619826569927983464082156029142482709473305507070318100511398039137351095107334768252679160170881127677306648055938931079859088902443281750056513801595090871388086964420700869245585103064785876311679181107107351789077405609085826539286609795188440696870043541840646082576997738584467081880320515159299122418079282441368565600561270777397992618157878489439588039927940589694765496192834671548877626174808981365299485199740598285560256807959243455484158320090769868259638578014377255175464050312890888089478571840 0 -36963359861619791493421179263940710509218440155204519993577443290018421790884099281217839419250582433318182553400713323057899788522650534402488222970244340840377689294404899114721840842562958674933098837638064298260714615385553642778635551735806162934978777821878215457059455620777379576594650817598559398502561415598225658573951384265475767022000524701810164622079922699959607594667452591188196530393479239580066606581262623307995950526876218001579609488347656514020049256982264117480566805236912578968335573079528692288670726365471215659681552298276108486797889781793992303495370241725755347823385423595686278000649925185131576379050078822570052133549234639198868497439227783878822520910477667143901159572264432045601360806843681853406224837497154048 0 1836840668094562456816368194350119377546217248481757662705828328492873503224142172404697645729046028129830889384477533212672652494942592734414141538614995592892515001757696273435313271704111284418160429667384644425213272412573796230140179784371091935706379270898225307664122892520796116703613655048354880516174410585887272397242849468970746563768294071673090609743652277279169571872604464821398136443061568157240107141129391653720589904456411888407078229235312236248379691441628371917495662442984501443238340893519913410111132672203517388968429879643867586805739673312136492517046949255425753998679395776391096060649963002952318179224124222074377134314645907414720323467506793267796461050428724416580957708051077684209832726548606340349339865265848064 0 -89974038127199297825261934756158278999867560836896479632215728773183917344300280438376681568762242476867398559884121475745154217218821543839566325145482176137555138607275613779378348948407237174452290078383849442189393283463888316433057632407903546489568162258146217770388874274886513732140906524350313810179564437327455218153924881405818526768187335340407730717641101331300839293544461436541097262174849372368073682768359938098623408454813579827065433990765757684106420961439794200333748758850901049686009924190951661512127520622864069411981873930445498734364079018257424892013404389597065425631684221181471970057819436985738627951768611678459523865053340332756945475876894909181518750753653602272334098568891683401820078054809615886454030269996544 0 4344392588799574009087244648810815731201215185591029203991550499827297298643261041895890477759649840358482371174557254638423825246377501359546299771361798531324702038965356180810181598505182140245826204141155819663987997619318494183037722173408878283286800100519602720838649939314405957931703203529402227316280915967891658784540204806335791300565918696631600280819852295277425839965137077925871101223737412924414027081783724060407723451362178827647314850312886368370051297859634801101101266288793017599722460246483980375404286528917423492203447123686008780587070614355687486953685102431951441760443050507250230947409679535966514970655272665762280694975672738056508872643190329631225557754200309521961872825634602525051109719935083928014976349647488 0 -206788886830627309398786379045034511477066149168765344673612923380398147281355420748386112177468388764881940187289646801652784200231823850522281207877209392353859042447071073164216759959842765556600571187446004302327257106736722588907229003374473274212390690182154322444157696275665369311284142135549612431883191230287602276062164715493885872431410222508918199823063264768560006661501821110794962145305175805933220293985426558557540213843123970885835067232614578203852603793799708494883276270339904485812120145159429265497448944936905372857704609039054007681776189666818455502203094031300672788525233984810968175452340808270119157323854512513013096824110018615762173285577724337412888579784549532941915209013421649703262180593007705721159044497920 0 9703568446494433718200866445828667711069958786863012482462240181381468237011437372028936609966511676063736574031184046516957337962629347523832605631884142973055759965500318299488899483715200184053681497615061761365304784049296631466107130216429637156248323846284517409014016829069392726109555682937087446921827537513688811827506061220824688516742675801634514484685295946486788259204862564618641263179441627574109886628177778368657375481126325570321152697989003709013688546385219468559241008514081419104146803026091829072299754866227860224301169660718626967305883307732851501442623044827446817967333242239571203925786130181557295757415765527275560213423366871280489335343251998148633378007172066685487115322065295667991596526658545023437966478592 0 -448912277732320566163347420451070148417110491650768888769560888511681398043800341248039499135439471477894453693309100599651806048672340939005468000539131414666348881977155040558409481993608873622827625307970116898845442878663963363643320931949478439771223193553950611701994889081442993458101117182812417816902381625199362674248071518667175394619285032303137119711099555313801401983804786982522090807532361276635541349193110217179115731845662024085388499645473028739120118697898966469365653093187565657503024722884601173995427458748421193971571086087391181321951671106314252847304914162016871785441250346896503752860899030359772101489877451886482071788380746835273795383743772079954036894733853494651065270120641127324008203752794161454946448896 0 20475594987545044888030425281276003121249171987491398315324087952682472495884892548328429516463929049297067906007385611178040700127289440487629961971562330575744352794612509313662896691854219580453689212628231141570978330462824346245678312701565280506354350874948780609709664671761229234540493040843379515193440527869884785468651253176493311082023424412263231041141888615859620289414151791894177427241196171835429337262878415062578592914504621106466262125558834592832201140651972008648452425123007401817380639468683044797753825616673549686003790119117931438534922946196700232988794770021983206746692322824951832543575472301341244332913248322692072409305781021908001786395598568322954043147575987703006962507309009496598139166889812711226075976 0 -920821910659800603765347493092795412168341914763478550540424224702411095716640051484365986531762109019546515347128687678588744694489570120306166084021284273535773990179300093917177653421563401489449951320107280912280707149586773407346179888215936240254215342685641384005473834519084322401057006736969974716274526814894894927052316067137669273457159714721754760015360163759905485244422109247396987331636266284336052843825204498419748184972696698008788559334679654754062268499354580916300401668762263279261222193679563264374086552949747205450862867568022826181932355857822178422936479040747003895486425822101991499064806281593902330758241591586428803106208113885405231483765429603932842328742452419826901988073703014237908509986191609122580992 0 40831711485847681604274060004040892114075118848062129676141500853016884794936782794470537653004723849680534741523812573307734996125478615068973263722416149874093879923618070072646813103629004201709533062863847311109174347652246164481173677850355012043587722950524319060691566334859003801436212072029520670672617662486334455961489121580242663173631131822994763045397058037833745922706825494007541545822131591295528680160506254585685059094678859486382590767535429949128954412610038338458286376786950222296353445415189965423059038451172720480370916460657169303204534861556678740978026191714210997413155780258932356123058354003237463181934936936784941949074373003629539093965045512393100813822416263101456774800053523435716854777034711568751360 0 -1785339601420577976479766545197406779673523876965915312002024817127494855234594758204667318536003878772036442523992629056569559104938531799447885957302654235465011865463601692699162815331865072751737995091747308066674517488692718110326456368357916131984373490895858836840603980784459389655022352369700758283682517988411956904591896413882337703176318135387082985210247330832918404848545523357556619258371995570078706723156250915387065917697682616585812579672054653279332927247695216188316319869767740834902989738211620325311886167058135625299303661470443645020487329608288582907582309469908782922324826236995996833750270494892012528105575119053289550648627776033970055278590844549791982393161193432370945118567700316284378295846989725695488 0 76977469878123949878609626089142675450900768475715967379866085725757937661522740961261248476853852345394747394575344080591134574657540614913287344287393088852627222701670290602326648265439653482417497348976582129290158192817855382138308809227932804357098112529696994297426106881037078543619388119863860032885916029257847375219589217697941285918130428701282061832309536520051434676756121273050649751979278464874944062687422918293365818898947668442889933903537172385515463601338453852136600939431455235222013904191438421404376481765582321139635796611281656712792803967114481025850651849658487279158096755990664365059686937399655570459080034666145413017391386114994987838894139763701774966329480711458192145076191662349609121701801819556224 0 -3272984355099464031276466641057111187734776464504318671347360184430244025998159051970043392703471209731862204785073885950209434252615839766764826599532910302814602914766133504999470197213788982855168937499132857087489253024965542093096412783053567943816135657823586657140580369938016477561158066864772822697182850903704478182254456188786182313292417015707525107448202965145142601891226488707454321907197382869872057191149080863446304325451134265283964594053542331620630040936802463217800927568847532357935738786854868178482621053127907065386483667605309516566092538399704618242626773314490129179039260509275309872733250487666262027810661115164749336695566538858959658297408367924097964086731451090464473681113844047372434235768353964544 0 137239596939103098355025752267479150773747990495990607739889994871621133846907985460708698336639436643345303583193212791357842145273308701040490311435164101200573700222581146003640231309406338481950712748705199367718732431709870022093835029593572239929242197354395728506217876844856068580863846832529135324871510219768449159635586241902084915640729877010543890171331848832786825009404344920754173140720193363252912709706535132718814721514762755818919857631745169909369723621613588271902992860217825919824744058228847951126082449975749242906138958701752037981628429250144897358321976180227825335932718360448354514140386189643751477262969480086152764553491910254754706845451377654223396679909220179344262754196568187185531339456095230208 0 -5675283952907033379626473131248522620336975222213858357385543881792232198376163183161719443265547286572224096669114633253028308457847415968654887557941108290697103078762502190196445598590829886204331699266139298913970004626686090752951245214498500886726487719087600447897749682711289719743604370789023107351752487757343139849183078703336927498724449870036870044553610625073453415096559885307063170174536076993568443215531329242436285708392005960271369119035311050898062310712082494556731975936023940020659862815395244921946299336689028904408331701274199922250482692633589516056119366182848982597083358360620082688299173946331840928507019471292008140630873928002604297875892545711097104006239131441193914465304010055789628344014165504 0 231465150070653815766486950057195982362448239669272546251118136221257293970794228382852660187999694577225097009086180301505251660908924788624207099310593945043621713169305324899771608259287199775702144961087400644536123358873241870589661380863908485785986796003756833415736620215586115143107941637187366685848109617213414148705090365277556535214592969513383103096879516546482232165984411067084778792481094020193657501711833101353596680657115888459098599030588954775706116215302112410364713690776596151678081152364556355759866178291419494593390380464446860611826192381440693115605256677539925587873964247941022715253184785558848025343209322539919614743470410819753966462213653656376388849241617724745514303274705695111592972401791680 0 -9310873608847356296029408600676190258475418317738809030112372444900541240840058376720594482633658053509831780791910257432706894759480058050556755740944297870002648684293657373441899750447096709738419785355988239407906222432365364696103038215410215780780033898957454099239888139636597311787925988062655413298923905575283774391771950511217443800046903415929705978586078792699622479091852462746055148022129796540503168742310952834393055752823335979822685321388750257461594375979393968915068542709150454230414013431390705285839327574006138613122416736233236891574443270109429348943372628395677407820851786034712577909776401187015517213891746790775775162105244832704287984422279746901978597426729202125175427503668761234048360837503488 0 369418598448992370313809864157033648744909760631649937254129254161617986132205859245802024053541443256378770711845983858792042374035854689937541902609289145094627540871106646027198102698129929532726378750856569707329668898182191584492379816145010582123362609884403475212406411075552825682165493369813408668338837755992048870213575717944840088072987101916699259167837270315322445321588934179437370827040523745992791122651691761172165116574377905637291071831686556116624693036010695452867466970446067799051480336753818303692675849101930757935673561765905095134707403436465413539263228306261472301738471045825247776192229770358081189782656064020810490455949501028808294409209158017812276491493476634334007366076050199914508425543424 0 -14457295107052361647055903438522539537748114061871083947223921659687665414773809407766450876933643432693964550665479695514980326470536883321326131857174204841152893213327629857685667505256245892841083433955282957744759706489059790402406787060207666556707227528640680806107703993931065466730714235761626596830009344301532154010534405540757584179636140912496415784619715685088097410067902688930499589518129347556533421399896717452825969686119562399529729274753010700143364000266176169547762815032347007694820667515270511004870202442837028404571931101068057319489624220791318110806061444351412487439710784877464113616157250112813218674320632362986841002565905702272859398874781515596571211258486556478744335676545760541372964335104 0 558099353777607324818435535568918855278823955984927336513631106390904653698429996187380612132747488111245926650814514068935231004531751529507733897168628762919164483066386085405943784881669547796761600605456452122560698536124780315499519692136432280482772900135267466744433060436498488305814606030120221250508782622216033334851426527712964642748250047615844536203647462469436724782749577616020071099641698174615235674639541965569116383357366142614355885023736562716014460024128143720266241313472540495504271285111526687211224125982881896417245030616242631501841362802847501917953953207895324102674904571596703815924804020014025611425265252752752359848165501661816658730545863594913830078723554386474526268211991314736008108160 0 -21252408667959189686065344451016163006336741609159032831524265781303179460456111258666676836008247400899778697161984167568311727328887884064946809733952757370676613576181016629179199595000746029485935617790864280805172766832439530970111327969791425203825521615829032861917646095566291573126375424175820890270276027335335107027429178450566728113410026937228617743199476037919993282817710735592627956696372267767512060145462414925949269353725237792742551762785763677618738036119311249730868665817495857501242139559989842011219954925925116955505072883039542903148095745505697625784489010555587278781123806725219420046659633241951184517481236730302086777118221040693573294203854866905107942042732830480629544022837567174430011904 0 798348859507661157620155787352505264137290862642967215312096585933607810020354922184568482249592562092620757004079107473359225648730674727232918949381393598595357695162892401728621532872648595105368649326929899714553877145817229553499294624023738218552460234839537915557255058073432905678608310240489201768069170395858525744608987201106070506583550008932561084457096514094903280924193634425659111534959771999094007509901165857611677017952371631583603784497376641339876435810967770261558928683315171765054346782282757055168713560132267314771919711814634314123488320515573008304732287059990065542220869325015338823491018961013220755131329618125731158933267274241406092688769726439997223894551616168283506276571414026260479232 0 -29585620783650436042003740612186952921151090914895938426060350804776695425079589105638207924223487221785090501999070145178667087118812001621587467885063072647483779627639567325664891994486475211655505433000653402819511726639067779556125289919131390407569417606202470067008593876342461626943444388631153314983642644933255938527864853079660299675019329431480349390294355112950031810070110104440835637317485604446537997863044073040920949768952134211542792758122231532101904908174753110323834924082910921852271971388684709626821456360921379584064844962656086093769133349805812376949840655364254834288075613996245447182808484932388698763886385526417666712863652221489731367902655514757234607397288563522163782884830009154651648 0 1081651544629301526406204484507288694696417324730393846885871796596246736759446640140420203304614707658407952754329319706379856336427632150222929362003807183688448986579052991280954309554876762291131300298929271558956431180487464236312135088611730624841009635055247603198392564896611501821052056350459518347786733779637804017449875045580806480993721481767991315862623416710593405878568227787255808485169361197156234687532153607327534080627959158117557686320254314548152190544826499751797108604750461138891932370245546127172575903339019829730167451065789173868065952193137299765463543633433847778468145238211283527857734650283958118664048942139051517670852775795137294111824665977682644140863506764665104146670670171963360 0 -39014660534712249675330378226107715169587996656289827333360879285199680584934165945034938514048070812367562627755649601243695058087721074858750547694460373936807920192324562570059610414754636423700352629697508642598845087145788574450662159577739275355074860258984071376661763672575149967687785511831504249594226918798489527852722541871042558364137093860352615131704297558929924203857420764177946544413647392520368290309351928149819572158531786451420998352644594070231902030661492714234113729291938601021569398813835688958154076145002578872406523160213980671210313104856559192779890071167497037645894243832427808031570666053033807304256853246375501747081847098961236547771221381265696352418003754290907940695992942004736 0 1388407313686789598020649353387999691869094547502442379593352864054036133215974256696304847311986469476367387362305952417090482114311915132440902490497648014597485154631116851580231561504290171095326243373846790070161843068647198120907112931138640500315824436450605993961744269000558226862576314248623314550746972904409331594456536363986402195856594551094381736201972668616722429975792580387423800602296177917135622589046449323821450027754915395078806434355430925884717071067697665186422396303505111203437312812409481268936112075008837603233882230297820978440765752176357726292803106045955939951012900724610470977234053029294366499686464504701438932667308273046049685018167491785718214123239614271817606305968667304704 0 -48749387864725098265742478744866009401982357463538140921074946286782443059813518945560363452838136899481344790548665865377599622231884655931609920462755485858968624509630956218757773581718518227595761180310442216177290218794990832373539211325525040983648111349910790334989741215404144016505268097902455764515171514745571413501475255999404393745803710380869921716282334905288994177398845300926464474905170777827732468920300551779940058435407746776022022378156048235324190572651459663500207014756481105444876585465778558148830588649969362807599105486593447895418781856824754837998400188185739732167943423646476574998892667363839996171962473139822703417959399588240779303056551914461516153181807078400883070127591366144 0 1688880984475220189345564374898704919822346278761415669328377756189548348077926111782109417086151217539761811786516454394485698608502378840989566799932038432414580717668772720325502451417661164553389042296306898815988280091888865502692948223495039458891092612656110647896883826225108343933705543760219978546753628148128084923561893511909071383870550494840643005223527979451896802424213042859153858626746162019933709616320776480191734012415027780175117349212616445274304435864461316854639388190591730539921025005401407449529161866828668547988489063104044163368158972230233554540979352547496278527088310389885704149643824175774359150835076853412375896537640105247068298272222819180101998055026988030762939259952221056 0 -57732545189536440200614373180986342361782885056946511434206246440354848627334917826883859300906804944619837573557070480655942468720162829575881369161439991173417847390573176527522002730129239971953688154601491152910404942856193541792942238957294801731782483403705451887174050865579425020749199739486254300310533797601397240236523164923259199725618673153021038139364474504342860719281961727726805396943034514439496044705365932482082245048786479222020424789319228435447738292102089198596061903285364282607799853442289336683927277873049485527313049342976767481063707469576334070911660351592297523840242254529114053033927323477896135900536417982422006602402874816441576736568018437003422655496999040864763102824489472 0 1947368318638041901664461244183943911345678096940462554700000374139333810293322231571141597516335469619275109677710762695300876242444895350293376653940426966318573190318519923748642084876399805584811204070951132004433554084195341325763024564517656183678650598064752310470520449325448401812827601205906135065002450679335890915410293075169673856710537942049864655268924672213490142371231534164370258721538355795916244977019184458564961438135370770253929977377843862190251603220366754828560160619847403831307793725026716579146170529662698167745112365520456845085237641738154674079226357665189021111216393467449899883502654435193280246124746193233106161454262642716223828325921629912067502446841078963338765967139072 0 -64817903500417706593926308336786025680737954975646638235102569490899860299965064294163498921956934211731995048771151894528957625408997766697186573979281036338394299413169258940372633691609962656297054121171047024776280526259394589701161407270679015492325120932935831632180530164416905508569472839481054991273000491800836890402887035936279096909287395476645312356932609672016066995033708389402111199161016859181408168338913434235391575364286448405677852455927526917760028017370878870590219006964700107641529737786498919003734528928570802569369850123761579715324224939628716833923737609701824333677755134280436320020667342831149985793056412555187045527736346895176458854690516198018337157159299932829109516170752 0 2128996158942877621080171194322560298893866387429775875035713262839585825306110040178363191787666188321192369610165438706214622868630110112464185380242364020478696502968393766155130210576457507021751451102561240952648611762983644503273481581014480022896342879657206248916338810180860016553018883360641917839347604057458273285034112892131700588499274434128544707021103970568978862247738418187772182489661973875987908991319851398626712317135178108542547312985384465016592782941157986988157865800962621644949872050469683806479031128451652799232177121663514955829001464274936140821079956121570542869887730767027636217886354571244085464010255545641340305559083234067612151551787431353209766846976036525022622212672 0 -69008266870947144078709135490686343612420300834965387377504547702956902157369096090228311081179841310204783872027015946717109844909099049599581876332716514198400536464608358742982088930240643402616577147681426645546596010357735557720093858187945580065713751562241369741135609225765886910720744355232982522727883001969505676995102646302089032351943434470990897700890772845051127351296603162572916920203744086590503029287000763868160435307860773401316518813911068866040697825931934496700313389876332768764536788638838532758106457572537756724847487397192854502278169025236296879586309268370747408944158426192972904924505689365953815846485282436056010987165116105173225597265068819146993719503284373168199465472 0 2207429420559176476050831775683025719218100528107647159965041572222142952382516420793542000164949170230278356159457226272692735491234501233010621363070771067342683752980497110315805562313217532901838708502730454373333525673625907444186399916707130391340927603756207906297354454775634504154595515112242881695009015347042106901143744466791852462463326415725221295239028697867316129725075217278277464773028025783237897902993226048340547473009326709840266469866258270306679291850514632826187967038810926579501099161342391378481766074674643273632905740730456895184311497106675096165770429450436952408278546371939716359027110626330790164849923736422635918148842787804606422918720482001516520367902030005999372032 0 -69685899639320406365455649139461357152490653717760905764284931524933640596175194809192443869529987631253433730949946768006299339598580975561175700877240256778554644518086616525682454961673331332286439310643857339290199123665609417293282005811846648271916148764858219403778091637412033701328551583358429268092732965543295153422637337605376056277605414800486201746145972632663305359482114969473460435365291367517037667876832052375859275778227969281972528128231057303415264931307295323024666161363969103616276456119240456466799640641876921818875839324649151814370475889598030450573912427729657120460886882040539330755109920199320666621502281452501906215339951220208349878228164815787204891588239033875533312 0 2171141286584499435870657998694409680123368719541404997578160086751630650844474865457021754883920846910667932522810625832213658295162839855408246437227033066043230041444855611800132184397012012405012693250486961896857224826007412714633668543759596192791966911939232404410866646410228343701144108508555890222346117210280350748731639719709168391841418912474519419102193690849242127662721202278870739861216399677669836402185489419348846143190202487346565473469584925237844751511739825153391524747816982996212772014842378652785092436491046105593977105398213078576428623250857918679247206986165766223258769175915473990039777039571737537605794645988337608905496987355009827137351574412219479125592737649498752 0 -66761926787885568072391023895692120321350551924574568889468555545444905732960972351221831767092995747221655987372656131374940307992989262232719361064848580586217601364114874058280169672292107626702741163857891848972767359409785480361841124015384113111040347462385516028257980017774693821086503375491160886503971801707374012177377526902686542737717058711213684360579669131177125333736948441535652600503067756882708474413134772071222494537999642131418792494890625999777661077490079650512187454716165779254146390143464926632911437900818172643403162165744453610039678993492386531632753251527570633690249103454565588352645536264974786397566099165849168495421643877306824203912759329649625883932794306089472 0 2026187126376390966950059894694862013051552252348224426343879276216464485498485404669146797641113223462105613166440258263149865914973502323050663223294459741949040108756671404554927628646861474454014689372022221744057694504918818352164225582679568311253332897032623226027490388277578034858770664262704387776905711607914442884720951945439644051010777370171620945300799422223315267682392977724232320821270986277928614380548983995413729086359216063664992624628238737969326256260661148517205295742853989643686311798463184387426773426935883324810563269566592679623294358560396404022268899193253616487574382443649446263480504515549223392053425986302317402207273584595922187548095252152616504372650668737792 0 -60694909665797486078168139484451035527329017860988987753131367029361824150167935257192205139349400434039516045225053665436211883507945969766054852989726343152544051574298297195338559745833873521703718706254844246057875776544160074280243527746569834551407262424557095199559608023622367462961026760363091304233640423385519045013779598780813991208702542116010901465141285928105600772130055774609880948104287201988555335474586962676008929546207073436970361404979106438279262379605488544158142055502337040560458601256342864614828042023160998043547894616262428783818157889941717358994459056021263985388946517038761831770001477438921477490696789400836143840290028108148303194857705697984780087026964588032 0 1794563931533669439900509215680360747188520640673362756825222914644886316341104388098243986552690182481633213764830931905555946019980432691072675305856339805533149948711739814807876962016542226588595964141193797073483997540069138259238642012110154318153874265442818581780587465632868859585200408021938829662293925419662409035176319069487678136365587662919931775506261052755261425379673933052341445709237638167897709558295110904015480194143256410250303656500877975923739069690691697392869132697768634938698993444859777842181478778898940173771014311703927752870030406227203996917840654893275372711121358853826134144535237516734655002845694790861785061283589997339482973570444336611739391720342819152 0 -52373460899192757440349020450301977412733426915919605731148812125602324702448009961309636204665355045192573830224569882427499484215003473738706645815398304492124336000848061799145932359522627151159454043987200078351723932463134388170294186337935757366131757904676286616162643506810433476079767140362618125483980263202777151694590271189561112144332435849826257449264883301771728460803901580358774599322595189975154256977562969777498303363399122092962052723765973220687789629841800627945339729946903816131554683576704003252867554506460353251391129656743094383031558696321026496673623886811346919845654410453788798758985825916786569129486062926350467450833725807725802503519500997517065598204774912 0 1508762285945999551663283815334925496031982560107401994292461624774256794019316546835577004088277147234987934348860845635185399382089889319649447875287209817396952216497298554700243141477941551675134056151736347527137374500240171910523728997589012960567454088242170645345818386076100400902951611599801641351374935247241177861854096095546971935494894994689292346850056497091279171788140314888614968866709176029264084753523874037301759531277406918224431781914836678834653138654428848727843751920486309922349440741047728989424433304292647007367016215649614502254550856751528702468092834771851107128719375157649665536624470720460930872174218056978024520369269787768217485100191103267692392363014912 0 -42904111878537694855599664256489760016741079118468736978858248978249999438550363992654223227853587691353794054667441696859040235210609617658338111452095455877221974062107356615279389337430875679338410817875916212241801629252983281448731182717796205895420065264719355630158517988288828229436900428465241758297327049182161528076525746141784200708543754502371454881530594215044051547073755200213678247356995826896841645876422909146458188492062751800313061259105679043851334278227005182200269594133952995410648340365850504099856318274232391978894420942633968247010070428470280917554969282558563221876017739595435898114025635759504735115886208356109419563176042199493984255148344757810535950310912 0 1204361097593512997957043937498421048659442432083001586602965820739491323546314438713691981953379193762243818005545730839362226160264305333638781407329838516044203626342345596151218671803355194870662267166822942379213244035812103849603842007042569739048453753264300158509623411900886216119648316777312817378548464581838915921161975787890006369222036354840440976517593377287909568836729742862943823936698205077324789280607323605629832392801470438486077818491227365143089319667084474578980384588240063102980621757855676815913957260838044542019451258853503374053734715724397294648451478724426847482032840841294404009830482735922076103710533223049164865455628163266075526707087140396828650145152 0 -33373764287853184476650578170688883123220962751730261461304836064624070988462005905840741592886854864060590880454086645915871651507916986460571380364125202367351929075689128592954419034560424977069752457665688793137581544492678284882389929282665541157819096904238154091198907339852608734544831255600681004955693771787387362184210172993187891826556216668554257264921435892276257982771963987569033112271017477908849260832874360813048848663945342357952628089414695089692172001561933015027178227829126938129225137252038986035005455377148435035312318494269842842686744227552559666211851077125478357768880269740394538194276724696344410909216782346239313793394806500888088745564085001398888653312 0 912967094618744788695714566172586101486285576323401150751392837394181012714695310452181968311012595397254244359828184600461531347162907747513817772094958139817480698578810911128143017513193177692080395977476233767486358378190933007783946360789541666154592880158339175362399263691530832373765588116758966735956230237338098426186652374648788336000026110210129897387975638134163813693133209895414313022870227056363644568807948885275541408778254839962351748945433720310421522603272003920752575184422329607108556525543508903450945880317245132009616842693404090117139232356207236475937460282058605257010230053007346305247013061717871748890789929368584407776030720895631846759197383802234689792 0 -24655687014790355720067903038092213798155902837151420635070424700060246185251516650857816099126672491440311597550017580065159270236726569452374257749390637870312620839882288495803134766369078893669660886623129429063661347976191133602477540331551572024993304141799305701912257371361635399410960930994131074464843785465795578959855963460514133327159537131052933791137373753824277491792103510361117597847173118990333223364552306864834178144873390278150404957199944578029362037024073391605588508548161662629906593825215240932192249394535061862362672468655664348749013279752192175805343386138759724281395397217131816380029412472836490669818844546996310000014787842979487833026637015851054592 0 657357405564634715379157897660794581853415246961674243271294869691726874530407640872511245941111161774114713919049262799922859272603235782969217541545229876946815416845515441907079315734750523574885920876374197069942465843221452927138964830787718714192100364666557839515006113896104363583404235171611526975983893395245851208749763146333481608305582887827558304137075456943017056018330360518939388866269507015039334109967088552647190070902958896814724509704480940213738416735529766050734169480583787620505538808870642333474459455233679047717854981814730888314083698956247811377455884143866620791198305901957637616380567320721213367617200530885540012400156052040911964505900787934867392 0 -17302892648541496023622402706846580799016335364985112565957218993133708015914982905423400929643394531479793652573826373806148548577683824106684175847350396480783967352245183181644852786415287456908073328146882659134258159108160145965034727784514860810336615045481862767898193250968996639581529922758249406900225237798727360180622153167346713478440627588923650529419204765002259690366100667973107069633181908275200818629146599202269414221672939267781748247172266399245133625110224805728758317778661661001816299939099133829748281457472086011330952601286497842461800142569653493777225119774281681614673473110907353632209781688178787767760613905847424520267898607548377363626466256845312 0 449654167083077054554719511778534812889769034971753333081344984425459950266062580493450482654475014783778076166644458199576893820285104146027337689175830442110319805307308636986962146329477066066211324502364296979769572530183479156131845597631405783053354121621011217904865367094229463791526230870005284256261723176231493291838432471262480852946961277332116458975660255348334548075292537786247108817367892479601371009650435219207577050232417705603681743153016489021541233819575500420018971176817438788474862000967822679167854192236241409801512817329459318585459994735224931490810865232338623561700060388439158747809685812460216080701282958202486290239527285718406117205182391983872 0 -11536954047592786651164682883836596983488914491397933966329353588023495509579927925712403691903711097581487551206194997134540753943291082013327978970515434445130231761939406182096212859934205940475686768356068721637689624386589433724076974825822897579783234068998979315245721687249698760261216827778659898120190251702213779408016554560612316422582684788642588195907715969462317069786436299880848785118202190517110214751334220491638897204035288778418991849154524705401268797062396856924182760559573986851382910847364050222784132922856187206988217981021605235067125669907756533157853380242732552122692675543407751971417240364149872394054090985386954735006417965410520192989657288192 0 292257747178641169431679420474044848042337100981236454961460898822871276953084171067107578592697880810026969340442810855195793405587412838788085980055302181267457790505364731675585672501130389628829058529691983753261476272140430180102997176317544619972691858726951399895836737828860834068798750708028984149580675492927502149243013095559178804105628639894273695796032881944172405106319949901841370386574480130130452944702317703967112952337974572453206875246000166543288198803136181925388026037585639066724212626044875477688177236781028365086998454232642193913789818289606334597931996963032188201435634529172562886681609837328665042779055635348667617975962147299560223827727484032 0 -7309922169551830057287240169517446939085858825409315431056279004573596379245091473983721187107619173079468071370063304950660262826609875839202093679546770722220636433493946103705063713045517778610248616299835865045707483114156731705833933350813892588612323386220700123800413526906169998250540920571768215420408637072443520308727471375779342857682973167742101305667159061220946437149645100712497473777586895122832994472738970182849748964987370407137097056394636910154145042963744352352920309818760987177557379512317349901257704993974692277062476461147240950747969220281916359809299871827070315337309013334628086950861512308112107365087170090222441455608309518418780221529805312 0 180526379376723882231011946606910737462331404353412963179337802559035222224499153247799378414791216478875141313129033678608012261750615440859572529681867973810412865482054353818280239863107393262596497781900507850662780347737251185517169300980600678514684556864150750046683553278122415870040934724168103641664540328257368148538315177504005789567984598556604993038388035405388042310642979454822808904094638180525209198605984175099646033542515103025526667432094184710481181924854333102218345698486227613177491589275822489500800541556343751676767959324358820760208366310451778673382805945899077924874100628026904811846565677770131185863445796646070027485063220203342760687533312 0 -4402090465173549273216927699636910134680936539652971699461833415622671754993353177118329676056662013398052082898546888145014742638428736423823439692769306965572059926919085356315398641843921562748344994262846296396451087192016598650002393522346805154804417094059196018959914817064077837574038754686435404738413907187444229647526986258344939141297484946055398400599812935447555199214525125819650418664670238643221359288835973868075936369364305117346383764003245829727020963228497993390509512095164236688240111767502663777193691637809513385703128622184607526051053613017678315056409647520294998193992506402084029642872495560500706698387146401345725588966995020020254944404992 0 105992864139440389048376710486372820604720107529020662969179746467819336927905857728353249430819763644461509104576559356035210622443186692033765249377242587764257451933733397732722011429010620895791165055653685636722358121486669524228204977986148332391202851411985840612115312649919606431612043085132190394452400036265938557423887578980150068585996684401483280595300777748727164871777777866661377972856658483022772491501752394456777872358709041338310770443301426667266701541482838635699545920307732278930522684703854771832189873419904036795037716991995300464420003744947596250245311335666565321647391298705042550226442728889213700846989456154920965537785995829284423766432 0 -2520011342892404833876806720937980636187526214369021046119411283156915685842700838828995074761301479140989446150485656608849126775572495953852599921607064779305297331272496716624050526288662434907701085261800430174275251229331347935466786701190063781262410302276752205948142845857139187907875008761157811162415540499134908426163024151093461368205490230686089642552707079679578717081249530502072923062635889275501934616242812239315542788090921872644865934931837261528452664504393118331729249730231845950096674675897383831029941908194084133425788004083838306293557387120648686582261663729584960788342098535208616516615797614335594860164962294598042104005675199346951956992 0 59162324111260393453446634670997940417267531826427714423758559455947071042890443474406038480153570221853967741669241910898772959599250525576484255770106913347011721296078752554951188660779272104488012053279963289789299205454383187724938296535156512894635990104385512503262031662593821487490889286838577500356885125457693404084898345344282084285393554905963690478129588641694243020355151449618515772436840470169827401351625658551122945042722609666951627328928850545608961270339068327118782502578273200899821079084813275736001586064174105639433867271453815961731546920120831600392048846694437847079753872643808912012745276413025548932837745740003487720115036081649353472 0 -1371555261641076536053603161119022888420008448447961358767182614780363800339697633079280621155348813871958456853653726287891883644306630854945581625696359858797621546581349247100884348065875017286191868587926019988656754284440084072306687849398548286021353277386145683827669195571326543753710084312843999573582209262033581703670301229759479714800525734772144191712399578246535064543086733819856528761265771455280459515333143258707595563080675844108234855951216047199397158140040774929027432903472853419682946684712606844332768943098052883606969065420224766492730650528903052179148704385008252895593907042947442058767844754164456050165524192384853938632163310664678912 0 31398946056331375597707996093205687305217345871003518264379887906261999457906843239238580926620670262827310633704525759035603341047755582003795430236912682068342593429401876618601759999122382841291208743832173449079187135243704076144867420444667491439213322049280229736185895359625068738769681825475364127161591356239290078227714372726378414330007510765357760820545278530379595815266748709443584215957155385294186788224954735547928205066155328695429700101319657210102934259936222308246656947384417735313745663403579015545876471561163624357670675244700733402724352248630941438989792142984930424244255647007225133075265071351456453253848351957616414021500556270806912 0 -709837047437641471699055352967579431779984439070044498975190776182862827821006394805299473175252976372306953918101759627216649634085905148151333122666836548532563945033874638117766288235932076706610565537427457709425732194200451650292358337076075105027504086130999653089669474133676100231369798603302480633507842123169614729469542741336374724431605400958102684387082871352995681164583872447421207058709232229643902266691196258764531617726160208699158824090598351933869058359544367218522062781182427612999688138338769338433755024172384212871510946557633469220018421988617365782227065693213697807550956845474746600631903066875773687001050161631479977240299643535872 0 15847183025707403719982506405842353816563629131690459484795338559809277073015229351542299129681132116232148605160996469701297135512890805792406551337290105551994590641912796421284774307214515188942850339764709933221817941187662941690496792191547189746231105407359674938678135678846443684325344927241745582609306768651145604714687411573855320890747346883176846107049739308198535408688304150413676417321515769433425814897732102673737015438037464565124117132141288571056104794800785132458021861414142654896139932207887569626328762592123131099281428733249406994176905652456476125770517155333195900770905051565651306646504711071418806955538122417179676544446779662592 0 -349384094253952940592831666231663175157801832614235709158846201427714173833761659397838370259040050069335538731734582559104936071138850342122854852027344795485415956838776796828634811375993787674137225341117758477099558365955512447238794656739144609430368898220576124804406423463322318338760739604557487199808185891498878615031580766634400684916387880227952054778522813614536504025007325709557774480754058973723619219093572446853526502284444469150345804311065276118513657690280847341959646890402491274732765356940210439345379123632342985773379145209188813869731259403727081123810268966724908194840770161740624317966751361225982029128901942903434611499783542272 0 7607106380522160861445147882693942398669775954672031938558381401250146583801267890158424042685135802713270492500287303075755684041175483509529401896445334331424228952921529786564129187198588535163035138587479245148933263706588927703822303439833911892965381465262802753699485641198109472898535019056586224803912035438018377154161027756357787233337582260604881248321491429115811654574289924092065198371087456982868136174621933866964481921552485193139484964095634023052783172170972755695735044265271653776300896171141705463558486629881238148082345922653522719771337236827397261090463636509461370881053390451898787318734630431299434713289404848851853334505744192 0 -163571881571517719924560001339679465662767175771287896273994147206748052533171117069465685512403511999317445532967258752237067673295542906032859557859044126420117254361337075415616903077855702606354159167284022850250347119362002595329836215722285965376290908932021411645860035187427566900094588735397763859538122615733403812340621624630577105239139319570015499821366765108380016516764199649365240995242799349974623755403445614134641159656628976644510745508078566019248647332445034908208830116293006579044425525032914937369093232133653590721939481861499799336129264824910184128503362918295397105704455929656584631246016462173939674401075133827526033616804352 0 3473585095468070350432738240984651734579043883897502358719270183384957058981910278378155934913776124193060903770690177831858160892236589144720775850372882174675371116162817872692530612187559827948088831219456665461771372967798612332091304463037638708636680491338522570586778674407303129902639283528832276994470656119729978807737850478069226565745399747373558708889734626620841300665127259636088921632126571921168093666935695736003150740528825208756681188984781331773062135381888770152323694940486386969079979148017530296354253264632007567597664420984330647928624923569258540705398928200415677409923276090330273023475923170286541261802614598775366368175872 0 -72850836185592622426860382777922507455174282234847055155713273495198553321744099152523247526915641744357612505672314782163042957091503942150538433278078108562704741461497377462946595202857923476011296600507307442337854752631076154859450552608945812203725381860261862490802721224362252096844050738397515395525898718382316069182332795821374486444739843590757560555873860515370447625390305648104699215794564805633319758890212844053556102241686563912898389297356058736216831162175189831997410626019934914519052872569843883703778770885370179739391688094659695566933107691509585351645998594304206193129688872754435255488879633362885134930138207881445475282432 0 1508986849919370307186153469071208999446772110551287731158869458349890730899236371141622509751786478875595687856395846448926779623662601101503530030157927076516061023348068872197767278950211656604718669437194376643428278343350531983292547350743637330702608704165409445608899026421478421296966728099179099520972275679855823842496369592895400950518700046248293029972307417935384618868062498906760189681375103338555368617780971292284125399592807585432689753966409900821339226944784577796172098614741429114027086707166948472516173146285486779641087431697482201058632059414677284776631632684466761899127282986768845067110826914464483344957210935851434714752 0 -30870064395740117487492788552136429298765140857497156323333615567745744315768184645643412226512437177397959156360862270842145641935580266957559814094238612479341375579462166504156365185614087815953632956347373105628313865671981065705729477790870061868173399328328448814945248990914161500648561681096246088629963743392839273197862538373703818456863717533225671762003231762500950758641755766997601092892136540655762101175508415454103848185836979338199948638690232735687810645864256530302139736256302962485309031485349956326503592432348543127069381555734378042860806690383804691508320199818840154024668182878578295004835832430479590442378472093370348032 0 623731205809412324292452856871021711175694738317387603430453886064295075056248191027294295500796357502848281118252608716401475607699998089023026651829785702687281014217090726212749769722312527514835854208964550845270489564801495568826325893154401525512794031425291694871761456618033384648065381997197382095582650962827694194711371475257537293365839197765274465081845515390938835804327989861520098590421920264178301753059000399173056156884001267790197942977980565924205382250072681180944919142610292796700807526514058228076710348864270580798549470218825411682181761616118731963976837373126944453446994578697077221353584052185173019166754721751663872 0 -12447203759173165254144415500786877978488148262933712944416905101012503262104016455254911934998027102485056991169936587264904064634121814981197406511966136084083533838317649788497231564907097227302623251361216283534421209404034423516299101762505541035586438087569834191981148368194234566510358539845816979119449137329582571788283126544094688116869694575126713044113581007823152361741939741833706171539849533828220196895806272218109632133431812059608003292785736125232243857753165727980408750171953470610353792608499642381472366620909520308610127917730996427796573019449085337300539765437085546175142193469537504425253374422157439708902161001170432 0 245339167848802643390404325504112181413045877660066329278537336407870086330040223450130659013487168416518753147772101835850513096215339501331564778236504702103071768041540534830270610967515509338557197909789378599223346791181032218080124442430899363109263529124340510920787848787254156052899425153878036830778776796382767357120456902705829179205609662792785968048019296388125567142127655769260924127168658897212485583916492433976760269538750881901235015330984181576705610604878913461366888641806667966103277989589172593704138308452584721692189607216328762088135887516827322317347196633427195833961396795084639616095342489688643114095274348759622 0 -4776270950744824891042422882679813978431702773061390594173691246893780755389725287883835842346581192499512489548552000790697027988145392407494039485259193976275699702471334986092494995935269120972522228933273285061382455198508738644176383234641029065833165316212377316240280353906482879755348265595935617022473756374896251563814723558526307654501141595395658699928359720706858204163624455514201439265875685563306313416758887104760681441601605947454714736978367532643621205792609118699339433448175977428280281332632747186351615100528713933129202744153948177566226782038822969634173397046635010167970118558702012658163608475517466672353396454912 0 91842577124786084486086908752133448847722926038320982489915355827995686281235779537844987855543889640045073368520708121730349520734814294328730429689624178348339842772858717607712502224130192758647730761295297596151774001321874883545044709035125082571662659736843721750706334340939356690655116028105643698175908776468409771768247037491207697971143658119565148346185455804863890814317650258340409580011301883333246399188171072998174114299833215096462707274943336337172866063996032491347313190740791458808796287436327317512057553335778146853187853728946446654633778426386727172608777611850593264402241704763834482437348280768977936139891414272 0 -1744367989865358821008257827661051777820787778394418029732704010722215725038878010304702164422099350091844239974038478960404340404716526212165905799219635506045911235861587642984156808808193650960012003898079623455711885567023162935483258722283380405967409771273553309482088299607403368477678421056604934806982741869253421368526333829902536393386755218577860785971548659051022914643710296201438814605693446546015987956443683472529724618502025519936887272074373382025239770993170868437192208068480916890653819192936902468978283300992598718797530406854861666825867842147325853630181217205691530974990827749993131677024155769056362633721324032 0 32724788123516496100574830746437278773964311860914516300566058624898955158499895899638960358089810468348216131608376419909190322172687777165158351263458192677370567722196412723935437596118088042920922054665819749875283868229419315818601659602647164467568708841664648333175098721955992680034632330890252375705254613337113159582976489606182017059637299556186678687168564617450388579186912723370680818950598061440199090802929572016919522304629165335098961065804744299617871423579470166267206424712308386461186384235001894512926759548309198985799121284415669231560826682891576323412970810865159121633400494222569115525377943864555390116836992 0 -606409306767044048667292189550084383589454103822828796304834590862925645999367930412778469124630611595501645377739965221305628451947255602321400706724999739645849599773300541498308811024385801771928677997646821790824670912025959723800640184534561259595489382976279682238397796882209906748491428018609232773971227521993230104180053536530846517809170510145146519425579289006272153414394811811618698251228880389534444149436418108889392396978081568877286725933747832214372943938865210650712204808606723323214047709276094692328819245448680810999499416128694732855714792308722293432598902379454209129406800523181318147347058112106739881385472 0 11099683338821254631013391488906767233440950648405987655191637597824208576645488001148639317580889225493580363569698739241847433403071548278148657704790701881560812698363354520637604253425406738645386346931438378422049287023990511776761336864032693766864584018940533893735018616496288803975394878048763897364590390991676677568578851827303068448085718133304045736327045397539934496234347275097852913049374953642771099344772903249000784596589571932046230142198599961705789211329770502845507424580928276103798554704382540443985249939456512572485882266061881181472664074778029772036826543248578641589414870317694121398133427593547634915072 0 -200685649911770984891177587350699148415414968253317176650578373851164258439347602041144405944476261803961885051043563557112195554609982275707599556200753211355634221792854876406807450820495188554695835907804274949739687399509363177227530980347882338540509498868146439781088395215416534540363722992800491326533967569484127121271338179797060018713708109571341343555937989880864489083539765957956399421903597164690015167831429574637036355978576822662784494772308618733781159475965882593299867859856140876659467867792171191091042454770720321139022018799155766860962839541142030430661005032553098914405725643018463543042750148069574298112 0 3584166506919678020972103101577747003991178696829433169823128211858395034701150672611488070357758910048919738296127082203850611306739923393871294387836520157760498716939200511833742100033883918438892458246174480721959469860157412427893501901942404572094721909558677957397341357649428820821476845307337238834600651017257406574414537884361862963464474929577874579172491031635210309430039264157979122196844915439934325719695417603702528852731366266084242203730646364780708371605709182266995296051075709877949393453801344843776331697743833978601164356399294141979576876495996882290061349441030984848765810325597571504675466484430894912 0 -63231158355904699742475331068531020769714432465364274848560262378828447791627672693419384780255142361747602751565852680327272296752296548363312318956701149534663552285125737455042641648754445370190205285330463481240318769459041765241389506424372081647115271589250528942168982809301339098338065680674902829156514447062785917173136343004780438477077306973490998816743576314547966704908357216119377089128282126944512341252056276580551405755131995848355186194296047610011124470486701876362216223187690876632484004122657986896266761360056277371148403285533458336546131441928848332378987501338402137317306717330023431881542021209359872 0 1101919893006847022915147471013659999236679763434746889336981237042299282925967884938280122502641113552387705805762598588144430890661247682918164650993460622954126304597281109297760697140701823462710672807275650914579714094725159438377962837856505734625876608492128029559200747601412892526695004268551037544187466924025337894586794347303378176968842786645524025445749941787323794086233477705714265198392925143282441963262740478090740866781166959186074587091731546188712044835824171337323754975422471444021450819326895131061872206002317147675129405484187408318535961397205902235508841365713496765246680333733924185117302016618752 0 -18969221298672084575108589857102119930917049360091689101839344111696632095489019656259446302406940476273767749474947294003840729790599554442195327467911686742896525993115230103470480993674707820252517932020789193622336008348153385027384076734378762671544844129597950019654598061746424909962837140372474693153919151204348519071285911899053352753917373256505553338510392899559886094789559107867185104085943756521976059590762549429021210757139075836256430310436529889400308560745783285515494318803013019998915950943982059962334606597426229849494728702592947701733141219463050237793635774202482057229644738979141440923180616561152 0 322577516261984031702744575486866313671027619555467189810696702215934673157614672583656609202713658026576737086920726799808247156523097958290129085576659430336954664179143344358697210777919900165411910578010162897879757242761953113422446717010986817551957154920257355843227344210296494628099895857843854978950197540729037931154817871109375805233708784417164255421799260707220733466473878953776313902575915276675860648907629475893641894751705064555310449059410789606930581115097983819626653842665007674716653498729155889671707553662747027186164599612068595910713724479513111465872980651033703527542701060231729324265890232192 0 -5418862856265422519716079464286743034669090031597388729923420343045572351707701459891849060911884557631095651747435430870669984546736809999041178903495943226807197321226343590120594887625745811089652305365830287521728017691409039671710717140808864887455012631115244139141220888599793369489017696112578862396347947811188446715768777139465749480993477227424617923986096189448693002963757239066732020226809733537196641462179796791287709271627571466850563795911670721451215025514490887029179216031209129913630798086304800158553500217937336045868229720002135922338174258099311530150881814846701238740878442811878853982841974272 0 89924061563883720671815104857735372175201851054535747571588083954672862873704129908263921546695246777373870754503287874525470105173926890056338991683386032705102454743672016346455710696141428060071126711642936822940364703091818088479087167939035574984486380183871665850569106771036572482210741687510919305488767217014996606580912323057193027026587430859261935303478535759681550958209778424600960787928652296560520016405598828654311354208688711863914414558599673061305998601188169109707546594123914798925856257172191322252292558580930520095941520367151531139118743593282137371354470561487612896322568231417394667826582272 0 -1474149122911388386224347957381632113942062673752664995768129307546172381534280014218221993841812406975857552065894253200320787794278274414942745440437692919218356033414622887042177461454742829469923723257033597074103294890477172173073691534250391385310538184168751399906001671209045614136588811456547938988709216035225854948468971641055045017372044852645248880334887061729777470713981805393359473993505771990900474536247778489842529155407188112307459456943580155091653841562522822487119150597234414053130401270483313667593399168651787332801460553731986535037509157888120524721023373893842586590825347473117911071283712 0 23873087066301247170763931032062780191873169035077276878350248576299494993378015808451360560541477917321011420214518599820401596140847318256586975639645466122718754417308790956062938479936354736082758341651449059018698998040160424003843708702722914443420373623992753414201764941015742233784265455625796428389649126633172477639874773141919378724714253167154240344098328115013875813898274704101183635609317375595307422806656038674435473332598604753836995030533307896856802131340673393777942711652130805629809159475957345413344257392238092172399486231679672158049230624845445273593940183117617196201891712763974001402272 0 -381927705341151544749255370131775044977253183601558815022859219879356541423320503615515578017126956014006235689584183052535792494413206145055683848504538938614380850072453259822182584469551833799211317964012165974030576813679876232912605140573699247007909812334006571440834970561867731555141085194673205532169560760805954466682588907124343043117165342771499188533538345109402537683102262565838567939651818318117135254389963047989729442267259193093805698979768731701246490160652983311025330990028026897681235734500619199514210443545276471290098290283347276582357187283275358122779041410124455144543201663875230848512 0 6036188185076029947237992291357452472689408838568992093578843612856169572492706113688174089032752085201162002783565240674395131373139596230579868506002607416281317979660250980651174500700692193150523744886086156395328017664670570599844933525982243685373966054343250939934770885776252730970327444247130600182302469287737265079335502690439077292640091903409258589854701754628429226703265387406016383088054352583703089087419261778360909524027273417872165528431076606382199520956119004334253160221959791665957010475407425094098710180745847355345182741672570414132341501212283177028593690649202630997588496667406601472 0 -94244683598436928343909917602374165099819049328704815387858216543450502973358232607600188344625078514800016975010195610999061992772226680678586698947205706601415838973115108780556698422353101847488553377459865760774112601376456015191548606074785678868537465749257936195666195449649245748393931101663399471188743494456758090164996500251808813559379466535206244325631436351845713181681567712852804587348366267371058438765345930299055798413882196761534469797285765296322043998296917362433736072810188930289879533944540362941858637787610963776485857279538982836182813801939730312265465535509024588962720354007777792 0 1453673049792144101902002359097800545329074188826487445567060333415384729724446924815688899261650531997351410722940739659371027620316803291233031713190182218930741207306158452134452292722094092899672897666858348692711164172128960904257707833078850242887940841402411623837966809408053481578052452617012703143980022876201404473983182539142196082866597882625499092787805379484889082498799535143446794205399702274749294545474662615031151101375033707291206043167106510846987168628327707632491478374120739410383825991898483532565516733796034173464424734380516610698696354521800316171803836625263762387470343698453632 0 -22151113422793422932968057784472489039110271995322744596775124558303406339780143271457869221260513720195781522792458913216836265966923546018803724801098435799212199898040419261957705958218907309279976424186417531786301076603388435397096143950032939045512101799796345547927912046540285509702101089129299238817255919200701632196862897678920918367076411690076894419179568932260894643253688781370486348579529852584803256855949522750388746556932790298591404135401713653785558708262469915182214909952349005306876703830953696484643928463922663171555429705601095248810037303414134595209113222473693948849260290473472 0 333461985030265027729559063187886132111163209270505062749960557844839621308868656060224147196386122339135518060153221990997931264423308683052042817587201454055871131459009848813873246849336710303652158698547819548171039147036985886162583727709297858279620424356862166435019477156913990984690360667932673194692763517455340237292815263976427250510033998708914379546888010485266015206543022454202063634208511486120860598080385268566397017721632680591304171351693811184702781446219657112572150815591108045589284582918952511122199489785717493243691628517482679711431475474149010966340709070066907257431766806272 0 -4959317393186660519653010515226191962814196047220453878847614623767320874811109826694633059761851641974051644469027682477307867252705106343018377689005834189582472888888206783131938975113603827622550485487956463048498809548703664896075194040660174899191738244982581631607318561723639127555814779365933652263349058092555131241085238181678419027067913286988663823377165449874975076780304135167855320765490206922457697691322881177351880586613243822970937348584109955297407215886263737397906033646763045924530533651414238920579382750604149246688215338789903326623584639634108844453229062991359863114063882752 0 72866008859789663941564236289368135368794024277101579586727984563592908154770013928571979065483062000464022263282886746456295646983970576487779243035490727217219925735060646305094212915870114104044042708139293675629461180638485556401850905571640305427150025667006896560571005448708693048885147383738159724144220525159116743790442144704661172884736176386774713742559641305426610212711495077749969056164003880915603725670959917465663233197469098549811483026079887834887216079667536051696255898345952042010666438716745870435330952795604267717429110085138742127012734560224208115472043938820365616220061632 0 -1057689320972986734983117389242153334712663357712109064737439963864390092353798638332614996704703314585485625793668096211054677439263879050996071232517094384567391988555193499587883755589477167195254424440946516657783710992301975366581788405210671497746714751938214497381434591078114899703918431717315659379270728026233676629725925593909515210081527961960145971424782729154614609839484421903245732926865647781874683814111242116893967024300665534922108523748038909956336453387432909771326541296032435870765378159290811230713956127901895877237396812428597759016610063579511483518340403737107440439485952 0 15167839260402782746958612416957653492173233979320129294783331510985445614650141543344619440569363252258875912169164197040806200472620334904686130286073623848273688753309299691345492456153538731834549293533169222085567779455911257869802577370758416660633458507731816122697543010661206234538846153401449445012521121161793187399105790702234229797488605117322265348877504485146796893097742999858147002222414921274508913044618036577095529927539801286761930145791274187792300533416816561543763115441842700782076342578245032838049986386995752233719418231834000145755008948213584611811649614681352960567552 0 -214893870495254736797680408050521627764582169868797932582707220235190525680679716311084846154656402634256083211185527342475802857937294557426965102308130015034065854115994342340507121136629085360797488355734107081154616721775315780301619745765972159460041459950104166449760276754130715779792753499662635103281306171724576149014372389965174759686709318790474214292959180131653981679203245557912695733535660079364180773017866378763166842815148108342102891412887139205321357993934883863843834171796460123190724254143529275091780863818468436060851184745928402910121824306503974868342713663109503980032 0 3007884470963221472989653907489173640649702177148469744248133165778649336263050462986491556839150570998954336757105379884422289320213063620756880059309115109323376305734564751274929100343635098927777497548983711486945543545447037319814827129308142206045208248126834118005161212727067908368416479767024373134446150840557271793773028750493678941837447024623649272604980895095536182996296624435574418428454603460204516443889008430866973333143163319182046671563438231915670010294918715202908194767916559762890839033929984256043508667632270334598579854394117174517869257973345571276675459341766202752 0 -41594608171445970609540524504559365100763509447810481294163233378440868983101629715103817110526463510168469987657265187450591723195386224774592117817631740922789306888749596283936922421920354211455132308401858920560321701762286598507247198627038899160137133976598481918509603598194516197515370789018757487731775593461184176180641362421018958332130075841617366325492438409401183292733921644442478083462144728965605702194563030656650466950986646850214601245769546418569655367360128981417782854541647708673405639992527206994592790150574884303768945613498531527022931987927647879139172146115743232 0 568268371024110404991272059628943990481563706008857041663478854491441258996936742447792561938607579117139237473980756281378828897713338597463998365061479533904973514094796047719077029995499653088741736303357548625636050963800874807493244074515241749500023048379616736939692339797939219174639958751097461433405857434223979135721335645580931466492524815935813453274257515633441170040958159563533380008862131933691689417018812892359005656476578938605288159886874420119245258974408173142238908357702798261488329702963080257899888147431811317647006044093972605296134536646953414334904054528559872 0 -7670296279269888897708666401661633720073341000140487528301144164493974745404750999919509086361623163448521819370423110572481101040507932757537131971641906570416795868438574001604804381945536171190415713532841947416623073425389579379068524710707062435774754972980747535677426033023249931653168007019530074662153156222768482669096421017601007130065259970133359184088831486804546847245889462629203161331061817493931228634087126597168051836101418849853927663193823635050298648855854214052600963778655222357719149694367433834335644340148754418040103646353070118223419757438067262343629351270912 0 102285600364555717237012508445549772319118543939013716322491376350151044242126537802119346285909655305904664611323652602318205929615317081147965377697809755608519071829905860211203261554363536045311986417416050868259535669437858205427833656121977856603588865621762743675145633099513769567313868802020352772954779516946061656590065632640522681768568136538948724233083950638773108615290317496189142198525882140245756429216170847816203498583274923653514053607134911331606560788702115727366203838207437222501701030946879183338326272822295500043607123456086277364001211987010158949462881509712 0 -1347602801066658046509365754092933525847329192051162397518774181670437656910283019039875012954336684896974760227868955384940763433159633960748285319412951984336839784221411479251695644261556411592711405563099168118280701465567523723545627814205620063126824367657934499164120356245367045546333250094143838341944115856079353039195218340362530685308819315266984185848647410150680293652969516043566294250276173388311319365892846689458460723298313599077186752976997584028862024007687767338075898564065575458704890286650973276924425903906475125572840837818390063053792301926927267377638938112 0 17541048552445320760998879922462209716488635295418013911675731984078644278035474087707427260861786655116015477406394028156208543844795834331200031655779760707154168533390666440896943133797173284510436187881812443085182236078560842189343695261459782857448850436417278059367219913694657838732445817538276531459751309340808886970308409851370939006348287412409952336291459730900521620283201059200085673809656398002596869530625992844748111180042388393019917778990156447996679766061920275141835151650229163801723762462653640251828721143890240440155876519587061205948926566640471443518739712 0 -225577861323091357960099760525465582521782775008663621748290837318709427000698621645521638155250590570127522115673366922092134425308741024218378175286107374450088411619655318967580361376834112577724063980277791553204604569519447630110985997713062444870183790332156785632916498699579699586310362805730072546108701075657311640232331208585618059441689116118402500825596441488558409698275468536982432216920371552473464700135520503346667947676731997090942486105724084290269030863447543611074449464009816914698947328343775974431808837905157127639119695379111647194668532324465480877834752 0 2866061888926758283693186827923486063370393338637944640565478904908103818343393446902376039935003254156198054300050662189041980821385081940501416851298951034241069549453877483817282975627322629387948177287151036900871541881905001898823990681095615478584427860391795458924916700598817827800879475835443054709265136735703850446464518769672094249670389005603407124575648889660198969519716815072015616913590797279222058156542294416815801936681411324342919498810613240127145982476982241392462875168916240618667948282041710740664572534743293486409520164016762448086385741435862696569472 0 -35976884526139202548365395588534764400650598789143831845352578842658941968644909195073895841896026294271658649370456916786840885519224120992086427755991846229449281805137435286087412277212599208253407432264216904732571747693152314130637085317256881123885712849152719863012340736685629915206856879507776116443611037998360623294686909344496719668664036634553000341307581046606411026728297902970895136531512809492816323667821266469456427706546752018206113123963189975715368303967371082497219902633429947538172544429357261897552144529048737896272498070182727366058484338823848934912 0 446180945061479436946625452238102406306079228331329907407335150974336866436824513693680266796380903609640189084503395475453807242261629576235236104930330281741335821289807150850275693064228186248122148642302969719653156527650258197270395458402214552397061701013577881134626780035783354721415149488015593922480592699562741068002367005416365255193998076988544367936092878915467235774141121223447108372108555474981011019564901509182344797547867817725714888813194166864366508022100998237720454433829527865774473589672285092565812783184522484411792158150817367299412319138155665152 0 -5466991400700742246828868978568885644913639097467106913673646620750469229387667338284213532161378720362511857042170278369612339646976759754104623217099939274323329017853200795163349690960544995418137943213328932269716317476385445582615822580198445321290764142185240328182932942382996192803748580453779084899860225246464234033706438407372563197417586424346420310359527117150182831377401444680299203924911458679468741450051104352802183653650403069671349553177457896516736203964076728910917692744946108845150632701342173381442653997248463147886255970641301044761411666299791872 0 66181398366237366804868103813627963415875930551910787435308233177674158484110771749605612431152463497624655343478996377849498074891418993549800144535643476257584288467699465857664012696625902075382077693736330750130066442001505963221305239802160243340314720423323196631166490521552530919062515506479088661913479710130387259160710351569735585317879078099064707271451381637946718834904549855301909234724451100872541174328813911192250736485293248642930598265461260245046928774144041631480460257588288288762989633467851427883172755695900546653278659397666091873484544845378112 0 -791541667545593667789430868721030531151730835547855587017353193586758386190499856768009939294443291660152740240108522817864567296726756123513223094941124774203970408559101473097983092576457621250073164523264387355945612310946626370535136724866749163179499068870383325388464846553934092716264278923483959355446993484459474324441301898985473101079753111371241591742824931071655469168080285767048702173022219622771895356958673466746164736879713851210793049298657440275185090196800341684138779116425883854260598509331080098392700777496682543515239525165039519384628117612032 0 9353235710895865915678833927033515738112690353898170563013573442020279558221060186655323609968229833997190275223452656841863930225013937598796748869271934302029877916961703610643646551461072156629512202135559415671004510161265084661643117694815987312200624592637160053544883229548456687039466212110872500666489407615829591608743144736217930101326077679605820022866858351299803557338967377758147202160198884930234102290242184553150194073962560007353548533684455795470355191371317801877317069569802888236912095869348247746531722686375316119962301740032295342462803685632 0 -109194317445123058566995701484321470779437651509464517140893763822645558532661817649429003411588862630575916670315190317514197049451252495723546224889258177308850747473949492087274459876162660171060092474929142607241870351375529957757780900326296844509899478794088053406558811683451658849812843922777492876919190625924885403910903183243880488127707718938065118219060659880016006098663555785953361398149595502497470340342788030252022975617431318966051763088722255060124836491695924529249738556808710058597842972000885139178351295949802728119662096984508969037275238912 0 1259470231828938332676163699400411854074137793789268178804606603334634452955981536613573065045849897908687140660222536217484041058745341503659250762113181457471509866265219528367640752857821918360216513144975117085975870245483827413886010536962711454867607090130018957398611987239756223866065773163624287727228803062710483344600783460537752642238377921832481284128151889844755372288063591180874483873498236989205720376166126813663253867795246325537870331802797583379234635161302122108004449294786979821075876987178413654372882420424388314896883672815117043223157632 0 -14352414855236776290288899370919590422189916298398274626368924838594851218109456618235073164574241461453504671027425222111211391868032045168383386787575243379521076834346916398571754654263886034116500732145347424763860533428705757534254334849513838255599596898089897248515946432935115104345272383897963806950989722906896506105503082180937376901019934761886378415826669157214518659624827679060686647249118164721534050412198011018299839101873901673777685048148543766352564777058162881391778150675998476126811552525207577599993489235913275141016205896214246598528512 0 161588551613688060202263330471112998390716002544580628270494304291508731269614630887367912810236655651447535108717709686286889930741644104901703509666192643640508819176115394425566690877937877562265078240033860505492489838179744082655581347851580567013454589099714053750228521485727314096913266914466432560020826482223729262399995590425074900422520245946233762118875791775583282338723251957479381913476801888501598110546929013221251732058735834926507917421989752420933107749231853211376144241474237464628484911292515893714677779945520124535204532360414255919872 0 -1797396578045057212469981049511781943905514046276018967391287060429777072607218561669884330292478494020950489897844051663688682846383529568730954612103725619234708782616310918236206370270276643456101886078824194039098408728468328108285425302832095321404076053023153533804877090853053964506196638807865488997304193163519916749624954907229329501269990078889085165926544427060848194787647819784791496201355082551870503902243065826783915450943978163450803506843695740148813661939180920172686251217858743558623628013298026388667818411084221147496093804377773292032 0 19752586080200246532828333735399500709819704671865208054878732441490072792240161537329127726076309392855843560589192376317777675973660028949507523254011260902408416700836007699427169896677252276886101494135913775978419918145405828651115814018181985748403119467070260662879388297383876478366176429095066253795631214899121019050445678060290529377855437650626360897503997466677805163596468232805245453839435746099533202591057667546071607416443877258717486368488825548983947352090750158299691007139922032420384272220178073794049141570369411613993162261357563872 0 -214461630271337576856502351044107588706923904057847957025997948340894004687108916913718491198802123008743785114020187392621007426109230593583248112179219413382429680169630768280868438106087309769561321508360368549496095571719689957183207730443825272850412447829673046693177173513207222136909524528296400730995113886852467110814756747375747386158255178777211114833312556748893469898141647943314940456081498482771894115232077267619599943276947491625461885592177318282451182547357100154680893685169802186718138181036072687953490542619656269094783117236598272 0 2300485641094450021103486824468285152783964077554456371747403949445112562072602575891198172827879904700005845321383772896175074515429641659680515316812631361495216344896347959449966297337911086519638499308404525487412274833124012459790466742854888131622005819183758565751418284566023139706787884918845258159188849623375211110379305513687163861406236309243496806484408846621264973216358996641891596139337863628142926821437343573116204076190766379342880366602267462752327454572015311942986192380176185937952049332683746785010805257816657477980036038102272 0 -24379919635450409628159268606706830550516490068033675912435181793950528802847750227313091924802028037080711929468527127896246706194456829872271081232188546338796610666826323114238485553907632096114288676077997559569602446078226584889980185030383205987366386276012121362263694798005063323107568040279446433114327586205403047617311537256393654175630747959881019509020701338623722772504284232350760740258771271426530362466623519141020395582304885968739864047396044363690086820714291753818379224968110125659889263912878596025002949139792653134535116349952 0 255262021543675193566797731250529459929310384092915737813418162323898306251924504239067791425573936418922857873996755527890246066795398579815847466707402394979288887411574894393277604083719745103351109517764857356372122521745991507710271234568805293775861773410251119377741174136118427552606802246054951291036666840724891573757657605442518371597022420332490804097030727997021814213293112758340590127459829005945016291015150912136973661504148752681236724520910753134506519066250887697487371876445120635470133950407701391232714213158986873502723057792 0 -2640459680923845344367734924074636705367113629391925687449061151588154172675890904659532806784233835363143765497641819809776403029904933017181579674921182642939927861991689988459141476848097207506368204270156610899046948461060831356011080975603330690252491199030007463467868257437349984737769137159122835904667870393343570264202778291484947386769935917144690386741994770842044473630147679375366713942629963781429023985744296337216811497559455818964290410697901968255091055596419461747140872661777287879886346941440211444419423821731955317315968512 0 26984248230149997567650021759723727149314494550035318583785902543943888511999964995509931859252168008747952722359705267863799742924515827389828716136117750576735155322509461342050322747001529715769848300802263142291617439994135881654282658902126872750002298897773688856496488345406903157117400899261539657938903690522163231988809971238210452147787943310918657146998275079869611934814970746412519107805904904046841990533102912330736027006998277259063649999510103321135716177675794470459868868716923313158325721002539271473321599885623351055208192 0 -272443489260536938851333307294358539387328017030214038248851496107088275449349158459264640038990616799795726935545265726719427087889547102766292986108636634967076485481213089241941761879418782708847804011821754898116326377628303060037997983716075539537217718977681409598215520912823202561497094942219833300831160592079626801046407031370474241023281368796436396005097994428200101917084662021500485307807725810130322803003679561714029299771187525538273953207705658470455330517786334425326139409453265005822501910162560580840759032178700415273472 0 2717537753257925818678158753584954640560040667567268749410168827916726058975942201745452805533118982783862950726733152809623663606161400232622339889090046732347075826045914351753280284193204354186890889398784848867858548801250040124355107035037235979049372541855468785886094876098360380843753468580791876762741864585002439104412518984451954153123886780879397379928419073663792486590868022580038662844557763783976758643488768234583823569238568024261196122581492600826733122434184375863767042242499414777733309365950766363973279900304984793792 0 -26779676600555682160062141077449526974967186372416996208012156955434077058334559045853937655954924929925874305234942776482508910319842952109495545763171711535389263375717016865816764159710385285637114551886227589091384060173993656245714712889208689768397461951834419155941634222644652112411458089698439853515071390150611284573583024028152854030683091853362580456847522116230258652382720815578316598692494988100684399649790111837600648379751356253252542001882739468010074706435173851474587946523209365924365224151113781309168148749943178752 0 260713210999782244970997490906313797045313013809381154100474981193363980652278823084724394556044407951368732640943748923428644306224143174954771943440970676297957924232432573615436639150377542102202893251471113133009446233612255418191658752191584618702697222453613857980080950521416935068237712112151266386100089399272048432965221113381814398140939273783478705037098298598814010037593624886561813735744992249248445341896425324920750215622530081155334238866365159003370167848072441137843095450618499422425247608531397821238151774191855872 0 -2507528788231541153802715377653509952193724641678143935608703653913769945512278751033694573950436955463192686154847281713470477516361474699224652587877057999488711625872200781967507528188061914942698979891095923104764624007147704178706612357737581474951388998745111608692973627596760663498269794744115727636376431405669406747925739934768363706913014716168232025456332036719435471392225599176990243506374248240553903745174845742446585707770344036759915261381905786703278881362998979572873962637037775211974393939195378219549004614758912 0 23825994395966421807718429532822210568515962428228062178425146515348859492900804170933325914501394598565898900955036838420792346193085213003232403382240804686112027456911247009225252646051059881996112379967276626164271449676717641365435191554595871227870251111459128913539851182032001894914584009598656523431220051070117760014350295971945904170340609215543019174333524077582402213889803379784241018334071731399775428865171068979381854054702655866408688464701989251599346521098412232403520380564187814241573110013580108670677507955072 0 -223653258144789663803540032775752095480158065311729026992727765281626803145814973496055401976546492660445140724377674231913039929034982907893522601965959390658598026694767874751504229364879202534524727755316262701521061086879522410589542927766159052694923205809969954412431357731421773442919748045134812217255043608803618201134741498680875596740272422084539265548246598954669437444718023776467910401183776464658500671812022305641519805735916251187871020857851483551846818688428053624529620638196600357398658527183682262227573059072 0 2074030816412178537374885400923147987548966825558270799695851916420182978789190181459814749875211904392047282759559538979775250710339592925496658579745454959922081526304325578034265577748224403534847127047503505072052810427252556013062362161395338405434683230995179418416103612214808103782763259533429153254598636596117772703027957276730499937517697009931053417058374510396557837989811165792837262038965376625507382823007507992987288548278268912047618071484202126463803664127347618762727934389287070431417049738538555838370228992 0 -19000607355640717278290545290354571456669460180752585123948509583963740181965887335570341131097501348665300701227524353888260908341805708418216048149478634250400590426031586249357644715354865785587374897597694702838607397887300502326359810996565712116007006395636551505932030031942645223392100503142683048460677342178747900438368134301068333411289830774552805655694486399928262635753763098659444033940637308640304136110281231337511120234355899686206968873609309245313621841680685786564609057924128697454889258444182544647690752 0 171960385668408601107155530916413062958019381626850358008315566008934162347133555681923597223814487730761926227203677005124944586280451368273089317275773243137717873898193821943259228753206980104802195254811073729905929171564250361842050480871928159665075505031024632545510791954432745269443606002904559635320889025302200993640723384333144438501928156874262168649549918545513193493264778593539856808552739457949304655859487266194451585234318734610252973598560913961181255652986967916289813433057471067114353264595491413605192 0 -1537425765405721990558542133373723258041863316656372231631778705440504809733658343744990160070932379081482879513439581865698617742975491351336320074355113858631779734872865272327088418718470787414455086821677059324091419372582590497218392802950423271362319132086059309334954212159434719979410576999248391663827698803005177212653836610149284497888674650496899342932021967380479154006138033808518224578136247514008415493683962889761347433346858520787230409719556144094261641556247019706090563448012798408564382757015996278272 0 13578778620985121630599628927357358314641128078360154250289986827126457411178023988109373321315114138611299181140667639974337083525546584037387575824547756039052837869056833680322447323806924056313678197932161805152443761287088559592349774182532499221774693815797438198404572589156469996363427432852645128226824040420106858869636787716117849398370593427061622506651199003642806816087857823409600597184868307392984786146998233506234639033075200886836235174975944785475697240558414846491968306426935985756659070389567855872 0 -118474226052351824270584630737831942394734431147774725685113977311244856626832159098651423407337594834197737390908661914266472322948950354838006201801801817849841073714587358308933894249218594710817346279928491169800889465478385914819435688168757522436275430649904609215674217297335443922864353606595349843855495542535323424250881992391958997911647742526063536272622666200415559734040323249729487896944470427419560061047093036175471697305431228632231779343389892149942036980909415086334011941703552328577684907366298112 0 1021125924184803659055425277319107501112639641562832403709495081920600795661112291528218769922423293157092648428271205749484740176867822006756715807587967122807208230726798801154929956675944091948899059280966575262911757553036678364006052909211531779916354024725721928651854433182766707244991495876150211745455415159491566464759462406031533047162030254064412441673814857418301565057051412522525016817306126623964518216234364796648204175888569411521360908488787478343743869484208002592775401631721581205473238912844416 0 -8694055750466598276275045466081606736253242664096623057425394435247141278614145453719405992355785290919947369471676496191809802920015538941432908890822616908675170954518142252485354767064843832687507225807410429113662762145825946426026186220118010461126933267116883655838701202695977520110153294228377196459230616025783918786554861781597776292937995272138412281122137541241972593292153244740980360177153936540446539968704989749907064625252698090658423053338776029794067613003815145269842798067439929119937828359680 0 73122073701058128420776201575074364400537442938330735179313240421487642258744283044041191882691648591919409244785392878308740537460313330896303050129865244227731525705243729166778146722818627642271443387808091838750404242755544905910539489201667633933504503418082809578278848828380353184214675501764725270703367318494426226043886693910829743125661683358426715236997584704772184999660131174443330649861689862963053056479635922727390164285718504787523944795073255956520087499882919309975793605127828062311945359104 0 -607508857971008981375064327509305902531294830143459779740354659116673054914506203929984126545221329714476952305941062758956960956199075022485671690400031871941524139285958079560452433447498149596031046250281432543477648635089919181700146161248279009959102414331908987364581687134322480415202647154137209540457305720059472494286775283544824871116781771444583768618218673310772291992977840436788820942985348956893981016382139464479294229844995666307058461881377654277898877588894896582949394823981584656250739200 0 4985740340881845430880530774693819726392918803914928517024331921849652001859517777223590617900173071433673656044620366850145155608129734018626750742784037438163718196196142017345230386647782924265510783300276144524431017162349318964492784733848519886730400433305894429821935788746636467184263300083243143970496625685782731579701384987136996790291213455952755383679660473471515606759058824638260935342530770349189652264024989424990703417033326612039513135377529832625225132063947657184785633227193162020468544 0 -40417953967932808446584819368882124273138179249383085974667836902206986809391380103011961902206073656482471053860428753732194266932134303176251546843845510556701972524775332762774820013813573617021680155528531252868332167790362646483581547875229912697060109810846698201364999607590099846523713063759479480428018377926243750219428359664855118766706890540466454172422688640331861543489075316026302017202722160623878336023068116588138858466836938891684028441662466582328081841532652515876008743936730717107712 0 323654111782009158177287726522828980470198277555198986772367847683414226032749026279688109028981834187602692110331030292173465687123414200220185237044459267688013150613056108464677282075775486485634739031120194614716283405635474082934825241793247310259180078670179222049812554862887105495314819494802488213600290595974779908349484833481603635804905504441059168109177332144725600325929150388182615222092833872027341379172320786764059760072678328815292181042417632306275605782045835283267700435203942357248 0 -2560026046079992002289067933338609405868633028031944498517130168543328708795439185099773373984548770584052336704119067210344095902225013731047749972510528200911968792301358360123046159521207561543079953462673786338515834836096123740708915106880631573888095764743727831264326674888080846435127881114796184146526324707423957934830038742802884109162529276678513493749363618158317274900303298194138559802605532346793015567738439367022887550232900647670411683523963352833620657399024804174715905182014292480 0 20001299418075869064018557494904920101815845078134524603957549531497675184669492697525529847689218343880396552525575445099207253319778583278962380480377240442869616468291479370636893104819914923495853459349174470293644064632603280320326019729936518158535637007423290888487084727232394741299762988021602783248947956879770091370056459155313942835775413498390890636397240576430754881644465800632777577396219297692130794902890123710287485047365011658432050709746383273980022314605773629597620512625101696 0 -154353518878024682662297145277563807763781303710542323174415064240024963030189629576707306862670224637514361152868935931505636637769130109224509162459152165832249136107311129721448501603405442818950684271083778443153296769214437654506209488746526152255810716987532075505125457880272726130545930911425439594445282258403555472148505932802784833670221045164828257051227964359765852342057719723712234960575949680117420361484200044668559342697580083245783168067946753117403218788563937274533041683275264 0 1176557291019549145025790155585837983270765464510904420793379520265630312281919980617386331568399474799901807482567859577402456535651754411974461602748986230110408773418083665960487880376283666028726854680689256078615403857669720058483366379219748516097400176647879180976111224226219956758751588914125491395876071745696577014821914362446446066044155042917108352071590420621084841535554284126614665745332606473365361455244036922017964049728997144644370983703075290708045845536898716469867506371328 0 -8858116123827172780939354871961941213960152621792961645963196400379340399565252928343842394359517621552207886922204599474677527600511777230754776630602742797897215292176302833653911635630019404221712206763178543684597822230607874559250910172183447213508625252896111763760262856567042301904556324328199535985517151625573735574942766373768762346766295874988380477957785894290514836213146566749460535472074206972074048697765449255420242773857324617035871998266273133318858063432224954349942516224 0 65871071040857184998219415116801688368075917155469149541921644634330744585292727531467234777801578374150251820155440548114387109461990143698334004701849568670146545919666794396505202439737449456926619282939620955503143832629202974444993465544756514486870841796793172534607518017052807827553061126578347718354101212873864407141044218890422005302089705594521691321046168022223202569942428797282372072651886166017723010815226171748641056136501963910759044278869436963956918597718557354494197280 0 -483800443167338432181167903401471631695317788704785406907138265643906842480069525885386372863111468125719383677641324780726272439793213012242817599473889642417362015456143870103504814605032547327442497374700160009102433143830517558704402701194342101524826394898155876508109514470633160291541105493373441204836130457519986975135354271514853441895477656029398530005850253487569267170155630876159466076093249788356647524563622570616636482538337416649077068577492967001685555390534794175186432 0 3509529420779760343209359955398152113777857291043816617301808263116743318079023073192704970274977239208053413991248641546273987469709797429616212832460385781462858345082363942713627111625843101347974985911615829300130299118355560252712601556032482001790138498014622883335616735827190788382725593849316673106609920486177924125299227781229775547597279985215463838438050151782872577414609636528792416403690835709619390694786330699525225985107747315418152595843334912429889318669089288672512 0 -25144053930321965557075231623988923305869179035417178346347187621065021633106007074490078358222855387866547406841556776219926783911103917513354603409070106378225287102003257296119360159040459890163270163932933002806850288995016220170828182111250872577002708920973900520949539592809638980848402619305610837342498227374131510111121320781236976300004560234975890058028605592033712584798828211201620703801316831817220580597626479159407602941276609897177801990446100899575400448142738952704 0 177917219573133604947049186820481393537025201499767535936480136436664396445539975331327321146278144431345294739644020734123714507215616090914204231406552754042158047248368124955950523938811323315890732959608808923801797188878288745288589190410659760122684423461685912456138546350128922582620590970871672118835746866292884272609845841559895994709425936725905031626607157063035975622442284858975826654600325484854170012817649827556555219148730864530683969933911354717001180824066101376 0 -1243338002410100448672288371142327578541536692562279583084179875503617749031793477961861705755986458819045870114237362329763679377402839158113330253270533033369230003941354395391978426079600486937903873725010226808895284143993178011819711305630456736083371156711749114755374805878919099878423739263736779027279550775848798284048578879721575351630617974093557617599334440655478623766609577590688362655701469321074859642739284151139542703856384572943700822183535484893674292811066880 0 8581061750842117026401620690474130619886583177711369872284269531279768935521318813473034138613440966256773972589046472876697970228107638806690166059224928955056069558698621151165238037301285961374763172069435631871785459278061543660406651815900550714603389990452751538102096032788312290453350822400020523130764014178384098394764663957311925828544157949994245794285120217604590987217674423956249106314806690428984634364905959367652938560435041670888614599032358175047396315989760 0 -58487798303895918476128849007705215696177712019109994803534966590757485387138000927738133005217722927678472713308337801214012604130815792827297724183580106496831539701568936979969083233597660706847987098565723093647536850113360571531681716826592625973984392174349033983906216534687340584870099636328257609077958526930216622483738456662260254700966948701936210306152485000900949734744002303566405731866045946137031745167741839528481838332087210783870293934406411719262903466496 0 393689249469180216504153459708297426335588588479587097903999987407148540204443415156004307249967484743808276316294690096465112423544333318575436172315641956927946567121294311676690328763956827304263993839749885120965383580027764081764541025704088894108279984751535858397135252168356758961536699105943006214321717187957700727645049985990495404617542244538975967161722533360530195187915899451145998819700859046250813451969305209555293413591065638780588620564002968164219409344 0 -2616961047854046596045219886404453215328095905723797647223940244526912678211466105830154107801598338316359985121648878961317569516810531133379362941049544888363331861821578420535326230726510111260299792048767038927436049779790915434800065921558034492821806223148562222054154543706158594578153512706471746977319290160066495471264202985458915082995582988138381658957598273911121505837944599739206849214198219873747673597972056501226053490065474097178867903547244361475036672 0 17178590899201351521171414213560193761228951248621432840018281146336474610377997539720735742003060297098471875225941437130691589670911097912718246445326543371444357289024576843625085940083305782191684175392377821119274158604892040338802413762557170688125332800238256510032639394058413402062908745567583494067001457081499561923618527484448322140150695019895078559828861607877547646421733594365751343285873929087292259618461041986745554098945947634347568252795338128658688 0 -111356434338430009895903542206852727695014969319525820823275676222586147152418470553568849248915300567903180799165768804409666496988688082126292539620780925861527880158962304727302412941305784122342378068117576438529346061818736047724090261455193660058411612717657623454350102361197646410400487766097981743162087451798542737850201888956036416842840399570971347446669112357463172753776539185891431323513065065284969265335885231045039610818971138838380804727963281596928 0 712805898944900516321803116239434458500938872862321151301537054966296018412947731776186288515050945683153367655762168669291241922952619168842020489655582399968492592723821987443134885960982512053384075012865515695080814973866766264327908580604947281567090564410681553209650378942748952606573483633499690707047534144953569844538445076264367535275063978656597753364882968428329872103785392372211578549389846238449687327683877721408079878975629895754750364759687190912 0 -4505530105663197481037296678017300051067687234874199224210728998146627857223551050183496065412924158076393268277870777236831091988192964243665360856920176701856238057500903168842351226349908761340006838610517862706227449671798740926341593842876153072041696660582729259640333242330558728418997048868464536416639729036052967392321438265668911558115504667437198829572902452557243319229245814734571509913978787534712132574861476644627288458005355545934124469750955520 0 28120909333769995538212167960277607511035852984169178801891253459577086659510923663141655435042961553362764021414139344716121886482456207680293207426987400605225227227353728182511444671854228912463964528765000104400343333653529106442955562127061166158458694661363562854449464753589973382175798889405687719715954228240566562057610275757310088882039278739988576290000129017333349201283239101595061983888340943270396762279320822513001822057181576741131614625956608 0 -173305220429716982275230486796349344156034012876454273143297241910773295499574014766756608263803617144352075115128405888645520097164345788254522306780297274202062462343042700070594136511077989726842297483086397766618664682619379140006157439945765864690464787428746886823463822875604251336386476888985590234743052031864337887432066880405886968331109799079230914477391281901369619351984577521664279118838217321684951437216892087055793540769064843046259329796608 0 1054587138555344151778861415793090063254030535924451618639883021272639921766231118333135555494100278633863411060718350817778562751929368723080123613366900307152092561986583876270083078537808570094182380664700134091114830318121122861198702471836118191105483360438239115021500507121849182557691813370167861060839197319539218327664637480287279474075135167159593511123987423884841983879189947740030059924573772910021429826075062097410514233724848812463346768112 0 -6336235427933278757642762750616321515818236280316904484361555226832860754837625190000541398245087394323731758787854054133670681329164104515221168316195126559909950449073953050241135898555700054652633195427415337585429086093071965960931571533389326595486147462417846710852475580578864963340993390639506193324136509474172329219317688016763362857411347968307799812976360522898328486659446827243866446801739874851091516103138866478419252517317067018369795584 0 37587839550894698558889810068042063950515934729457131925890471241303826381509205953929796936262954019170508655516007350744799198806484953932414027736442128869995630922277317401771552362206473726372127298402872079629521886950650763278179015940686668562471810972065301343095145003086301429181014792852810419201154935190766005003237094015583000017306563380597942722992319867651074257401297976044226077110541170345476294365962375933316868605301347556441344 0 -220150463137491740333035030885690590076098255679739030271159330497471688901123876281267720828371555203151257136541722176924252886451702538789368225606781182396177623978295852452905601630490594392428634157770674616466101530350930117385972995092297240030788985124052513484889315889875512659155028601296561732313666237375931844618173304483738316215902558273556589159711520083604433903468733324766095057704675874512826793222744666787318606023829414334976 0 1273024368245131342221410697642006960870229439352033761651902874070126906789408143598406044274636125949071806060284630972697509451781129681872359378741754915638608706505950785605207453042457842952510883325359081694370219836678855036734898065494156894278292712849882936153456644499777394205543740388469022528571940952626588170944657879650356038240042477713603544748240684291624932990099904542319066034836828325516305758993794216874891526340851861120 0 -7267535024185454529674747420709719541276217830672946682030236892755894461860063971380127203664958913685901722420507080872854725358859213346263452578167457553151147856674819369738163196449260035049288976948637499726722938618835805147505154323707844211499798143892485163754842439419511594620519823447108728750258639071540765178836243539851392412790823406905447340671344666747359652819683246471777018696244952172470731197616191038913714292904226304 0 40959911650777661201883227728509356811291596735346873253587497054876055644550423268110997342884998376900080842712227838580003565234471899547715897827021133140710357219693947759484733655071039641311839770997211564234625070053775387975887262143694418267872885601227353770365875222493885142914150757715209132920278039848087057512464592601119851073032136226370338639825879311356011071039582659118321605478143044988311030125291532882617830578016000 0 -227897853558896428041600052388702805456135831823958852986449972071218721856304979177244758654016105065588826356720192449769640666963256340528553403505375208138644997950594062823438731039536971281431531658681567409849934892903936879915697541556113056772484447461714683928045730495254351829394251577270742986542613854388346652864276129657540021588976426117608205969953722048502334336408281655421102730832087030286462648022089616140016836131328 0 1251752335847078289462185989336393174933844976889680010182112212233582313967352128414229995770957482462109326539587341754395602145999674122204022046748579160184511720065379264066981862569412400038252684695692623548932316663457105085571359062619523997973846222294860090460880043872687455209708557545651674967562865527733510061915263004190182005304137804447482761305495372132952212855253502951164311432467200131564308069161454216437695009344 0 -6787047080061744906994698660776088155907861286847484026289796964537128759590146611798001324012189149095604627266277871556266311939081423470405634673826832489354993348902204999955415383300539997408112943012791747646259029305954828200322519077522038098995439397182300156217141912412063237055863112917170142527753892190758186451377732069334531158201191080179308364884231290843226075179840932466965295830172643533714809721506505394822354432 0 36325752966518753728794740427764666926428951057378460547778128613186501376312690301705513982100624093602459839206318168801531079136702926570261508173782749626300034749054991385346187758801817153745305013007314416277104559975950770568123351791324017096643913523188261470715241427681422504918081547414163772857034201352169376596183018907176594244453038462330025006329865038825963986263691897259217479835812050663536367319008755591706880 0 -191913906323967572497682526803470294749014599580449184076498272784294618070038040517527944701832429580358388355565080712334664237891830972043398721990710766636545791998920969871498122185268163769013888038583657636900706693889924256063661835758931095298170021157277487882826591309381591502264776360452573584987401621850986484426908710182062310202739922857981086868981309695996696846329771084207444137939474950448693662785765991604736 0 1000789570062221492740921596747314285914276951200306857925416643209516237013238833610814368366453166081482429941733043352488490372436341518188956370125857471245675770874424276430798857806889177370852999599555874949014074770238055298301958360529782715192198099133870168623596897808061356157763484680989083655897772783876208965797873552747056631852461270805552093319158787822998469177327328220599101336901458149286329585254042296192 0 -5151215841102591262706547316390763371454682872147476842450573765122235337416514256328035764390997222256824486351386116992052124429322130390097095739141832292606456969402426633852419673707561499677827587895816282496832334861967739827548704935643590539386186049608136143386135186184070074440963535178087820048678053170613833875714374655375320064478794249804236565824037512623013351004829215789636382473083014778180124518437846528 0 26169366939680167636180021625450867223525867612504968619873392262895738121911216739605650760970541436654191648385848695739868647571309743665235446942279368900217526665291396243626518254832143562308297906633868499891739726209046460062543553816732514636752696652281056758199505405770507220402234983911414662614436153247030321222898502186301151184476446678008401357087153390182040379228431062059929901845330880534785667722300160 0 -131213556421683790329787610983248177532522291013344930377958956118876817619406926548869039419281258892538470915246959416473763887941695664212622636097149911076166597905310460557768991716998510109239829930535852582243342752225636855698745789211829425973255191381680202192436317743379632094508412262846581091802338373568357905138276550299572333968918534097308840342602104674781421571228909415183210681824723721194522893928960 0 649309010076192319154780968290360363886697925299569515934032384779272478666798050537538054200432377665384978162779480837500304428259790393774035163550068022003040223963025898113074620889860504371492274126543432144324501503669046430894747481546411407873315725312948403254971745847378995181840757981364866501694046537789980692567449610299505307578162299728020029801725922741539277043049706219112200288164253878377595761248 0 -3171000231301017450728933711045786152856336731470138859354407405876643821256414601483766454197598711849559028473599922987703175355090193024357070396303350927958570679580054803170617340936611362207831170480633512177905018135451141352824612336464335727631644211367893148793363026083473379807068953947075292719236961313246698907943070044536812699606208651631070619813307205515465980115650243483348735698834808944907249152 0 15282619518675966465597794948196016628235272134686165042985140151072846689569250951830728842408489221909205741164757983972332851753950460928809791552091628788018008450894557101466663259930297359343515208668454953064097341955709949560304291137855572291019189532824372503354304165599753105291869126963859362263739216663125255028358441644290849568341810859437782836345404576522968120226000338744184397962388159134315776 0 -72684237371687243917645511924731198703359775583886697540402704618408997113195532640344024074536739583230359435790025849669332697098809581864852786476740711043896780485903108786921578861664341247839825909403991291682576411312025918074392339373429131266129953817162167222183020037965730630942864071076922830213888890502676113462185950961432054555404518310656001532747504480985196856452895220314387961055337443930624 0 341120227116799344772310356749519834981117740033098184818412172047545155513487511557765908927877868625172479258401817831787409164842759918123576532579239961997831187493823866119601594580426887885134052123119922722979190614037535347141675308498412735222885637749683415157774298232418506461067842464431751130416356877763623883433237294723894336082675923806758172915911412136016652977293861295415686989150321652864 0 -1579730649102745890686878888609182357222675502362276985180067678208720279476243121871150528027986095426259407252328828291036423093233301161909557672169783227485099310831880802390405042231420200475276312374024812754372378367454159262415926755516290343266411585019192956882915688667004630492837859485724245927912891925086607726823707431644674619084286866543167676019414867034054819381999122615219243106085654016 0 7218552881935993506280307332183599731602279208710101975879269127027084741899570027119070367133854684357377405556360085424475532409244844277158228716579777703096837529086256449186129159637415268181938297376685337075212875688909371671733106989904324701192826343789887664426897584007299779050110894229986209785537959089260365484488876603180638148870558020633286377958578516079316669255133800002629687888463616 0 -32545548553259658767110152667143382621909221608129273056064058744626924478650156407525069535632197249861405578332787044015900814894103407568725141094653687649528561778409058934965215925115090608685589488671634440983753185759788304172752367754464864394271543249247337632928317160476093833217600240224264794590318808112031739498960075088907083869224832980879972327072050242904116372390293072279451846744576 0 144773764741442046826878181835178337083652402253068956460367404968759198181111116440237201476832243530173510913308160824570089611116205428177080732232727564573800860090820238001871681121336464451678434332606289895884176928108571294332000805647180903321770075593006925621931833623689221720362777075770766740392186163524062609203096277851210079133519887606737023330392998495683945127098221415227130734272 0 -635370503296467058693009606683451086115001978350274988680943836666900213599552613892972470797028528956302439122002084944941231861483802918377218728772984641189959714984435884309118953868664054132784920759415416771527932021451631794202563264863167573138588887188538414158624959892748270376905958494334358000983118865659932818708170353219452085386868859111331066757415197023747890553007356589507409408 0 2750963633231248046998988510263649301088524917631333754038384394001375773366113767466771693359272884494954663633326532719046235008798399158636543282615514228497075080968154529337055913270650600670830074046062559294557260674840004994655165484690456848848722010005658069904296688952865235919935338268091263423754545597506606856791767516764818875920365674933758433566391209893321062732043126274044160 0 -11750181934920748263054998648113898686979423020240088621961911874158334552446299417685419231666302419197130153017060259008141536524657113327683014017217935989913243005501689653857888457824490324093347307045491914797683287706246793522924936663846053002815478872011136463079717793755003571292872027858263602939393650871194954648874260327519495787823261952059938381075614720038381038509223303004672 0 49509347451731935353717017719136336979347571883232607683294573045715212032922245802945184899267321037557540522041104466481051713647511328639662733045640919332176057953114501394559796026438754255185694467583967404485712741082911763274551758227708781537308492572645866099473975428618133994627551850162174943801456651435508394245426708006144961264916965406534882380619170642638584499759553973632 0 -205775282709797613897019608808692122496071900430977511339189845780260239898593006343358401829121365488611028603028342413439380169468744540009560769276815730180046074722049357908028434571496835233343313404828157113013354543290138154700913801856459674976691769477606206055671442057452216953619290349954829468159886318605861558467022244247133305508706425220337429918003086030364754771391012352 0 843611941492963062564188558146388198655056290718222979573991868856617719557807427544344002978764148665708631753624402381450032916268896220644745452599433132936479028744603269150925334368846164717907237967900186233938897741012873508709106233432194420478649355331019775514227762647854309040331433820071056145653864088842326943468191861855565854718302490322776433572536117944238269437051648 0 -3411264781815459736436618064641161054634581675017967288742973546803706930403840315784483320935977773710518546125948503392791935614828311985468015325943114309494231094494367796270440921863055027406041909706431069377777301038822700031566315033376462633902436309044712320503191934850333488300189004647914137293211573973578247703614258377901113441657749541400985294066531003281570221173248 0 13604751330208074428111778860277239045113155429347725518725945747370957171105078432769916959204498216720195779004503856706782078130940182862244172886580442737094142273482422091571648206658914666147333849440831190687475980162088459301055817130093133634949092343798549487530900184441940716891575111428548385139154025825627927167870912666523530799934055299318206840388096656452380010268 0 -53511494342360100506660009470245626970937449197415208365213230482004116429318830017122576845258886581873898210330638530169966819293402548502816435494498431002752980952447363772882072406476672044231123961902220010173258454616058177693843704475502252516007856829801481403879729650588905237479217564902451812406924123983974230239237745346926017182030919539282930957786842439423065600 0 207569349858674311083827436108504225311266656547068956402109531578721044992709085185047480232060423940142442318869847819156569905770527607511892425479278511427837019548792243200420890969785779605422853365962837997182061260436145470820068945059930810527361732278189664638194350471617155705767202439478225083167180107051083891492033000191076455573787201218431302836433319724470528 0 -793993544285707002279225713703233686642218635266867400805049793932207438192167117193402514130672213039553697261020837467190385128031743081504238030514838384222036356152220216290030014873229462374709527096143136391831016901077662281722565789189166621516192975770179568873560994125146499077690400976882694116483730473316576710859799829642593872694575789364174719967287561894400 0 2994923802309329959625356709497401502300655833177195964145347190750807859510208221846209537137934795076174831890839451743168403710681492912018157385766737419205379888522823676150012287958950117226054089774832684323923751508921016836549007986847302478751633032769412437979511736716793200781239428246659502229313357746976129100861508259664660165386341504237876403810591093888 0 -11139010843411480391980491551499604893964393490096166955170848757254407981669099543420031264000861402314690305153199035735617545378792296865794518502854146602513389806736074547743232409300779528370872304101670988928972249860464489814021528197407502919163130567141154726932539789960481912450611489502429457891622243630867808704520206376101892418141691708418497160293451264 0 40848490835330807560537273668339453790660465270888316368009599824045778994595416460160958577612960922162465116928171740165283973292648198322193166903372299210861489266120221714890026321645609582154213412421064874697825803613312822396395373486918534926026139192727157664332749374739557340656289866093745766745028674247513363262965635191020421631178410644524983095560960 0 -147689610276136999794063543845242315307858539727764332235456121921166282692302735017057070174307523067876514975525051662510812175401563712563418358705675797771011159378835883497961865304393374005115187881489631061021602486705719783738289052291437798263007215087256313752323377120877974606751230788524236464265093036824606839800852478398216944185574656365231113257472 0 526433966231955522843628797096568532228470724244615079447085860688324570458467751143348422799711755236995614238205427595755272433665889040323727184976321586892716008422998445236287069281317232730534886233490796941763984973918125789226178383090894218818964735169499667716058324787210394645718063559879120528668769482391330181200900177101877577361981328761457289792 0 -1849834441057237512991056483942650235943379949989149843941263985620542084560448847181778622920513289860207057305926087942876200752799526835074424513524971911472511173545710706575931818525372886647809020124524673740516019852407645840782889056982011714777185777315633525699544822619015138380409535076102379969932733734517331755311716854568427892021670805322124800 0 6407538984821598259753371732506407628835888127991410421499507695338645521165589540133877643317913333185244875371893928151489854404804746679112309344362207203087743394289716878132391111416968024767755342904786318644151846580196577822431114154548250895712938515203149148699165445211561593510974245338084823372178575174512302346918214271445680598189421298040064 0 -21877262819978378928409713612671831856960203721227195261104437975982405735588928564860582777851188301331831105381874704251516381834328034321696914311788507921847336493109123854699000564432418991365287418447187574982938644163518406187949382799590510288505948068021744631563468657237534823144091924551865227001919672732332631453411564790120415430959752677888 0 73622638442232187706987640358391026012446520224456493963070650780815318749402678359978853886192297501777691446575688235771252038744382964552424898262285868364130489066382396675909020325384063561890660077702229905163828264666568428868402815507966187751489577571651032629188827212374579770016448809207086587116164637095063438871108698398599980940986007936 0 -244185123076757713428709313482551294729557436041570136366514469512652643408862392173086436305535063075535215990040112432424712150510553930013080763878721911406449146117457227343751589391190601705897605203069711670365071765973133772039915495154064414442335611749428599089663809692989186274709899560416841470812126423774095718350813898507678997214844416 0 798157566427125892870634474338713960146166860714870078389842703489681013675165818625396364856883718079542825296580115807259968591191675622389308446660453865425303687205674194669216808340892548212062210433602658070644626614911974252528129822430916030585048624905734453357186305863244567231094021200570410243548514508895069878131686998757701979059968 0 -2570935965167969860222514544029448307116617916703584701416142957774540858351529637298126089967118783777731132255353782151667420868760678484532012885908674011602950239404355312302658914023954628965776209645045272701763103984345351234583380509984438581824448996796147597179193787534475132892244561347370110316405807621308348273121776036041856553472 0 8160148117303057195526855440453340785640987250067945029001790030916961254639792458958639879051499537595167279381572251080526979090966600697447527232619745372229365805676512833924504310258164729521828043237075451607024561150628795379295681398733105456998245930266154739462436218813174252984977017909739879662112890471530210339709971199446795296 0 -25519920609455411982349442979260578662693389409101272126984195266703220678852866691466086414269867048213218901350931120796183761711453942739910842019071495821480079894118692363396949677134503445900533375520578040936202352315684164721026379773638776038507077571161998748097111396583700656655384900376564938935266568103152127346285348647394816 0 78632988882738751293669090388554098065645819945718127695600303165100612631217510494070386236017896400258072295887369530134805535626039594944623812414491002235830798366089616069418597693708742986558048779493332801457577297457096596213427906165857981966577893449085174278019366322491870754074738476677552875765243598472868572615184143214848 0 -238695079884634234461339971307236997038174708151248647048355851543880706309256685369462754313757167731077038063379500713381418773046685409901679598720873736518905857531836188700784296662679205353701521219203970607797523803071197078038025842954147764165439450520061012647842839676588490213416916894746785226480694459434360848515645643264 0 713778926581923787392583954558481693453477246591256728422144806738448248656694246954908503724386336912626763742481533352888332450226139477724554941084563986822085372528935229805633437716919937209286890462037352036552270820634334544820260362621268677661269115722760809761317984069616823550832489435397160082997477126558409285921798784 0 -2102486442117200814189762575529116887722489643733485032705501302577881085452483779565024006904617492630905093590634323897993158510376042460814482685117661852293413179827782295160788130542572006511907432929135585132544642683151526540606597391987001641784322949793967975900161759040617458352537473739036011602044541639681059504023040 0 6099845781863576446804357740828342136233147157895245123424225323926196192074969361897924776705892145527980836306993099618388437003783981781769842630782044819862550585036094508187453200480182842605349851710421969918056035050577294935282716268446318827276096550647896267844776857877596990142715964459392052216476531614621760037632 0 -17429578454449604181866732991230089671866675419578365822485987270073970000766183186689522806025865501147763102914784924337943319300330700765172584977883528935707582184980432273851321405379506389612000986536427129888418246784537830504108728276561464850795813437230764225702917624835995810843489877959370822647597878946840584704 0 49045903972700747783646340903004789399490928721618121314639056159990704787932341970847519945398886069140783348955793376761617167651021794007430174572425103990518466824686108284462644152015243323042893368396456979966468612761099681592680165581655826015526045715494968230067569202071900298575702049009471131352784801041234112 0 -135903648313179288317712977570420691625348435691397212644528640248208521638658098549626620985237753617987526048919485509478089929551760321773119510169515795920658457437478017664518633083460218222310978222676110273953346141628232806232607261587154137439101146695640375646606683421784181076523926661770491803855432284581376 0 370796720568207035034934411099032685423851398744634823655177000300837360286762091616166980658413104405756464185209115874538272134638012265547174700429524020070236393981048422673867967122273698702755747326407600640982120172034617623194232088419912357976560704071136667933467545957250283152256550093685267686404287239424 0 -996047656294898044653702270631031220426775450046435882225905830938089532928344671326770476419633575202456634547494292448531187324689204319956738661947745599602227467111639857353670681569300346778889316366627475441315651582962612084154653501865296187967586507767268706757887791112094410497373949047889396628984621568 0 2634062299737259056587005543707448203025212392464661379303812144412933639213678556900247044824878127604479945788101314490095079547506342267664402820905217273656304870483216422272430428774020406790766860103530435116545467435538904562862920359686009937947920167592545201665304173206646903695722823361311583704975232 0 -6857013747942109704650426758616888640293770810856345176761644205079867289527960794566002840266415620206839652319375685684360816448107367332611978358568145343373407222081850925800474626055173240165346912845861671493321864553586295812724402511117619358548396837114031241253322116798795051666796393717626371520000 0 17569828538866455505338991799249074778916153949998588353753045037643616897415533123592479614765175104249733309276754533921630754837952719359536788382049530210647385717086539329167052538180369412076404452566079663334403779932042220822140195443325442394541115119386069092219996646275541349123695227598770048768 0 -44308098078592216078469727274346903273259038183223542472421381200581401583952046881245307914702115198305007971275431535228794272724794509118371833357876778504310147178403025241662549497874820555905875539060235147200826867373820708503799515606115883068886478917160847267543575940841991597291323838856393216 0 109961432578804717429855398767875714346454141329747238285702028988194349101489610171791761056642864640515305907833617925762635579330373585061739475453633465289955460024146671323631503120364660159606561908444129942968167985335846141679192554892208463431348672739879281332051278066529112708897221156490192 0 -268532594900064027979819905384398290267423087233894217241480309628749256453545071431178591678892920956158433382102688045826756499688782501211774154056283341712003266904111122076084335987726420046255012157933040659612879248202972316436613587522721985545707167196445514500510894717054020738686939930112 0 645222656459259817160008427291553303021896943525598448941458217951607599260692128434240594850925570002308606568034518390729468777677128786404553226247122831603855850936529844080002887774316898070220162706685090816538462571858895729637269304600220835126671556536831663035122672152630517226080850176 0 -1525224600667210840894090526154538776998427112111599134466379910291767893217670741378308449124246523842976706366548563580903554831835001597120092984405852296258085728727675904977172234676947108647702494103575961747461283939582137451338960476396369683978973210051703394967282064850618786764364288 0 3546697385231353134945178108366647351519528640361430475151897419884530275442205188041778066613229936410923281618959020178170778815201872410445572780849597253396273183751469405247613479497769045050496314504736969029648978111286222083320056838141468286676473921334778717997629210466859570542720 0 -8112114289509724477524573990060681886716979575631975794967873546489929509136637711359619188857718788355889192145296463946767940143459435705411658123574279664815182981150274632503520778410218404438393329168993277204486077841238409058618236372557026624906984022711097827332878093697481025024 0 18248026381906084423060707785382358381835750943332828740204261033657791297807713142222756464632219705148234581052512957004978095824334094039606125056670311621538525779534425181658854929593875052080823869155921937941869544079567736963039798257537542701605699527992853834500015216046484224 0 -40366473149269656155926764095163680901578292413082819683015481310493754433055254872778038764925998494004523216744944017659266460259215833820402399252587602312566817533059148325374828996415051100860606509656987245521919042081828411010598218250481216407307184460852548841209444325696000 0 87800851407762676074387727398595121684348658262246440844308474872415588361382426765211522366884415069469638061693968865967434018930194968859752807262761312304273349285915081377657637452384205300967676005108243745638813700745477974038993671357083392823304379583664044689778666723648 0 -187757963181306792461099379613321014583518415405001160215881559499823701160923537822829662035101038074101287422374328879636966321327586269421924950390104062660651065937322906608076485054933840626237138624390173574816735305621754015660412818407696083764422372305832415067084811776 0 394700009046690966602866465068012445793458834020784459503270129771824469731075343720127643995848439227633764671446288746390616903654329374415730581743753705396550032770367556022684141278051722928144758574825181910349746354376209392223378603650749302869962487876037206458694912 0 -815551002449037209613614296123713873074636985637668005804456255662008746662802684909365041840280976868994115600864803141643220275956863701318074024354038985666979508033478228666318263361433776499806229455152705330485284229518398972570438235707854977348078389994223017585152 0 1656132362345973239931678023929794274149337552914555816474917742796017603735351311182171630153621400972829977510037127149981182581087919344049578209326390777655155523250213368511051851686742411310238595345509196089792495997943641988840755397288557481891515917764200625536 0 -3304777129414953316746628114979921246462423353207106081756379600534108863814405587662173652980760330902074069434946275586717424271202582275977147703396059989741321054371838558527583823324426165312761380921947168185387647595501215277368271032978349872529206148014437888 0 6479393219605643822095751793087707605992379766888712184823356545443710335646916711306020009638348887643057358582380273884854526495869391815181410871229612283276445068949455125868200328491275457946071591409887007120729689986191284006555981236780485494681118888892160 0 -12479920335288237020004833509508663571143816601312990768257647325479854244265378926445020254091937810377227917170491359997282970312734920115785113931249383674953437312169770849786787508209953286136139328319042412353167506169984609237875533271789262319745987899904 0 23610941826291633820050192005099340390228065378725199098750175552264343630199177243432967979620720238917204016043838396083754295758991168657652929025881723009625515129748436689827732596424590076979788040989323511383009734275037451703278938993373560903348616544 0 -43870834936262529849623933081778788918743590594876220026405196952010474529992751236524919490423052735027614123470196754087223425127224091857701764612093753630544231748768688121883837605952023799079336658588060312784442515575309660046831966900481672468856320 0 80045136325918282331230250587702029164054083133403321882781295703185709419206030903198898684298733651876486405032273406867970033780353641257346659518399659218303918303095989635933200394798608678704604410530143471396468402800783841706696139502953269963008 0 -143391716768522079705706247778238842503979008237359125836303690406142889967050719851701581508946743764086357631553025019274023283991041808818112939101052795135062155042228396032207079334598024678286683285900854394412504228088936618636583152732372630016 0 252159319964401158295552021295820177769880447429364887815567202178432539978865638448189121099681478314589480291538224013423235030591000152878246011886436341997579679835561523082655892386509128482565845228535929629448441561201536930144030933432344192 0 -435228880836603354776086952860302505793795188811346424789477548893024055255999500295392663210669762364540133353067476848520045558725016874714835382268792118011831215962783460534092114735580071117213546968296923685118390123843417078487110718162432 0 737190980751906196779524333563739679722309709761217766515794795986785385446110676403652230265029830982623885903605240227595535072932786741896392988770408426319258687761003003296617869813961355962393803033333322133472268683001806113795393323776 0 -1225145855557853104707273574651912098481465278927417042850592151302958093440151076549880392566430417078347819957062345971314200368123496103367810653731730904264433381995327002764545015176795247782767801359197216252676751551187976182673965568 0 1997398725362387152421616747887931992910350665820020910237119286383754948517115956630192521966039641277521814313271062593042989490538708575647752907947395192122310672238753686572138771488664908725094888777953644102796957833641369771495360 0 -3193981721567729931485665327016500733307082722918805834517043689062599446906929533685716178184672084084170821426890932185005946164010424584728670098651228958816559400956348260685558127607351795497271790146576409425947234806195806457344 0 5008526192895373851357759776872454260114315184952369638235444733656951731937188471332305392266589443883695508668103255567828648341035803987827017346994219990321559807625214422483977335940176839977706830081830659429419965006996477184 0 -7700414553196740515124563072365603082502539245667538692662392664972055222664770067338515147934947536530604180336347698309006107958782367152043065217296686805622613496092263833958430749891832170145900406828517726938166989269977600 0 11605374307423214975700841740726782293634527508402386286616143938186908366321542352633135106460396820435417065057315928157491240551710613692250480477861438475144841893485333335116137266176998001719223257295765371609615448759168 0 -17141811734743429679638940068918133399410081655279947036113106126986659166131954017111160026261397490423210755520938393104492325868652795987724786544052754770820564333900446226317764829661512702935320920125942845652911740416 0 24809368399498494824165797193561721533194139068377133542295357056724677320258163832964763698747139506160174451720272929246055773411032232992762752836303933442853815765386280519188817997198716816402444852179953231248273152 0 -35175651490974419231817067667961020458370876554249049795682781148583589363994940824697230921906991821706047443139294221674070603451556216682098114789208763087810214488676653888936188250655378273842797835622502502257152 0 48847134667969537027329232933487838359180671973192236647795506141507269069423736498657212019297062536235757892243646609516898420276527020302720257876358741267769301751002381252245788134884574447546344457489506210936 0 -66421160596890805660111599911931118989604804035467725455395676292454086595569511763986514007643797077872604169906606871943280065692264783617303183893713813357366765444291385563359326505738728022852201912729734656 0 88418042782960459195517794282349192001135139612808469775014099567693580375051942729098972036816364516483147504286874038581726111652969240700860349178352120540405127537226420705063094603710923976451852909127936 0 -115195529416218514143608823540391358136118849377277835580320284674876231171048413324421953691676725009776432492212315087814975487152551735424332019473783708846524805053239064050035332629401238154011284597248 0 146852136492947709622340625769064860177928824119045484161328639951985558478257457871795255487495808358458168164872129812717773176315103231084673361917323019314204632584009951340121080363238275108111255680 0 -183130501648196127522045744797867819023082726813966255791614105112204791109972450444232322543183707040333841502126514773712879607702104261590679472566963345674397026408729736213876348414132001433409024 0 223336017918372016649968932654872892262470548700668814794051991119864889642498469280746284453727574445650392128122202998219522194984151801642582506770495336633395753316456644282928642705093454664448 0 -266288404009210037308065204877386657220275429479874200650572919424974446712660359124715037957441009096747291773761411642223616551476902708162534301007027060350440853038874124385355848948525347328 0 310323384797712992566157424426561054281532837771448999829862906840615047780302410100445874363106889770221395838307398891566679713081450276346744396824431165227616199836722493880267361279624768 0 -353357462775840259580063768158265820297894732527422410412863102516970758279329424445530295524003958243527836159474282032436434930110302205546529822403312410767414450145924349199946787642880 0 393020719659038714184621999361733643925873785972448161372818308863228061353619741665414341165181951453298434082180283967160085469187269898916044312356206819480122069913162266749407376640 0 -426851507213402420888280319611871654791229037295168616453853044330400752216081838430010846071848919027623633618353269754612063410045273687567407955704200213935973697364184834000304640 0 452534569604428888091763314552872125421485605271308168729442565579644840476255431451094115138282599045439013004558627441262446393599880423106197688194886203643623502662663228288384 0 -468153134247169735955007444684306814499024556072476282425628889107090622301910830982063004739577034730844043716389277879392403565287633501750456994468543702768195655402562168320 0 472418572512180603900138428098629455774554584201921853913398518839829576274101801545480269679956346945303372518501043187604617051590240580609076392232097006908615142584606464 0 -464840613324987712777440850461171787218950943620943782613710285089184100056809550636264776172063036513086243181114579159175249365303986204678915098504695058912745277391360 0 445807816588382365971919340893772842029066225858575145011713996937044689520558291707301563242093956495871451645514140255577037821366541926320313554957028864295897623712 0 -416561411271422740290076741357672133855900613947489187364675611991223346376691986091930021169298511222566064860727522002999078364625866760079280371228324863955398144 0 379063277738382392607614282930540770177968528367171472606900630983016386821509280077035227962960818661104115777670858127733609011928029716868310500221193492693248 0 -335777151541012821386734547251100474615434051649892209497715037022280693411043355843986234247498462972320467147682308524180561393972131084072823603302437472768 0 289397025412978576440355572361981633811967381777020846193776603084452056760087087026575346244710512552177205011543566523942214479758198024811215632658341504 0 -242564901726481800783667929958096261138224387129324817302726753304471298799974270486255478663287203803753899251214515263554486084185819582384293147489792 0 197619779036732462433504361852289857137775037006474223318275522312757472056057124538673440131279289683815540806927735354171857940500866394496057240320 0 -156411394257625421710475112992923258127199301205161872819183344298445756643307168525728295803219984198053973038980939328636559236223055382750204416 0 120198073686418556371138341665833093786064224293454293109744340005537027150092028936474069937917711229309555366335010825409516648811188689055936 0 -89631606543625388418920708583170912567874432908722152595259311100704930148978788983769987893116477159984930285900844279550237614395165457920 0 64817113963540627394362357844488538310434409845782797324591036785835359456317876977144181070918375707684208546826934974341629873603398912 0 -45425442906583704631561569027818786181081036556787436726524909860261655735007373434309024173916871423838706563554329180902409459669504 0 30831203755066245474228833936082528052564300642973788251201585386413146804754236847647079365170402983517024354839494084041585263488 0 -20251068910399726158740480093969072952938325030763641328572586847931910434718392609984674818278839577993128294876770070430156288 0 12862873114978476811730982196990560876784039254339633491020963416460656265935816857284408205472987871776105939795503517890304 0 -7894188796432455146321308828403163535826532024761080424629581770021887114191246446406314266406343562527294416422706831872 0 4677159973520091198497824439508320659602655164071498536081806179477800655104601355132008270952100714585915170997950960 0 -2672788897543624507989674589189356029674582646457826081002740135053371828410129714888168701115343430615907738676736 0 1471742920500938035445567806836073034073494775160673211960813806136576026178740379576909574397277457774720092416 0 -780069653327907754281144003064228001810661902144514290896150772204739973214106448904863500511005872903784960 0 397546104667252182210300223525344241993320075957054309413847621987395048923393789364170522120173221469312 0 -194571370114203967321092676668647950038774720194573191089518590492080606878476116529390313568933000704 0 91338668078393331044856090577273774585438789795746226747213384191790314295042660501729091381023488 0 -41069536998897388277662844253152153552428662336505994917995114815130751008902981724572170572288 0 17661704177189341133783251340260270496719387743370003983894737367097873755079646303011185984 0 -7252684617982040575120817421250665705639496908427455374370179804465348584863032241372672 0 2838996299370440656421953466544071074551960334906209641447601507229083505218784154880 0 -1057328670846181034896460916346681893038724387397970226499337261293413566946925056 0 373884197826192032074262270526583792815561149179978929538519595686228665127296 0 -125245222420165723465505084830027484242573799679279153082122282913574192640 0 39645690643043669768047810546150896303488636344986541239409268875747072 0 -11825995671690889702062521541168204914521018190632802038867294462464 0 3313940142525084532934507330152735210852308558144984432603852768 0 -869385129085483189214408545504360088783037035265189840506368 0 212687154605132402425267318646886420884712210795578728704 0 -48305652663080249676380996393411961546703756521957888 0 10133545060267737809603375649184007400912522760832 0 -1951887143334567963926085877901821976395912704 0 342808721084552431759061810209578430556928 0 -54443890935945251321864241662982435328 0 7740733562222002851710448758327232 0 -973096702140745774826592542208 0 106471063340708883395882240 0 -9932399984112004053504 0 768049936920135552 0 -47261621249536 0 2169616128 0 -66048 0 1 flint2-2.8.4/fmpz_poly_factor/test/S7_flint000066400000000000000000000101171414523752600207000ustar00rootroot00000000000000129 6104549033356152351183622743336946156997116945571290671544232012635281247174656 0 -1979332218966262763404623423933399216372970816025375863206386201041334973549772800 0 114443186458102017092614835398864206088793349459276761475370522232714155835900559360 0 -2087575691209236858435792217764374972813046075089780265983260917463325994284979585024 0 16716250476390977580950080425030616631242279069796556057134933814043328606210711617536 0 -76431585652014306418790100466495642786362055976712829993797418545032395556080029007872 0 227510504918546958442694560500124432204989575703102547969432519195254842814782056169472 0 -475264198475130011327972808006230361670490710409645801780428907455183907133730565652480 0 731321656041136502813325320880423834610439782762544652956373864706564730461129103376384 0 -857834471403601877816627441633642526746656338035964968069692458744011458425706833248256 0 787265909309000387335881380051652216976719850221121335543831090127895235509330034819072 0 -577162615893024502436193627071730991090649826233885934937087410682120934716479274745856 0 343886600266789637669174020274889859253852583037587384336984884212255119842232795922432 0 -168968896094951871220592251783876197627153489712136554975555379398006690399860463501312 0 69328286222792763936166428809935435016283234718829593678305416286739172459771252965376 0 -24012423936843422983664419034967658392253041339773750729314743871217266876690278121472 0 7087400216301248406935638938338547806673540992218610748799100702008031297565435625472 0 -1797440944170890279779100736006313773174949684282278977921510597025191732858423607296 0 394541795322651690997364472125919980119682030107254869225384173116410204836228759552 0 -75436261236812253890297534029787599571028589753948108400750537219252833234098061312 0 12634818624198462792789349509296643132469708514509611868902735369579621920802865152 0 -1863073542983433867881229581621476255629304337666733964550453617405955291639447552 0 242933099192153062379085564296090175169797231896499051247394875826047104038469632 0 -28121980260113441327370606480010293698530108057910207055174671125351645283614720 0 2900167276164727484488369575698467570641163199184050244519498579487876477616128 0 -267278245823376341039030848791200840505989009415084332736718941531253629779968 0 22072993483001442717951150630572556710933713008058963890548257702815956205568 0 -1637468781492256799257058926891534772153906496815043605613589865518818394112 0 109353447465990461154275059499930652350787933570216664853116299417183322112 0 -6586584781044762754432396591638754183394424832456820491052336315709259776 0 358404476657045798221185207665972092789370888127462103083799647054987264 0 -17643821163437882868803982766421967698853581671011330793428596771782656 0 786771463486737904901334422970970984278509597478185633401174342238208 0 -31811688238714823368149191179217477823106022727607833886872387452928 0 1167269095437034737064958364676023058927895636364215434384647389184 0 -38894363335290611786893550060260484541460160774028092162111963136 0 1177448771461871651202200634331348411268343626505480719944384512 0 -32394336913641258849353443650851479472030483934129124892737536 0 810071835349198150995621571598474517830171152379101103259648 0 -18411255997011296404052320913540805709615470999464193294336 0 380230601699989780374785617619544696145646704081646911488 0 -7132301957881064719840880712188705556574633376329236480 0 121439217109863588265569520357373136629333683844677632 0 -1875291050929870162366823926401808580653122456649728 0 26235624898904259344524445640360306520117739520000 0 -332084478409994215399530611292635780117855993856 0 3796979926061784897224016596870837336599953408 0 -39139939226262688074304167944574068714373120 0 362907500511928056526647383772124600598528 0 -3018461171642321639305647827126375677952 0 22448962185771842540598609233462689792 0 -148724589043422506063449283488645120 0 873767439111740880059627877695488 0 -4528074772014246499433674964992 0 20565944068124191640272240640 0 -81230636490597428034535424 0 276356206556779286986752 0 -800188570767203368960 0 1941887196244590592 0 -3870496802398208 0 6162060360704 0 -7524792320 0 6609152 0 -3712 0 1 flint2-2.8.4/fmpz_poly_factor/test/S8_flint000066400000000000000000000414171414523752600207100ustar00rootroot00000000000000257 37937643407353470076417362765412050476044933297604020897127742480688223374404219338640783151041351490295256115063058992655555706556258581844711798666251065988498077623880961 0 -31626559298726139206345053615363966541095127732018678007622290632321735962475201254257814924852385620953658792734076664275231669992800677393367279264018566971142425214765711488 0 4636702378237208456898531935994970546116970182368013120303178235344426026951878516045878050825513615142742904030237432152758222061616886573795604171394635635654874560427837119680 0 -298274955775911109189775273247373058664911268150074181325403385247093525899287206756654789952461993822089720568577275608417884624589834440857010947883266506087884286099335259100032 0 10305084721502735487134730587299025083336283133524846761417310934418413823670464655238777191821231648700336129548151723122889772500602061946809747894131330171049102553184441498621152 0 -207620357230077085143329406722370438701221517241082577788532360108381386271697028987047947455566061845691519809553931478792141382269213290263887632137094802474059418361908713281329792 0 2586667333083681750438166141288249226878773837929169248999656552989603788105413852830345389493570311323191922072292605588498218929278514361156518517656992763278935230186160321893481024 0 -21474040782316045737167416801709791526650012940449585940941114750907643774997220146013699524265735355249181057469037169948019418930597661559965383164043900011749948837477047261149162880 0 126629612918310773067565950714503522926498409199381877275075645534433310741497341702716203617118574139272500504694730432373700393884582468962373449082821159905967131511106895757307547376 0 -556948759917979506555163708112338193873581738075096647402755235047680057522178387341412021677786496255842110556764170349411758720878936326086809396797117739543616402616979521089032268928 0 1895683643271069817794537465895049890004802189069196864230167074814259061153827080973145628450529833149258965495407227393924345465413113769671445723413098314094705224772703647740651460032 0 -5136652101501383187384240009868821421985519283080128693078034266049039295457207952763936925075262175427734731277404180937535183313936049960635143682830019706275419967115104453364852002688 0 11329902266737145728349699639195161422956319744320921934848514002187109833858525937478902357487427566678853506503728714430937389360768618040381618997926033185240021110291137611396531478944 0 -20710616182000300155344692297039614209625251817454474637666078143868937983502427748495297328311332956491265347961277183938003330814418793504909762958744314667178435345118424615497810454144 0 31841497642360046303204239153443046246799714328715224158315872168775763977183922092636406757969865986482919019074434535519128951853823260338475989908738488202960626907758889497817232796480 0 -41687544165590395986812922938283384751420668745418464263315740957541075761916596165990536114664557630617785068898857412707580344923986873742891741510206136939805708347831482977966562052480 0 46969310331468887164996943214589287948042378151413642281332846402577507971011021635606006096484331805849457889024905584984302718109249888912785699996429547371709483991187387685060369564024 0 -45959265853929074038027248709787148078444150116740682872952538764785840140048739100006722350818782245432461504503046182845379023078822864546622149060197427374192167337954039470429656398976 0 39367314442508334743795589479547774957275183804982428835934223122045374793102930317977328585159960204055133794075743799981044666320692261627253055426071393525450562153220829112816813878464 0 -29726521003591654414152847669269962971513462354741404582178028873764388698164529060765457524269154955474352366022113577861656385614320198164873412892920915400438743446054715378264736466816 0 19911275876382761801548648593927808701909667473481055493733309698339369495142198575686125450759471458515600004138490526771566596151416200910365553931551112274451032419131176738328218495584 0 -11896410646045560348612665204350253384908141070132982799226941806717041632313777642962349567109143462147151066985656146062082991784002120391252762858077533758544885345196975144735386347136 0 6371872480756235274202012945777746787232905418904365029760434950244584185053817555975368800070966289598392950294801514696350097404257676688195180020348534566520406356896766744418484319808 0 -3073384350350152715571614476053363814077253541809960235807435197144478480404462517060454850890854535477505229744627530494962558141789617104794962549959217498066467322389651054285517451648 0 1340447894515052528750997616673468332378916400578801559284634507482836770667739315027894440614954728976072215218788461428999420302757617057883158402964233047913793089005886711708628674768 0 -530632970158577285330742740763752113024037386626656012783815194399669523931584178598009440650277186708417688682087141493020946649565241293908565744615326128885539044452079587093510060160 0 191311184563230271648224727147275423242018482144407058277399174901050825145381310831868589174995371364581868337627372999887103435076010331646091373809336876145976626412601853919806473664 0 -63016995062011425515058974415391725332662752460090082448460828310399803445787668937070042461805792900821876038048947052943238321160936712916302031337440914185020465522743734946032776064 0 19019888243947511990549337801831240782872374896900932598196341083529466580522761920264396934924934304874741151528938571219730683848484163602126476801120485247076205077219509805143793952 0 -5274203455538006152384721517043317598164920184756221007961916827242137249485253036831638230469015067817229578719111345043017631003403191791332287685590513412061638344895789094778880640 0 1347051002485511975801399867066540030154676012540021907353637776450477996021872274756460369505213541534508083779221471436414965695689722721035843362279967880108251364216576974423078720 0 -317608034249255795909532125084187731635939713901904943847293538336241524891951387618773240688537652736306241160568146274724725541128519386905627743417144829371579973736546275094445440 0 69280513451599636971086053118009474347933374861971785547884167694685807286374952569097600184446518104732344229057919314894429637661389044574214780993156666709924270116178900728942620 0 -14009128420778864937573481645856661169196546915725644843635118083723940800621180165373455307847659390057903384634156596570011963794534706664002652224626992040501247131360681652173440 0 2630884317781665098930539695155330841725409517868768639581441786675063994530135000992863359273263443891929855769786998885186609208895112976730218000495986373191567814786738787524544 0 -459663693083002300447669005495511528671514581739472777501723759991691268084782929938939810444717445377357807922424102502106545563932887705169332704188356785868753614326954203498880 0 74840220016132879575207769013454418246107035804100585362477896854011641988072490774946995538573085087568118127160930322128745545234878579710694191721412216523995987653051022670688 0 -11372349876100298563757839129327805277412116329044325076299641259012587033030118618532709670047078065973504863623728074459371266474950783989946123411013592751348911010444692855936 0 1615133307776275323165101340282700306899762715232455094511144272179642487118314532414674252184679864956055520290113020403251501641708272773341345945691138892653688362860147395392 0 -214681273070152746192482492472555584188312069762196826772001142882716030824168810558582167456848459050293935566763301099914231736983647924396933606053704739536191221972031777664 0 26739724393236095743044115298288305167432635944061987777057668550783192831026207221266951562197897809665457197105882212413914365139625638017193829426194856983591827162947564016 0 -3124735492141748416815015599196319452878592589708107283542551002970849677175077661124179533812460826089785798903638821026515400349820818061166795368269887862770196822666262144 0 342964583180261573021900351626993731774879568943012769069353842997059825039273701863215841562170214842252147460914349934100090219802375004686538863712887459033582178986777792 0 -35393430055684305475433844141865745664087708085155619438095219031151600730365945239808417880722990046705431286989648995162409038108188432852192757517170429060682610364536192 0 3437672643540495550829236467504824455397091210831354639477494576812576997333559370910438012327516016601270474994679319496401857247697278149297980108232610392092864271423264 0 -314543791041810042841129389512385729982270594066206462226875700836744833754147961185285968384312180433241361162181401714646434669221237622791111364237332389944491476007040 0 27136595455255911045995347480276520821334418749282641939186910286486822339154039176775568209973362762605360861296275014301635548851417008332208533728695015975079808352320 0 -2209267085965918097158067380438735750423316489580391622870930181184790130460673374084585536533199607165295873968670190994084277919399718858276612749400214535711532275584 0 169863478878669983486696931661198899936997183135118027231344093375081924301949783851665054972573486424548255975306354589944832833873574073018449078103540206020136901704 0 -12343307503297055029418173358359102004015165685153656495314051694997964349755402171343855546999176446381514661592924208214056141908399692055295582744297133595116650112 0 848291664676413092670493820281357197556081185447259457800708323444723266028036504443286919951442886589586163699301509426265669158657466546675806438994216432574641088 0 -55172907978580632973515374894764824699549416732422161263769397702858376667635061823556240130007494586078644908454286144659979871668491598003948766384082985195681152 0 3398144938620650960612866578075317523122413557107096371190855024813713572886714551101280939754506671223283150735353953538532138616395943846904491251450385106153696 0 -198310551452656271236569645629129277405612605578888901912748667942127140758122544409267644102007282157361423307228129237397014890654084056310004762138047996448896 0 10971731258971862431765832910164970877738463022765350900350529082879355485130959309904497051926137405220938880530791652374339670833443471195363756402834616058688 0 -575775353244941155326727489625393538559070825193371918487455620776615362156760812647781833488176571301340505959540013526052771379826959618072351612038657886080 0 28674044512259217853434816676318622617415363955486055720608707409117632551846106754294246035852925187030533716400147228610634580938237399213404469387486065232 0 -1355748185067411286204590295270251642792417795326514611560184121478159959092493455439821883368838787155580906813378371460714876753380020001916801752002923136 0 60884512650839591753021390073201423191408347412794803419141927897754821797412426967535395782740409594675405788646831668291462253465525576494955225074516160 0 -2598027074002928662420672498463740154691496526005132044631106155920153116624712940442546874187309662030346057031663278623008740710689222066869725057855872 0 105377780866679860844614588893406460932347484384983269656016909434206439609525852974104647631499572586814055333673908463029840971927794698104498390217376 0 -4064162155587533371862196057539620507119656756589552870450871210440238164048048490326247142283051068898664329477883471319505851720704645388409488800896 0 149089332800510013029550686643757453392096638942997400788675456887407450949501351299864643277152304341670381993923013137484741749436540786934085875776 0 -5203575187407881940288483563736029007578261908514559067830661212458119438063902186103656976112050714870274699777963335202804601905008807726176609152 0 172843249760049916832040991330024101147650845306000164022602597539055338308455157884333816856788864554240789694650946805749516594438020483593636166 0 -5465169350608844442732600062016412584473907530570259677490152988933425554848566341276032589389771472896918364624836891355363438244175983415898496 0 164532082513736408332193751674131885667887344861157857031229562639185879881898132066953788067249688379426544298806610684307420541984141443434048 0 -4717137410008947384775413441085310120845129069551932136964046434692735875243981376461447859777402828433893886010113836800520419833340625455744 0 128813915251695518195280987640690657564011007328829062816877551881850452091506929747270509270261261005392950199093463244702457064342473662624 0 -3350957968991343823161747724034900361411823604968272309676828779993086593537931110555274971243581190580400893104467359750561296148748763008 0 83052573288939371468406962613751033277362690529881673916877612854277676189232672996113317018795372118584915839763364555782662118128914112 0 -1961378758705054456306789983565110197496973246743286295813817495872989086502456228297430986727861832816905083053830401583072538185881728 0 44139849767325233911797718749886162121573210017515283387331304850252735729950240437668208236816765245855847622286545586172080500527184 0 -946647670752506609200636698889030370184807117930046165376038668374211275004651603537255778199688030307511507525130669326476952745344 0 19348686739435264848068020419409662325360037680152903741104950745634114175492511717921823619306818927889794564894315714107644834112 0 -376901570162773962362282384587271943643151451373184398698275279574962733849867970460534940967648823669507527248283239448028462720 0 6997060271311743329741794694524395238731447836052193565105814619493935761902209512561433064535868741555241273726937885161946848 0 -123794799140715453348253170064909381798442600998089430847634600400198627660720029035133745454584619571189167172740565771215744 0 2087209525834182898412178771369281629537650404204460706425013297225657883457980826757543261465771591518750435845557738791360 0 -33533118737341634336502783272188491553516958188878085516075774294913503261055425984124289237267018514385146606995496299648 0 513313722823656444386579542726886133894675365688926479076319374206699407220588439358034059929180702937452277032959603272 0 -7485808639205370174402010403904613571188381587556931387181769509829941762097750616002663983810825400829251257082533248 0 103986307315080898031375146044862485945554744960140609951813719031593912232012849398603199132389445104904141326630464 0 -1375682648914287641016555630573928810784613602626726503320303931176586020801431473360263796539268661474295107892864 0 17329103550676949687803225840698475219953404630325956504267613136912949895779675579319045176667639955202514302240 0 -207801290985533447677730205203994592761612755600177849762917986524905548999426435088583816488658606224153351040 0 2371484214728574731806817414133491056555908673587161115697435136390233656361080673587507837051989978648156864 0 -25749215494822002398160208002965281103125251107329115652982543783623651858738060453070111118895926509401216 0 265911512952206583884461468723258911861517778931554630618425992897804737431226548228052068655989928304624 0 -2610851697757434757292572131796531197632313401505936271086730626683756348670521627220469913286814452096 0 24362723243584569915669680173756910915638258634064423418177644044106232622282342837945009207337314624 0 -215962236324277469253817899138171439201786631761336586739452880861808583695109231204605978778024576 0 1817732770833899811716784078323449565748777452422318659249311703050627116550413034228024549472608 0 -14519620920833267314784011186580404880669592541490797252529333012944716888702239204739859326848 0 110003345511050686169398016761011164510037590784974546489753661206254206768560761239354342848 0 -789973115332297383487707373128777587391749744200324438713468141263464697238032743244961920 0 5373798106952583980981993287057426974867139790564038216718667440998130641569368714041884 0 -34601449481727759299397034153277693298488549324597026112112261854229742660404447245184 0 210719519987885427138563568095437730554337225500305347430721320505832226144112602432 0 -1212652220885394813613632106452156793876071332931460978223556745595218315071977600 0 6588390918784443701024273066424290239639397030599925005421600735198190966667040 0 -33758917337389842491754878977082782377423438028799313690871676956788096199040 0 162959018672651436526504936159862530996089129343981089561722092716836895680 0 -740149939610300883336974837522349747525055404808648999032798941120097920 0 3158887805005378686181503053207922413266859075017713990972522764955344 0 -12649956526241962232343897539858134042884100071995686241166975960960 0 47455882151365588488015658226903204159358185579777029563587923008 0 -166484540378327720165138188813392736366554415870040501474311296 0 545128288865835557611010271396485912593895994254023071359072 0 -1662389681363754124636339082902267875858020740600909553024 0 4710221908168587915853052393726677317570918048968344256 0 -12367153796044204864607316918341407393381572054913664 0 30000161658742664835444620018838712741042055098232 0 -67010597932036662454268140736542153615796408192 0 137300950817058312839767021577105899573571904 0 -256933653197904116398213084979746336648320 0 436922040631464585818874466504250689440 0 -671247038755892710197451649618662784 0 925262484104149116404565299862464 0 -1134959500808148856738668900992 0 1226575440219515619416802544 0 -1153558512624646269539200 0 929399648285028606016 0 -628421278544281728 0 346713205398240 0 -149847472512 0 47563456 0 -9856 0 1 flint2-2.8.4/fmpz_poly_factor/test/S9_flint000066400000000000000000002132751414523752600207140ustar00rootroot00000000000000513 3728681520081714254905987749728384015649226897052652603209571610245555331596197574853057776938335202644193393371333581096297269090054012356460722762656616794569217442212931000696423173164925644619176683773459858313415058954521780836332928926163731361331417165539343215960274281003661343738935761349956385042603212261786410195882237833083509124037586597563783487962886854248759296 0 -1029555615424694867009534265213846854643610246030151809057231593542616269384677053253173989740744573032289694638186627239593298006358074925980852883521050435671964228094536612529128354999601213592724604560175462951018343982955859604706581835444178529291770026784229910272299531480276853214501105770816674101643468748013893977862552769143301269069637531260048373730991895178043719680 0 124281538196934213333732671190901974254081209666169022110730105273501809624136170192488105456141435793493434941983733373753822808975121886080458555911192463184819530195195507797199780488870457760122795274837687698636609683135790723461511473541192203859550077985006553929256313527858077385475669013371016459966003076412671721743662403840702827630817787873938320675179210269308313665536 0 -8762326425874243813729457579447769402825963585302671478681575621887087100835805721272388968599728668945400228892854749485874801784843028264281311392313295855550295729293891215143336701424515407042666593960531867087414327477708182775036524652727576495290752476652544143732195813684144385390776103759890352502748021680935217218109045846061683722837640971116740848615876126199876398612480 0 407238610413326547221373544574890343776484483430283384539424015079649208548961283343317379472698239226711324030018841881841205701526394417784122375848989241348115373824311265699219926345832056972271418567001028380118505313483357529273492785334008124225718918082461347041153415574321536363328480323957236069572803471620291581153503055705242416230227286129529665201829146593717064587804672 0 -13373190034322398743582606514505935125882518779447017974288115018201807739502729099334297565117239256210954373184205013206811697602334391198313528684570450136808993706103946167958845409104566321623854144135643162341935380418631301621241565263672776353699913189981541666563859840608605238995348524371288538056160942989389445745853365378152087068949827443203066134451213112825682371291381760 0 325154115625466916239049598225105333526343710799431487265349421144178866380369859204021187154866467352891693088616481583480752945928151980758185888019497470779454323312235038097082171653060352840034983902593477389574690273480971120355713025980593979141137283127979259451009971424849904412436407996811050510945931256493930746139038979688623270674447936064903214370703304225417588424155594752 0 -6058059391812079476291938937962646179801267443225130490561666746710449404868167966603117430707794931578872809749761905514721354535397204145583930389622789948402152988585308371310102543572792418264306465111091813264425249106339621920878141906320700756357590609333958695047350629533471852959186172024099424788470511625441611390938229660983803642183122971789933492091109860395048439860166656000 0 88818116526241672455728384979933532892477927522751936182279828380092743710368696357665878345202144612893262100285487568124832431842969888673014614524779779260398812871967577394123566722275020423521336058804183014326852251827594048585533321969253889918310279527246568980671887629658759520982798008361473196169319327707113126502495203294861569189467253001742582127910693987208239088319854542848 0 -1046712377809933088138660227947119675056372214220131835240146861323664201611081803985228111305858131548294875202666183089221474200349911411833718626977361626544810579672508305931393475630523633118386087078933100392579866708915635361286332291867790035169274407763909892780535043532953216242054742159398042424679467164199484084680179688907907896167849394831066390241599452531850082205657202688000 0 10090465868442572469164449729608287559009887496288477039043379887267946898402176587408345755331534166722463439440316903396652708971587987430707439677250191756864640510514905981057695600643185489492461804874663015300649928728604244116415876946117382448631041955182802047389022329458127564352437006179219934047174600457718610883229463909154099384589409365639016779251754272992475557698070053388288 0 -80752283806902246516093318791356611360785039739953545922541258845897353474086764168842130275615960253988389997242780153166180962332366723120813767368911458033815431123649464598714019144636265714072709740390805271040902612455393142774816902258098302543180231017979438729933449712315517076055934862889967853913590266597823436562469379913431997722992888329476007373555955898650113736973699786997760 0 543320179624432444515850145135390391694923295036982151802659149735218436356812728027027890372202834279823075565807905534948988793538447269345264064592271611255823266684203771059223217071759720030327592677669580415764003052199438558483864122320304184142299064858516098339784340715771720696847954933187651506487924313691852503788428662450684056158782040627717447848461799722688884885931692767838208 0 -3107505449110180649622193711612192475887272545491000197303108585597797460707518370956465505628272935064053851803533061248084167724045320156546500211584653008292518734802682273400711293215201500505798501236195515106075519895657031464725780749180695309233442369611650754320154007225180441607291629250436387288732427091655214270539770921398627727765552859823672814558753020054930735327350773587640320 0 15256825425362019269133717699624008895169966830202039455021644831336402364736219688814952312550451720001454754837776140393534335026678823104291771244150415740311078853069975779689366126157525560090624570517566099035456764238933826468806528488462187837517191755703613185705576591131392372587665949396245267979981993107052109803579106237302200969648258912170054535263835586326719568422622434739355648 0 -64863502875305709056834230550137643561325438648961987808126905957375633272825056134045829654040357909096408327741120392614400415053199054687797382681353931486219749315748887458389756032725617219971878290935453531909709510063693721220837612086870275110182181136955767296833954656736774399361324378664488304169374176807623087732172216680976723961574939065022952178542578776765417689901763641118556160 0 240674605513072723068109468714807995435751921995256928182365856775489954891810950158476735305095903689792521284752101117877886587019730031760754539704366440879509034634408140372247623483242852023727921757150419351670101824045813910440547617689501805131031173880667296630194613256970502360693853183846935145635387779713905799891708841823522317191002569923715568307960442987164781204963221656743968768 0 -784950112939433853114378468797910153067348346841788648300676151667123196813286209389546766816799853650809244041626257351175902183389643049930418171636638705740629617276511240201127974314351310000516766703208518146187958892563664351994089811367953038028083160755407108575662090381446640811891980323238676655437447648908503392831880275593079354507232393861237721141403094083296428271280190123178721280 0 2264885281255018525604017180330743666042671090741275836527339764023541010844231572844206259098934583327923783203662805513052236043634083999558657708038159592266468916363461649437505223907634437463250644392616855467065894555298125435756981507656982185659781452621006952568341183265038120249056095656192516588530538154198023269988934846113882624873023168152418817761054374893206644721947190987071684608 0 -5815806051821825719789659775413609655961439863462004534144066901337774911701590253801861146980963791580216418039078096967525601951152180612318615535042298251624995783123855612212902515424290479553374440306516877735306685508193369061902729736631139912609849450047906949665229775099463955954249968347561393093221270545637158658057044020253952969209911115188752630085352630379780686806191196726519398400 0 13362423191867649156088277503776954896763687625412102962001232135352556415820753096654708124527742257975828324299745778808446746780249444299616283188941261716284191280871816956384634500946912436489217783351323824289256698806240566570889626849740510603305875717648451905151306674006362174840714994700231544395408231088114876564048727517152324810384623518351728934612362082096879587940258229585411309568 0 -27607843147191781490816259478572749172279994261959479864451936018643092198465589230733765016546323009637600592085523796331891102572650319850865891422409212505921568389660684670623044206611072560509160134006994629164328024402711179354448786981165722205900302190857530903045327206487901777225337900360814312136432297663839602912154809112611318488769228463145622399769437980493033952422803847155632046080 0 51527641807730336405996088544516911730011538247651562395124054762823086996855084901134170996256451028385299986159558429104706164898302354714435612771058492244579133350290773713904632278904155536777618898427078940525213041446298148523557019076909079747168003064086256956019344070938822205986698228615825838852301437690784469487244145257963491922284366281505992628081819353185373521114611578045137420288 0 -87245417831043496051872431342568402523921307691873496118595848736502939382999810178684801372776092566504676667591395305462620627538836818402083940457357303002196776376777361606936091965156216602544959515935458679772481798259769741494096414406888951296913710519181584088992507253977199792451335055322027046854402108298993025689687410891937986780224747182168959646160973659445667287009412543170918481920 0 134534642972940387784301589331640165868444768696530609250637811041339996598954609112467615803817245701658571833648474783013963826261902825167370973021831432871600030307917990353943347271306517177343648554328280333059030461307805382972331905441256392699613519685004661374396934515430630313623586931016800415700045612717314980285182380093685775041028150677636655899691082545240018445231392323937551515648 0 -189619585491805681405069294602841091578865156658429249299145102041300227993220977517985109093984716519266165029724648903945584498167976468110109801216588665444857802329534753049460451313748285971633933632287933975944021106880004835727729289308357035321176457737787852987893420443457085706506830568090104889545259296652268503206557012513216171494273215794127587346148600634293557261864897325044816936960 0 245100331634577759722376306382194554984660986906833394328578969003588474890968438179976377554593092246364311072074575052135272930935861153850531790889209108263685153562837346744309329583844529112109683681803445575653292589293540533492353800759771696315252501677555054589687446467076874721021702321931722128003632119011707696942583191702601680798759566630512948014383482040486116506524799853477303943168 0 -291451679364278320953647994935769987832883705754848540911146699759992126216222823786624690230847264755505254897018632794625965037757072663808429377194187902989665367374132403564727870830239131751657932977795165959297414460072557828549967357969829204517467675395177555641180204400723595584161803489778965360251203292021546280929982061364254575380157833371601889862600733820192379019277390025335903354880 0 319747514847061728264396930212231271816107420781158193911278079727058297671866547940572770698152404793128836986351362168712450771134832054930388068054377859047458480375987272716127624042894037488437690097600968861545380599734359994115009642133570916518713095844146437301770744949676308721114358610476324409936895943417713988765310349529156111312416869091024616875128758163025673186348695318075411529728 0 -324515842436672628468469321993014985572388366824446551280709055941596851142232017964519376114411885780075836030421852091825559104315649370490810066017545838416897544958712662369547858643817135988135616243529656050527582302554273170300420783921141148537374926300218709679632270657530718475869419136528806112113588397434328737191678115300355907275821352916129575896168299157618244612890335629253311201280 0 305453198922408884749389390763474883404670751678892471352181024161686764948968360466072151692438953657244532082041258934797359808207868108276257424179213837074327872151937889073159817429620959298186877377650853137601021354985228965500668764617280702902393218365171462054844549091161852955867162071144978888267348340452039613320066395232582285880240519376895129082715331646275000920284400189734742130688 0 -267272374554640592196783612480792127740431954744577296912255736494799027105756498396333106216825356614172309243901369008040892315072840088208891026202581656011767816308037597804074734692672106559887657048510444949651424197452116183578298309919940318914688553827467798405439717451912825880790743840674241898904138358013587187455438163823599948910998765736979172642482872946352593025279647714467569991680 0 217881048109168815739863877545752899757440168838841937187934529483095012520420973049139177063332491291948855765990104611027854818301015479406065837494419150961705383035347684311586362155412636040171569908169046612817299011749009672381437043568937650266091662280528488970020985185247991130327685928706386315241587987482338525146261296524508824764540188900118050885515261075925925734801056705496175607808 0 -165819861594826823089657432538248624824616240762840626085254172957458861868683612522810346712587659233112513940923665105963066121493462646335881334705985339557544636607116307533702689973306080607007073403212857398008624307681811001502153816933457278061636954055271869379294554960252330415703604478224671947497239542424041352543770529371290522171592756434600927955103447623366839069391177585353860055040 0 118044681052164765600717108587583568986613338240587954833858814418674581426686867330058340130926283323673180815466736583889465368727881807639008238956914833373638069737142490278825176517393174584229763024177023070250221312606908556086647335860622149925876062194349237749345373283426065491105865566590066815869321434603747258633542583786719010182429974868186351200772035020022597760071485650370107015168 0 -78748088130433746250090232339474935462897718273397985675815843238626920370977796136989648296830873792083801147127507522366048349450431294405434066971644420743077335639044887226920951033420612392200073799868681250086008731712301945762929225979236327159350391562879509836358562807617085375570860613597091377729494395463443325581905238384746248566642024048397604684651264629712243462367699794994250383360 0 49313089273520097116003723336308983072301913797358495319733295376376044900762576111546005500873256441842712589341109652054910284610568779218555934311588970506206719850095729794368515065706034215088033046867711030385883543867024177328723560182833749573056528171625270749549289996531535882933734151518280928445338492201733033829526812878801066200698096646211749197375010499924256932144591654002505023488 0 -29034575891304180188890840635135221198727165722162424370744604988387914884363371365075145840935361955175579691813904851251842880839449888670131973109107920558829769565970991129337946426392937212889361615973286624969930595129231322735714789986326976593545396810750133246382002138852445848616626983860992699151722925891405490430884105273011281724566771888857768095795415852975057429154964831846300385280 0 16097679420226475471351020111934105437004679773366180178359204886406145431948308029699138758562891896245121271869409714148918531416495429492451058278234177469745773067875992782460740077207720676773736363220093449714470081233113524460775655018971630684147451986629991371209865703714561072758998770059188760939402466592228665645356300228322261256631176695679382399948684156684900612444033199773264642048 0 -8416527464478499097218663094815198381302660408667004165334132104936707977330162010855941376507227168490657998632165820644752948295533903336272366555956693141046682053333767861032121765946820773005347624359398598421621021100642139529088227156240702171002556984209862140715671728541677057528182899684140536350707721227470020951324181804891751835989110326766636936469135702797577623310255708758637281280 0 4155454584476488514065146684021525061380562572803895809494611519286020338716420477913478929688851157391006736387043651910158844006148850110482501321313522850264398744393071874373600479795368110197487868692359648070243769948919700903410131262971045173030712878437204033459743032864480260106092792588579461190667526205104720394148008416692924213589972587829276790909356463585599360723692016991561842688 0 -1939917419062803869309432907298349674863433536549900549664636610012107083921537893913369809338030567574495693920115711267485198939381586665168834638931369577467490167353243214861440390199183145452321158973018490811192764401824579540966595841432645999243807713447983152342576339563133586592925289559295264226637069243343192816884623144026495423255379138529399257371284426803841280966668169242224885760 0 857356844873066896252302710532140461751288186568458926645110877131005038802973549762692120483556537798303839225721140479538676218711439899963875096881047276263826871216501390335297588396650549424906102171696198139575019965639502140813074102650768842327859370014755142986210879967274405833128183948961068953998412850543835976839339774920486742248510296864893688221553735441154636033801273960990507008 0 -359138249746982994680709020337590749680854149971029957467500669775392108691521168750663451137199313873845702173714750081090554526362892440091071192445928097132556453616115951575150976926034947770574690911017506618876028684883920000212609276169774934412880967767997062514556148738209717502098689354137759917667513044974287521592375966392896723023341802669939892856967618621514393654115696828575907840 0 142746885710123242292691463711051739490825395042164316162760970391800046736001557814700892511513573090507625484888675955995075052557324027927860300084821395234980876928784452855131317599732834147438811905372735574541322614761991708868188053742459907800810878260251193620672530102858205717043452234799503818121737154068534081478092627844824141165712980824077779122675494613059324494001257583998926848 0 -53893551836814840178223007728454256319847739803951257262366556386898133804666908845310965044342800929900169746767350869595807643578946262965190344676285612660454767794558938265866576325644301346904622969171064003141437517617207988282143812151058036978349425751608556975268559791588055433625322183830379925381672952053650551086938281486011139746582022739557701428180296323407490542485015614906695680 0 19346879225578624782652281323063750042813568698670263723003357212884161594468768641880176648165182336571445983360446179216438290949395078400508573445148314308740281879729218969012780863452450234016891251953234970076264902073224496121309239076784139816538941280203715563124053411245357284702209035666717676247025129733010872346548138512199140387056364003105521195903230588672900434550393206596435968 0 -6610094688841587359772234289556625831067789176571156544442926355158280072423266004626113981986882486041087706753706539171045507543055167758086560394407512175666840111540892471296180105508872890630923667986013405407766781385617166034604810189643508563486097577561396567590794930459462699063720858466025494013417385271116001976405632869839397186598554556967637168225342772615233897231494639654010880 0 2151428950875024554385647406032651524240921872164386598336055587762963897329936251048827334504099665762534229536531947557258593155463389574881832734156256266700875219583841192594890901493274303873747769256969843848886988668833403596074061106734648073437453648637608512818604535525104180695928237448935470465016481669680855651760739432837419665749477251061908714949529072130972623430570905654263808 0 -667653661085311374923454400411649069568591083775394571807851158932831959298837649962640417959698183377549684507405921765896680958359114837447150276269615850513256106274241886790778069719782980464422919004307101119966348820933704743693101116864066683813356775564190245481744392823203057190508847987884865056929588161214841846440000808518089808408208412135789594041642573928841565070754732027412480 0 197717991058792130262708339404178845586258713238467163951530158161986835288830477992038439301666162799272631718683517794997218493372316900541788967516751962190880134383756825878262048973220584950291941844360104327236874358500385446798993517602564589022664380585496728399588542118707594356856839798001656481781875158081606009330681756939994288100985026477724174281837202102580119427252310016786432 0 -55919360902091682935542829286593878263338235957711660969552473839145676200954342582784146312191523562911353644073877740812677532965271429839956179661096740428175982441632377440859873305036421086781282068378450820519614347520797356017719065414071022485070112415169402660817028601119143497120007985404129855566136145550350623945228899489506212523395706984388786642516375641848343432531675059322880 0 15115934901638741131286258515177706475733319452661731125287541606311321153513316370176905850135066512357342685435066499452673042772974905002418679405401421595882670591445279459872148811504595629362199727310187088296509022141097783587530477393414154548430628638229976011925367771952283466475186952282580159113265041423819280059639990231878117558270163959907423352760666587100554903946421140979712 0 -3908288788517500742276070818448276041239220643442544934617844093451098140442739588536524571007576042059735700799281230255433573023068549929081474402429060013456201136268649142491284588536363759697132562366669196621821273114892187494787232154976691560129777220239187849186427284573662223468179704758960395887550009919899897995990693258293415130187627379349856726104490600334337072049127728087040 0 967222010267385808477259943852709010181029824511970514120426070901359975412565492178633999719445788451676881656862344818382981060634582831547208297712145142401729561651606093389133896786388918295206373395990884841532490952271903281984179766135112923525829764990449235861296095355151907407612691569923635467651129234118588252249651660953180991212622773456578594268144100319165613277900487786496 0 -229271690428641818097292201738179003960766873733913314003162173143583675575538537165747839405770001701800981619385445760695470712332918690701813558215078904017816164905484547776215667524424000690433966141018789541995837656089021216190360769854240284013344499363832323289283065147342668626247411906682714942367939966989263550537717800602373349768753089628952870695599915962823879673732053073920 0 52088845386249985577851567904438933894308264540685895355974026575772428309984975823610814843873584475178942983602710305612199090956495393200489909608646065276878116290768118281654497786170892940010681717099184545963756936888596569719909734202849425526076101156327507127212036726248498331581926762289400657025309659288675103229726653251107351525264608840704417888995528559516244571121764007936 0 -11349675200624898366750587087585852940824269338302185276520013419144959536223110020695466978488389304149394658573077435536634148056783058403631433799615001333632571209495501877017344705297053736275169900093946078307625732308418467615132666039067524429043674601105314783552827758992254729318369040007920755430049848272220947144170837031776821675980254600530253589043695435437354047999731302400 0 2373179338220517255716486058451030491750789198968490231843407564344433555044995115101513001866993169225118280331474535588343777460803676085527789759052921375172515846814146807631538316463308488425113230392959383320816601551243907648317743193807549581676545347386330074241119815928639649015821174107164338866338745423762159057726558990035319274958083283131103623923282129262298094412507381760 0 -476475210974181180407731931825662798936673490385950272015695352011573096961106110651689752358813209000424844902520810905857413258483927748496870037478420616432980902179319996180648033024405326914605715732565669041571836269672123191000099446286523312648491957162218308436670717086689904628810106392466083073374826546155462010734353118599615700485740275167172180482144671824115802103590420480 0 91908902638158154926727404296996609310614123121810333290985910763588727820974916894304448596692110917759619800544132329785221224974961983763953890547894136414292409532629658093410479247950632138892728215003857455146116574937769252668794442675302633108828678227115278993425660491844760006323810602213459298586932165519647558773510019712329953763795281728215089354569604830600516366436925440 0 -17041915567784089909362238778680301828847043954135705663954236842095335737259149624767640343187852783113863331862522471501916971054470112125327605167676150954608853106622118092449521397076262208077386408145024587085670537619769844392434029255834393301842473194985035487180505650236781785848206624679722055031144769455464613823404679911181798888968118012587683697012431492737352265315123200 0 3039138019761124468345895201540498893339807693397380418290356976779283273350054296906241605641206751538423646089741104601417682853573115094608271670480587582105051791141381464270381311768138578150608847512830434429924510532788152563756003504679091351205171316635171711594280166254569483384965618614105601928741353449334189415866655087731535133604051683963623489689782327148389341583114240 0 -521522730817247097004909071126491899031121167271452568128627024844479332904154928183417590536193396610274575117203758115284579772196787445107236022496643071468495103762503438515174781746970028762488156195767029974846864563623472123408743130061720890225482363756110424563040945581308004444770624273610045796854511124387167132087324408749006745797652743547252284853685929451707796606156800 0 86158643696531267944819177996425374229962065964260679066001897759741934517772723982465112676677422870041010445926529441656383378039924718965413779684902318230126295293087385232087368734118301716197725225999947841800049285732336011758442916146603930975321530191097606827345586635527617401902605291124841485935114026927807493778796293685613473525247976610628058786011200824692848690462720 0 -13709826950288750867951603211716136682481713407810976842302202818131627145655790134767375304140367081293537873558488570414804868649314328691409023337335400037451854964055838010053390402910842041726494742629371528392503477254952666157947844440222279459100941010017563153086947306101807305101119512547346012798073103694154797721640790567859499726098132616177796305865796531621610913792000 0 2102182289752486865828550632574756596168824154265562566721929306080590016576330389662184287531306489249421527129178338440101975238353743438946963073496492577356969687070588495218044973141392700054591074099419415558421512658336089790159126012523943598417923751027355310573965022727790475882186757323957736634281681795286059391718624036184873332024983994059264523072816354191366810501120 0 -310745749465542277864222623832552111898122770027034396795385625989756007554374679042766709708595724990904630024698566647587920734362014237323005411398024792505994997382994208736197147533532302144606244166455833137634572898262829867958909926342946770050387220603913199787256945163622006876170818461640289303512467255955976531132692599659693533251706246357370066471743414691077575147520 0 44301787686412587265902935612393107068363059723694342903366191802941459774763088154609686804946186990304768180824868311693432615990403703272136827916409251882560626471019752095242910745782265876252448866528526311650440338909772077933331826468859424766722684104420899064500635931131163233147267423795173300250704439329900571122859765188824774627887213132990854102304449095005739417600 0 -6093927487943825293033492328468131583918788304342829872512005039543522335960174030680494607732152641916481575871373717512597240628132989708858010662491145025685324278050989667871589684989538640828819406987421495302768635958952620939286113778858799082208539971275472195763809343931310062406244873974672138619234094594592022102400424765021700180962164719555652527609267418367944294400 0 809107510714639306741614737575923600818298354465124663599221660716164477435062018125929659636166643141011408904891866062931041392771537606434878780253562092642925634963126436209007941237874986406749294066042606723080919653767699200744294244706002448579576145016574902257298909302082544517410125843831945618644207820222781852137498543505182444228343089177165823583646105346370437120 0 -103732653610408270994900591823288192473386774268038555173216535251769058123004550905841265891074045309064871261928972291492163903246448226576505859747586949782117597160940358008844799920718569119905341006796676942919130332681020665175798570795950682905297705089254061470594076451843065164374581938448886192465271555014574009085548125471044778429404267151458903315762842288867246080 0 12846567544669294040001598247069431411603063975719904531414665187469198660165037306728876788179449089352398525460839142733341510058038112177350654890762046029030519927216229083668594870682484697672089965250145989277539072972096403445597357982274799990138696927564569755913989794149788957371858829385786908489686454693701137936645716121468543871768350076032117313298088516198072320 0 -1537368677235194884280281056978394695934995220225926699281813154164074110889113125861284653951620314847980798126912155167741392377090399244927071509872466901451110256516114806345725339058514024303397396964648244833213795761759383620891200431745923359591738332265020799948000953786576158143605041528327501025368485971127506905296758024011753526019732677521812028990381939176243200 0 177844442064229438651845261020931015115109110740261724515920183575105070120841312541020135227317073950588358271701405976946820312075494238321141305209898805655542915003628274952919615553303044917301813074814376096348532157448039408214102902533750078822029178796015534919681179212690606507945799469635853516466627645283406846129814987637614533331762475359937908260618128892887040 0 -19893959801951421768022477462114999372131315215525961067229312302891024024563592329907282012454911749057617214971452503399356839380376771580090817788396278943898463746877837914206283239672921377027993545107946439625241986129748698380731995541501975406212439642815642932322834904881570037462143607128051133827660774789213982654727517748563285001623563509728492948923830029516800 0 2152601499002660728106287065250847562473814287170189748231210693081974824550700920073747083313025909622874987429259089496285243064157639433024600041334632932665528217363629087837827434385232270643188252173574052308094159015637493251307468883556493220266933320072638147208838280951036272306366540634015102990890714848266564462397892826025297806939698348695600052457579992842240 0 -225375103834931317037944060105583584206798528036896944608458858207537464019446029047546821654718768193995082141897974463860871984663842707406101177682633971296330103182495792494998106848565572745295325080082673343424934717078062509844205694973568954444036883314272791173106844693702173272095963341177022954867699374078458341900573534293635537714093516083546679634613501952000 0 22839278564887788807331481685152464798841312825707469511672032922117471038629231649405020093578256887967200396671244154582919482576782138012162977382579770017390809320413726895904201754038393600889073428728389386472251558511150352846865405376129570727360049948150471546335652228135566436602654459694927876176503565094057957412407867704668768903967941195798758475774358978560 0 -2240903552427874485892370200313116445947855470023453682256073049113417792856744364043041319845182846811880184874615403407946803032978501467309507262527814856848099024068040551861202841687288389612418013215071581076199028570763671608799668179385942828005230531692310734292593787919962969635731612924103065122891814153527608496938144111441387856417029487320416519671062200320 0 212938700537873636663756092984271440927897009378522232816291619710055339389390999591349940848248358990477247767517791928437630252218208070149628251753086861316143910956433105971052032490177311526687557048894978683717534549859809151748981413475231369617596953416284989125508977297691457241711775463997667252260917629123299537847490655268771285923769352124882974187748065280 0 -19601948338603675833983848891908605410653002567867342889050989268843256098662813963101494379426231242361423445841341218731198124593149271416559913064646782281474344979091238987233058745120717184432897010899251255350679453371101038539750193667888536953128862024164956247188369126578898646657070857031055711677704138429793005809829380889160645767721820696307155183285043200 0 1748541812743136868110089135940944128378670341419756584971095716144402059635985616980676999312351843593635533774713532927909677216827726957711348638990409984825361677570695984520799331776112057987539500328820186943756593549750719849936806308348951033076633626949670475112511140550817951289711431131039637910560007526376854228138952816423503947515624439737324227400826880 0 -151182103448704384542612393287692522039579666864149720986250556466952237235704338469837732049532871550572754241932987320600090082599280490985179356808924211874446598885309602343593824521297898240330796054480526882696103623514808754609972310669964965776594880747575606101273855305671133720734518820743484280078351558123335925961775551790713707137104043277838721304494080 0 12673144513022130204820668767175146904508879812160851880902180142688114315652780981118127838951388663143830194227793579609402884402577273161800858763760409296030866684305876157513892021527872702769221275161493955058593999140783168928708564738623203893025688245997216014422049576695905579870308369565724682422608306727122003319000422747604162730195444577326395188838400 0 -1030236262503441001396502544758548480080910390984177897834308488182364514669620373086300740366429438124455198343536231841472946594631429787412142619713192932095984272584262930202184942876626219853219573512849467037217349924399380561292596540038745820723734562234881411024900139248668795056157978777258530612149017853896405094897891815751312525868017764991147966464000 0 81238774306885081290048522439529926781911446198023237404439729443414132104430764588927859144278826172622432977390339290037032158145146535530699617682971850731431845539030160869455374737708400481645995006288434988978768245860399368475678552732016538562722364676047594786127204401850968172778169396823927408933963650001669434682047388480749983924820365667211830886400 0 -6215364005256909149152919982589484009469527157619150681723480562568069923871216923659180057050511747452575075172135335711776180686178791959505499912512036973635746475777979136661718432840274779068630858461358019103570494624322845313381845288709905730249426943891706540428631083856128384375468738116528333264254675932215620812787614677040729423411071071076273356800 0 461472776008781766785708595851774811004251815813472489999222758807025482204626826274115316428632357492873164026142583866946201215101405303011229716145340346172109696207944776127933538575993489468673327850813230695740602852153123884381599397519807559944242417876805113583996020160359795161624696210917658947731558549298991591893178034136183380590707645288147845120 0 -33258195836741205544016489807041811949211698849527608712348478750637112781122023877654756211963082238684090135923302394209282801273258231815950348987686840218711362843645580299637435917827904835090314087744221381208904772417762558585455059668466121998640799896825126697869011088601443881863237856787157420182102279142611027757166450823966236045337347168927744000 0 2327117804895162447342876218628863430230628063624832105666250746055502873180253525006229191892051743293049656369796822380474406784718208760750528648154811704814775489087750619287800777134060286859378834143120178896935885501703160426286142743134321218686896799390995196415402440777686367670115160921344773298348882525649259196522230226053073292961122799090401280 0 -158123508384315075261467350825682498918569683424113482252522354066001125137223066774686284254047863412182905910238875727425722650130902374778370098031155654611424020524446151105623562384222074472907524724721471214918563292138507480444103077137761897151500720332004478371119993774190399028704610656343681065926688571532809373292073085959908783213666196227358720 0 10435700409340922397034600548633036566396400454187932292163399992450609841649772752923878146132742235145863235546581051779962637601581366693363954917087654226672505748345941312990957667445811011450560071036537464995789035444482939590334354183247342893560641755690478075443818744710439667488754269706105995178561745420574790727220156173109908964015246441185280 0 -669083033001919048328126349512458924904505403426837682706056694694480487528714881848732653136872500677874415920850863033621049385745958285571741002249742658707453525113043965720753839310434517912011987159838643684767686736211051772280634631477729428005312606152242550739061612426171502832318086486745925598073720433686731139072293315683019298620378710016000 0 41682656414302790432275769020722848548581918293654612921081833275087433246112285365120452428999253845993877183357183999872368510918703042718936334099439777859989207792382048296075232273616540723677710512136752436021146489459537037742865114357186230637987838904938644578300186707323741618719353547025436057836527881266121461512260988195759512838178330378240 0 -2523649463582574171512877683545933116565743233416286322973596943181327447331199536163396227806892920942429031767695594937160091253651149221695980551759522597040473498748780121728076717194414823426514940673310785479567575545548362361904157623038354861398562714650980600184474357337118471025359283634905228118351140484043674741523382426722273626636869959680 0 148518287550874887588590454129613962288696784184349728439478530314227794557569179726405235851720192595459211132821621562496269798084822384064191089904628790301623534561578878511516749301558354625092751463434074940303133027443547741852820537567412915394565818285886951657068994324594180943559210209627591505126801324828661520483152260793932392608028426240 0 -8497375734202382924163338805247341434302372185597911139564462701399267942908513525866793760432460662071709502440221358555667485274631537125744295767970102760799971815771231066719334748400631907267648821501983558613332103687008446217382517583842546032277882485556439073877498409739612091425777561977980361624595802945456958185939127935399018892152012800 0 472735508644586108143079725106043699115880420170556323970661922422365386912185421155732410129472373561796689188373597134479333283487563830666276537435484132196236704963257691365735450813723479254133622433765074595194332850549795978364505094156206567717235790617802594756468584359098216809378463826358633804202640880126164908067024397595106972847308800 0 -25577171993681913088441738084210979929968856359646178184105154097735327226959339674095295770197340817096770723916397911180957561797881803851070241376941774841009374919726582268147979937536541426871836779116108300388259751725986709221965507158747231720701013011202733220411655868624524154634129673024719740413389128217688819875952428095634674181734400 0 1346040150192668117194728779145715088505470964792455277053530056314429368192689695658359939362957814337066894345080157462001481710076969034233703218918061074210270646076132024679981514283525440669367271346145859396034995668330024782334722173557992451366807510507616246711216844838586681760647421162578157243318004013780958422036952058106945938128896 0 -68913285386584511035734128257130194405274520056649138833240267981703734057818144003980433728355574948446486109394159745960086807932478943917014809208866289129191740571277932547533893583976877049768260528363316458057216502172269722697746177310629004021439886824673932664942483543838097465289276724611567071541700135116525919100980414586632515092480 0 3432840450549596649397737857402919007898287406492281598121732439158763365823792682902072673047504552852241299547174928625760996181794546818629692655434015489808497044342660753125123596197573233332070141371980432137589225776369958320553343929223328194459812305803555022967314070697590976823546530350340049213690571256980744510207621155453755457536 0 -166408053803683020433689381249258576130920727396849102942890149513681372186648580344012382045875157617766810114375548357178585550874613200954078948263558105989094585856755939890508093398822569069702777619819793067410381111974123838436179411605665253046867195037667164694109508330361084424782671217902619686559614184005714093094241562606226636800 0 7851046778916807872843051148880632045299772277048247029664630688562376410254327956753081680839299296713342259352406209081223626231372039042678029766970898343805590705887615318569297979012604807049162148447896365680860394560588141469148658484204940638577988655712613724831404025958712754791155607959506625278988160334757329379001662153657679872 0 -360556960420052116694783345323306796228519108928978157487898540400041563005441131449162376269482577890896399088940151838580664671086950206662538226328714904383288571463165586449469187074421175820364752869621830950941378278114340868906136917626312512290336975394601123914466018619506251796823498017159708053983004889408414310430409169735516160 0 16120261580383402285559845360139673542153012326902727482878339331608276839356545738376393195568739678357919338614102061924520602184967865794440883637431737024936691999226096677000705813074649186096810768726866616308139924041067307951032603186539126442615493718883748987346571447155926398006218218136369058493451615293796734355970507881316352 0 -701744773597652963694757411015904542863799500479726635831806447881845261939553384664748374193623232107595497192461535809050459579727450333657456902750091040876198001949961665055026016881564230743174780071747908552150912489448997324954871826755467138124198918536201264110722392677109158076385738877209022170379489475495285126130285443809280 0 29747500432020131691487231362442164565859296033112749251817212525179717304115147538628663204219501986608567194504588096163689802885975678478269550381069236368320009357981609430296646850671187069921456134869389798076502162032931873515214211514042303014274614694196240008106052747831972265376328447325040984473625181710855845154176995688448 0 -1228116478098027175395780305810003959846314517480520890081168080327581815386613815013615231231373143820760956959323301722833449897333405967226658558207661276382916905850815917582355811868611664390722852100845657143663112760515883573723505724609575703852337771171402162619239721994473148090484003196305376111805679838471981350012112076800 0 49385375483124174549652882932665623718425714604500401697222860745454642509664011130253679354206896863246521120275427650360290620470658806947349709089681647986937844225244664553963269921484150164386553401138102345436453880200005891044911683826356153135665597449306549833743582106033370608319925928673222582053376139574338529549046775808 0 -1934537684181006421897086365162587020879114370825483395311338132523921875332396476332548092808802438247857146399718141635432131885859845863558549951265480861398846858842916683411175964044953921498761353617470945840060635663447222179476029272805554121751438456811449598863941794602152955708373181757089044110522137836967330720367247360 0 73828624066387790297719739399730575822729112025470767479008289711626369368616007045727424754527685052907940497202930969965504077461031190767424480779010228327950503256986619040654018430147796994189653751649476863606417144555885805982575513668916876608814686127116420526885047955162877458677880975591856252842115168604251334878691328 0 -2745290140307279591396397897827504449428416242287613400987345322455821811842877984922440115480535318668048387177003402732698952862458979333029719856181465284094088476097799536828596431591793595740739924814611735983910820783932154855517604416909799920327585465908965975844241919829381585359812612982658619836572222944988583658782720 0 99474836079779653007297882754028520067531837633820278598676501482300896304791852782048577223622500300892163264935078099071464475043594223737250382732437757822151820580813642461897305337719063836200091028978706079684364813735302386267926315322471751744141671632483294974143601153150812600052685315122218968806854274396930009202688 0 -3512722322291375568146313926774111806775581722583842774691785378638582367306630254945984151614362204055758422458109325079923993560784052941163786250717347059855855925512874662138969287400410402583229406165776410912127998879705487784664299462016448665588924170071737630744817232129377630037706402667091492810541035441950797332480 0 120898978272359848156571920214579463240269283091074593391332792733249533982955385202238046726169551869645989426927469705950725574684435360467252149110353281332773340613861455339377490872378111827894551591489013752761512494092155331010875465939218024468723252835658455612902367981648557414450629621857994248437766288293293457408 0 -4055933413933785698485227283759656324250837391979640052891426419756519781306114085353515320493155422733248955016264710231460992189693162000681665747610660066568241999838721366173897667208186844550024155871726891693998078895001721070087436486054300367528407139218655643058317734979690212445147163282732529572537663867248967680 0 132644148027762275385463318562886218294347090046105135961375571046142953203657647059774162043292376704148219135895635446644965528187280709721166571336654583019780096068965849765606316391946239427410260835526811540275873476366492576837443653892948788887402455633795640066206473867511956906056836018207937584910194107081555968 0 -4229146839418371926248510217384100982252063256495153321115453403799535681315756444573465580847545008386090573858273142101673914091247918923266268124599001334926869865015437750746650471572986943828555421507022804284868471291239748720755787901133604432748916326885859439551739227042602924703558068152054924644233275276001280 0 131468506746388523528597203251852048038087943189476893026272547376877662169976492967798698296708888190299822736072923730619105324178162703233361022726636427801630613907775986006540837320471159010300753560629939160831237335282047815103617997711061741521256694881880222767280604752214457355009708670472689944283266697658368 0 -3985020126146279772374768577292582654616751953717731371043884766235441593970651904489715413523084635696974746807102259936995880726913581819656156960105576354549803326356361917039364159556391304417225184688737489078639246938060504535318531876515871963220594211242623686184006630437324152369018995676883986748594748129280 0 117791323287572089986727981359958943558276559732553371720775120667175705913463252033012309542132178120030818739397645378885363609193968249309304931420047356460960889244200198164046670247645634392086831120089238966329830056732738389461103514702542787781442202609595462553900782798259967297215121882253982274587132428288 0 -3395493498847456104452775124427207614987752995341600300005404605836533793024522237951731956764646304837108493945574432152567027721344549842484818853347817594918144606588558081662232931169642282296739718896484183136072096559309502485954731576834025953754043623204065850510215654259711962953723478616286465847585669120 0 95462066195709562914271554580022518462799445077692381977451549538475802588620193990242247166084855065767914390507049416020710926876396366321872104749457901345450927300845808081409330851885095745422714602126204180558848258065076617643961232144756543085604068362371559395048318864186252302776012446547702713090572288 0 -2617744613100832951273086356366092193845564857078778577826383513756631970213472758238586415385404032486490439394106702081204296885059602419465619111786117658981856222933244866762845098358882540123065137414062601772196923205348035860431618690996194287756459425975688530381194850202725885632326237555475566936719360 0 70019843279321589631995057170736038951413255064541056914436134084539327876744491603443446489932432557176650354158298649697216086514177620170985532008860649451096427305411093911006453859051907263616014468791636391676071199415069822624715347813867461852627486252186454324470677327368394908281562831727782954795008 0 -1827006213685022292031228256076118171209642829571463227189607458110074837576331184059684381054716456917657888321088749108987314352445738183949975964041213713904607029469471494679599933748879242954027326870673570546347433659602514071271766647250100522751975769900908942068234035972305594319686798538650838630400 0 46506139372859026726028516960359622747389274646043244206886540386217823712741841793901514194432797379068809630770383933625657634377203479391414656712815259405210359082206636538075596836029500574972347888907177501586513119953778269301929882896367222747042386247446355987694905931117166864699963901821015031808 0 -1154933589156799341501620813313692204958559823015077278065275447418737602596568106079543155974835455692123687821797490495838403722198062329743427241690608447420161578782107763369162446440829753138095494529889968369853955053102311038073720052940763176682251899433512265447642070899884811403334570749911367680 0 27983628707423099622541297849705236431268848497148530221172253520174038016227424130491842189815586657702135647095359070739839801657509069552046970350683478319293785354701217185446395649126755245448489561139076141237556724888210809085971319952600795976563953250045610897162758944421118620255773150305845248 0 -661567157131882124218693439855791484429217742614036830772693151864531220875777109284298279290499058760614210120844739157790302823110932267151822614477974983300280858992409059728500640788494879794144831926241273865512107301662148605906814145222158984265357803676645425374412661970749689352522377524674560 0 15261179371991234803316216766482981318767204921130459848156486996103148513250874635901704054751839414980005685983633010086752566356125688321233723073231304713551225014228542655877445839577154949937375144823832974067818466176804526184441246066235355119690733503376428294380166474134981956602120705671168 0 -343531565644207303067393415005049346605300298211490641101387232832172349677226196250065891120649197973735776554885956906341830713808684698720646359513009252554247808252696784161009723073044242849141051053725553090482456591358199318351532537745114798439104705501573248677831608749483259893281917501440 0 7546203518704999098391052356393433229348528057993112625418558325262102639425972474354135353676386636260738743657237883122328165396848320460574701676660620283200741686352690614370537843385942789117729736667803258875728476607936474279027500457436285987896895945994441838173623504718586153458999492608 0 -161767547544390217210732087013383347880895259365613607385584921676336501092752388386568481203090184001384891500088545118109266251677704235539442535337109666804548337615738939602685667567001524345731449133253568486520214997144908901357471525244120403353886773774253434801433811345519680500489256960 0 3384323064250206795748243516137333771994795349503228412889861886797075706327488048565544807848975227920053903455705620616090401233831866323519523808233931982991463846298356725175159259218083138510579866585401659585634917153090636880117529852546714754126233660004204004118407092598504637887152128 0 -69101114029685595731337080315791596898845009591769532344181102640102466802400951895018556115598089650803655902024370154317341625973539703295440954453503307659938237754954149973048399641280084247334762601056664232913447610143580303159738160908655868401868134659769067041400032363395840611450880 0 1377035719363898458764688089385207463758773061973156702645232578067804891395528270786471243049621475714589218469766913332189929321509500980161185851092343189526201291453966139692712859413572289514928455135721643085844219598672696967898712687513206624572837778830337351728467455112498242387968 0 -26783367711351050670628117513743887397897221981393016546834633104200469441509097618708304624361238399724687083279425109775867532412173884401436932940020938438416731345824590036334111495074985723571514743591576023376733083944378122309537082566132341408282645716123449457898969622524828057600 0 508459875192940573255061545461987573217932687486517647846129296125471348761315580966629334192050553107336149449765538893335713561585400426604696898489223489477131154061188295671806114480606914852284169281602257729868778400545104499433827732335371165485200956788183400299925033702809141248 0 -9421720585489970018885467436781813960029443115444893156545899494781281874654436893911566869233803211691164602497963712279379292853823677520616903112594888715507872574382313719576913396815035487292520960697318021255038221693629271722167434272205047267978594238839917168125146399988776960 0 170410007433595949333229503540011109891311664158540473660981040787805808619844142897672848720640846549260601182068852831762991328438282317385463790838305642775848270761463521887492235275676171044703190574045570122413834281234991666309211567833152161772470172666678271332443233208762368 0 -3008565165083294744971270029681879767331779641763639455217980961526680508151639401403836260706164020976003205876967304700993352059789208110804842083582204028938205849965304365918815703511607860175785386459747654286620944673533607415107204102837093621828137310799877451674324115128320 0 51847773736863573169887120473785567896522669993436983799909722789291265226242663406417749968181400820922154983021213978318152252719357344155313501194040245634786327105408254439674878683985463915977993973615545713731997522631579354098262279236870273455706406862678000523058975080448 0 -872193556769194978443312870187280409750957653798343337409407020337878003434971145837201736834483842274821310934394965533491475788162810883713318716603597141595506234518819113692243240743590019135744151234620759297991519388547991634254842227475214095405634164746715789088029409280 0 14322281473817262488759490512126148649353454730087074967865455707214383492856572274338176435351289525574211664452056104649665173985307455965269871176133825122089740945978389571379315108899067934521461084306232446604016498595176866657243084901112495512971387104542459596602605568 0 -229578593798024992868971809710884937945782552335539676663903336099294584977880186675672495071549280752147003815807491028179458713249420122099489210328712425007278498501434767766927677264880363266471515852040974841498014698080698247737984483875452906047369954185383328486522880 0 3592299207094129434078275300784610258595426961145784653744206620966467060046475187289751612001661489349276353938253282840292874205371128931187075764118424886890219523359901471443808746915160219222493233632123621258974204925233608301874378261795574005808599026341694089986048 0 -54870179364116748174549409385851571283629363540149375701904438338282595248298034306803203871905004240164435590031875066589519943274133243222479729176502744451748505064759902490320821196888021394017909838364827407564445930298382088623558373960479326704441422020520003502080 0 818130592315996378878104668697592779878720985058271631791471319145933839116405575894027169202025999465252307464535040904285735305024052849808860488680296875797218264231377871459449978627905298960544726531101511548127949140194839437210797428477211269124298149427069059072 0 -11907747771167729622856637889984269984003220049597996587628875960608214935741130255455745597751191027741164595986377045709530739109665754398558941035957206213700340710253637115495866905527894078179083474486820873697553538261691842396198863629416415041668051723983257600 0 169182125633703043530908099706744036572149305402671329118366763874357109385803577965110184517299679947149728172323778627705809887956384152615599323903366521368943558882035758227578549529755212854303858776878790417781939881139467383597708584143676424928878047633866752 0 -2346351292245192214402733401119391347288666150429314212769513337756843146894315408016914099139682484819047789276184703604120460581046162704723462211237041073867133752057732477801475486964217488943050134514834360977896481071996557795754681416120649650851316750090240 0 31764342846350613487542608853314766700707327779296342240002915661116284065660150014881838381474200247546826848766358491647136222809673587717083991757415700766775564992396401064802627608428054936684165274788613623970167740079044542659555815469566006928356814094336 0 -419747662043902435314033186511994665440702808786494013932077698989059471890784167189318559589260660252032347914249518734974917492987868211669861252300803642451997859154211086369214533150567955444517022366639864396533362034251224569377725018608809019169361100800 0 5414149609548542589083682370471778327047299399163120308797903354095725104118238705610449184567030069467426247402520443730162279057082261999770434684811448500964096224708902533104883316226752664317934938485039752420650658970016383510766333892786337243281227776 0 -68164215692987671116306698762101650790882517506437333171216147379105777896558699125072790423317219126989974063859522005445850048255020987455687061259053174535048388562284199431989720370183813304489625610188989985119037051459009715756674456338702718835097600 0 837637644819194787091689874400771457686900709497743562021869770905011363966182539479378459241280103489837516487679334957405972590174318796914059503134936907675779460365660264586355497648339288088630934699866474155319196178976064723282991106477204596326400 0 -10046561973611130935744953217764202046762850867487033346825706865277262380118461837706975359157766371725162633664078427157593184034666699993962830839295274824783533934184750083770130695989517826856402083297856201131514718180727451931815037976560355246080 0 117605299486016335916815227778296136166795934997397515981043516873834906464691456794836560052119361217107134190244925197679923686876550453761798747355452689129471333819114841921566188578846501216577846170988663729848765922807169607844585459834672906240 0 -1343599015967319874488557667469790437671223987894882846810100657613595968818033783234607763467309191130421559091995641656516956999792602213381657278398465399380433426035275383533024384676366046940683640910555446117070039359083595496051023760326656000 0 14980614365467703466381314832352829690265453714466286114180450094867873199274242421981198153110638034170665819867993727562601326163417810385338018832980861726363994786840414063922936977855857175944523957284757404797514752677881809973055447304765440 0 -163000560913231041860793402203672350621413000630278061716684654058120971872883223369012022723593245107288235820511708638789463254515223863024690187168273662147273674502008906128741073197277209478168949915371020925071089205641645768740702173265920 0 1730728728593766855334886911035757816892716753433394207204500401957942672548993745024859314230054085412394401968911806704379871266608878764284950312887379893965353855165914856600967826306221615948084881979808969294423677563210564167707530362880 0 -17932000778884009689629052093226768264836092721010151787041750340566863819895581905433309762118746084617365902386050733931809559017763634379512292420334993974363923275412001754716343559924107986900992975274143022952462806644276287915425792000 0 181286821437997779750504893524543989672801966007932200246170417572329032454700946353248266293577133741196699285460129674168024134983373280521547648600747779199173082869431959981905864059326427679295565136696357807401008970355851462264750080 0 -1788207071922934746272588977362759808010113990835974481196503780903472629336334325205850272162841691036277644274802970376481869638796134872214980013110897230558621309528494594969897195066777630206888408621244976890406015735205272852889600 0 17209103274762464990762588512156068821908470503209668505593023040056915426241284840979183821835042916316670803028828816127177336328091008576815417448714095454436936440698016520990370999995882678970604775991925889277577038686177900625920 0 -161569987518549046436536444704891542955736263730540728615617544357123539743758222363734042613821265383185479288989070999115561434667038130705095339479562127968737755122376213091696080057578162406195060503109116112645194080717478297600 0 1479778355521652371702561714636479830881036953956709691255362971846689583123616705388878507497706787056617060185261090994031377420936799770456761647623613563555082697037338255280985257074831916726015161723268483925652279196332851200 0 -13220138473588711600741194329261249104074574817124723488470216970428815143416923693724114532547972324168883438149343757301307601275679520283818288884462448976675174736198567185381677459184181616560708610266666214987106672002990080 0 115198491524827819483900426295363579248151490657889908633173928791720241995725597957591560372179995944632571265929485402060720158745472348382948191666919538405002069844358850643837152001505464829795947025111320273708892186214400 0 -979028575001037200301454807857339860643083656599124700806573976275445412938424913132617493028175606988665585958451187620631895585745828001786480374685675291794799153598604763447222226365430240732389605426743661249177845760000 0 8114210158793116941309829266959930811713950934659591867793334925091227505578223547212220073168898845005485569736360561151982689034207987123721125958803234531274637718675886752283116804184755101032556517556923409541606932480 0 -65578594721637574835905216845258158327568270790288388125064833134009738899322799905317533926570272492856463842499044287039983874357764513108875923448703748254817178892848775040283157406638157294657029806305888201678520320 0 516777602801504260818355376357849332711512033115307276271961498444284380759304885676082922526391850690546003082285676233554335506500436482350082623559705090367663559742875360250504028521319571030142768711671641045729280 0 -3970358965992650126533781155818358998665318317937257165481745934410571506179706352041223171712387415588014917351355375254134175809146754102129898714831401498355641697402422008888162549806065269662291775233601621196800 0 29736999889612844849543636774802047852128749292190597012040025515611733774147338038988700510772428998030712937219429764049810941313942826278783544087067955514535245040794161055353001653470558624929069390010421084160 0 -217100344139470163782827893129087047441930598094567353711062459754299478444520027202656221195564417238295295440780748903724377862088799881431842244341944657663764532158105731666545971426287262070804107703091200000 0 1544800540883407597609023548633400527153109087304150600686538045931486933839373288678133413675481267670069904608004520568383517373786665969438960290474071419152397885482177605692246767875481966687530312469053440 0 -10712311820757706304025059903580479175734028199958169984218667961969336594435478176432040380942616452490786169137128641598883925486259593660364221589327565673680957682549823171531020084547001158196933951488000 0 72383731447213947787566148419930974890080864332233159646245885090665074538756308188472308034313989473875260256908726861960985715043764434593995743357076851969899898311494519540913648411697755311389162864640 0 -476531292797148199371224163057961103860321518064041312930954654966994441951447200093072658780313713558533020721702276238294783019721750964601000952061987865118703580460709388598745805263593226034772705280 0 3056172598939422969481816563339071857763484581457500864259942741977299735357190936530643289290349156821466438399656606681969592306332202149618978788083517267756675873521772338746320594094839590257950720 0 -19091546665128649950551269146384695384150803516262452446013372483429144815420864296653530858258034100556840970811566131971819348869691398128995775602191583055112493258691071423143348678618065456332800 0 116150028701951525577986883368124067950138427218711840882570474120661162051406720078288526770693716492931347623343431667104454336889852306245142576400041758877392328797073571677398654373170637701120 0 -688094360374880941477241964873529094386775306047083594427915071323124883990710717993481893751174355411886714282207508377140310488631319736742392326175979745136503702661878312976704221425560453120 0 3968805801096028335833548317855796121564111084236183152307281146231905163143481895849835579622227572687708211126895149061261981803866418916225109740350494119153137478394897514371725913174835200 0 -22283565433576186667037679002743422068232379482520525719867507412882350458992432767698450150726170760690609334090859584232806554956350357906424474110965923066122917224860905313860743646412800 0 121772519518178149175021480446916977034715189286585380617010308033699787550682381318334703307388844069844316647594145506856838322719092734944553715662472392375945454498340702058270183915520 0 -647556033278049207453059607513365120500221472749406764236835906758229360732145450633694128018616588283450849885263763644681180122459197760164624503818066574065525052555540826788619878400 0 3350343095687253532691576346749932463217448445441819810248710624738965599927939211941781994439117909589093172353540385262926455992547658252698546278337234868526696548948542137848299520 0 -16861729143369246765352246714529856933602269226185904697464681970963508496607943266244802494758858496027105994479277782638620945701383651669877781137250584959958832998489723502592000 0 82533321794108677938698127377444065533407196152525755107542173405015221113839513671992725439464529731311617676193057723867471835904883471631386260760681340427698430804367968829440 0 -392808378744053687029801864949422348179451624152114479185030686451591074432750218274758982960307588651681846216599902549676825854661365412308481499208905871154742987859039354880 0 1817449387332851573537495211568977327655786966761022122383848109364038532015622834054670686067051178790707980075707340254176012945392726835046497029083025501617101326033879040 0 -8172896761902506080083174326223936098463824292877836104783607468454570307191017349886257070323133756450221049556358835703717845484640408659753691815060351273345322110156800 0 35712441192875670553495939716489376143079482300348581648007197602545113594579271306428043753083274768932455801195634495882883810124482532802017444316987768978811712962560 0 -151595470785741575887846089684286037399420190344864023207514907844229388829015358437283745286114676682637265608973418864743321481340870459881261911073440298356462059520 0 624978073811974320633596017113661535940017385567879250982622481696996178454568638775716183466582925675210621476073483547822679705496834637069046379614193564732358656 0 -2501722066169737735304897907522944583694570419106243392806293622068452269071317723992106184921307447569096325488319374341416249393502702409160787311211386167623680 0 9720482472131033392963684560185284890244286650849610012159794051963490435432083308123953202935103370371510641642567750074485989802079647082959741031747048964096 0 -36650885475926568920876418260545881317162046434334051645976659651142875078437181162374987095605727773828375489379420194776764758968717129480677852931245998080 0 134059245765259623203052379977621160711729724382263793387272569576262927917871315939806911318041977490006254523977843771350633812195401958623069033497362432 0 -475539435103270795492272588409604635296794553157174891934182926954719455223171327384478262219347901364811808772020721482276702014477562750988941902479360 0 1635344704758308413167557184670919040909672762472691824220052667307063573006403390910192546176412092165725727309403628677312778047272692421506275213312 0 -5450219517349796579435046189942109178767809050745626845991018170007928190882911954040752660114358247889929279293860366806233805631355967576190484480 0 17597156109350977341158754820950361353793667268537395103551825725748762507406709388118693456973621801703441261826612933096065550241425944014225408 0 -55021097092314114197127413823368884033480115020396984879141295467338773495850820250366282788056401995431545427971642867243658298225094085836800 0 166533207749072126266452523959222202294158946760457407382165199542237036850933519944571091398769348031250031067948017076232145996979223134208 0 -487725534193356582340596083923381566884505138283542248595079211648400826901154491729022340923191302146405397252678156767437698698921902080 0 1381536853446485665055383572631821411476728956788678281463737819019939228316621451881111744249532752973677702369108549967114182514966528 0 -3783219959791928450602334980559630822711285641615544140875646274977023425705965582028071419577896916802591092428657589006150999736320 0 10010655574134694342738776032450738963210153303743576893527009153050044058868535456143601348043415111694160122085914262558713315328 0 -25582566088636445515408697411341568957447166253297090993798701204194063426144785901136138213343899317467244434663806614435266560 0 63106429717687333094655171635494015604871094657752497307858822937151163199507783585576925934303958011008189210681265302274048 0 -150177846361663777623396190512117459310444194510682884011031005085983047881338867028153375694534517457593842720056834785280 0 344573897069129443837909274434884675496006812451251965052863763452249866533184494846064334407666140405801691900645736448 0 -761781169317464353276420435681070929192373372187801022275696538292088469479016294807170090346382607971833838913454080 0 1621664692774875078967437838898409285447379102937113786546261956802229016837332538932082851312808318714657455996928 0 -3321771239043756371398928138692441558626985587045088147691677207833478679617635611129466284282802630714646855680 0 6542337192390653984556826767611685483500084063057937334922156031021136754770910292439458789117449220441243648 0 -12379630443453747313268416097753684164957596008460050108399738023121087845304193606221121014678173872291840 0 22486898099447192172088148758072269097205834989852757941088328074553425205220016732623937620714169827328 0 -39175152619713569551604594355258062650628297943329520920369497599360165189707130937839439465687285760 0 65393964210780186229146541129357560238121666771696380900787766088644576808165373002738391526146048 0 -104488597922691458220375095600252200598696766855582846088468720109425204573138438897200823009280 0 159636395770194539442076672168411111129346815624684425917945351033258650821257258452153008128 0 -232927111339286081942158278160437827429936932650552293100273821604401670735668782070497280 0 324181891156114098163698414697668260574378455462168767078201090552610049469299512311808 0 -429785129103021316987723624094639502065133563946986735932435185684484310441928949760 0 541968717448859641891189143317007226764520045280108292108598064820204426575740928 0 -649038925740110092821917772430859535331914678242634715101860356800684847267840 0 736876899975140341295662054619832763058713184881830880152040261663124881408 0 -791650320684426471361380584566121737811344681212931171861004002451783680 0 803148570090639439823176329014864733895924723338606500750713765756928 0 -767722463434285216615929190788980723147499696184511145525200814080 0 689729472144936106825941890297050059259410981091464486015991808 0 -580793698841177067821860039957805921962044295491205810094080 0 456980718615627500806356469569436091196059129892944478208 0 -334817248176386141271487196383068029084479874935029760 0 227540165675417449382488483794147401890260139900928 0 -142797267698422900710002080380284296950940958720 0 82333632544793055449144022263592469322006528 0 -43356863681838248635280341329780597063680 0 20708083061547105654062119651742056448 0 -8896590561644934561121167736832000 0 3403675261488753765471991758848 0 -1145307116885691251063521280 0 333663610109387563139072 0 -82443543341439713280 0 16797057117745152 0 -2709015920640 0 324238336 0 -25600 0 1 flint2-2.8.4/fmpz_poly_factor/test/T1_flint000066400000000000000000004632321414523752600207050ustar00rootroot00000000000000901 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 flint2-2.8.4/fmpz_poly_factor/test/T2_flint000066400000000000000000002253721414523752600207070ustar00rootroot00000000000000901 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 1flint2-2.8.4/fmpz_poly_factor/test/T3_flint000066400000000000000000030637201414523752600207100ustar00rootroot000000000000002402 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 flint2-2.8.4/fmpz_poly_factor/test/t-factor.c000066400000000000000000000166071414523752600211650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.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\n", name, fac->num); flint_printf("Time to factor %s: %ld ms\n\n", name, ms); fmpz_poly_factor_clear(fac); fclose(file); fmpz_poly_clear(f); } #endif int main(void) { int i, result; int tmul = 100; #ifdef _WIN32 tmul = 1; #endif FLINT_TEST_INIT(state); flint_printf("factor...."); fflush(stdout); #if TEST_HARD factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/P1_flint", "P1"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/P2_flint", "P2"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/P3_flint", "P3"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/P4_flint", "P4"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/P5_flint", "P5"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/P6_flint", "P6"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/P7_flint", "P7"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/P8_flint", "P8"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/M12_5_flint", "M12_5"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/M12_6_flint", "M12_6"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/T1_flint", "T1"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/T2_flint", "T2"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/T3_flint", "T3"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/H1_flint", "H1"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/S7_flint", "S7"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/S8_flint", "S8"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/C1_flint", "C1"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/S9_flint", "S9"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/S10_flint", "S10"); factor_poly("/home/wbhart/.julia/v0.5/Nemo/deps/flint2/fmpz_poly_factor/test/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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_factor/test/t-factor_cubic.c000066400000000000000000000100141414523752600223140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.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"); 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"); flint_abort(); } } if (!fmpz_poly_equal(h, f)) { flint_printf("FAIL\ncheck factorization matches\n"); flint_abort(); } if (omega < omega_lower_bound) { flint_printf("FAIL\ncheck omega\n"); flint_abort(); } fmpz_clear(c); fmpz_poly_clear(h); fmpz_poly_clear(t); } int main(void) { flint_bitcnt_t max_bits = 2000; slong i, tmul = 500; FLINT_TEST_INIT(state); flint_printf("factor_cubic...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_factor/test/t-factor_squarefree.c000066400000000000000000000051741414523752600234040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("squarefree...."); fflush(stdout); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_factor/test/t-factor_zassenhaus.c000066400000000000000000000076431414523752600234310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("zassenhaus...."); fflush(stdout); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_factor/test/t-zassenhaus_subset.c000066400000000000000000000111721414523752600234500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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]); } } int main(void) { fmpz_t f; slong i, j, k, r; slong * s, * s1, * s2; int res1, res2; flint_printf("zassenhaus_subset...."); fflush(stdout); 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"); flint_abort(); } k += (s[j] >= 0); } if (k != i) { flint_printf("FAIL\ncheck subset size\n"); 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); 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"); 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"); 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"); flint_abort(); } } flint_free(s2); flint_free(s1); flint_free(s); } fmpz_clear(f); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_factor/van_hoeij_check_if_solved.c000066400000000000000000000070461414523752600236150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include /* qsort */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "nmod_poly.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; } flint2-2.8.4/fmpz_poly_factor/zassenhaus_prune.c000066400000000000000000000060741414523752600220610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpz_poly_factor/zassenhaus_subset.c000066400000000000000000000037701414523752600222350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fmpz_poly_factorxx.h000066400000000000000000000111231414523752600170400ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_POLY_FACTORXX_H #define FMPZ_POLY_FACTORXX_H #include "fmpz_poly.h" #include "nmod_polyxx.h" namespace flint { class fmpz_poly_factorxx { private: fmpz_poly_factor_t inner; public: fmpz_poly_factorxx() {fmpz_poly_factor_init(inner);} explicit fmpz_poly_factorxx(slong alloc) {fmpz_poly_factor_init2(inner, alloc);} ~fmpz_poly_factorxx() {fmpz_poly_factor_clear(inner);} fmpz_poly_factorxx(const fmpz_poly_factorxx& o) { fmpz_poly_factor_init2(inner, o.size()); fmpz_poly_factor_set(inner, o.inner); } bool operator==(const fmpz_poly_factorxx& o) { if(o.content() != content() || o.size() != size()) return false; for(ulong i = 0;i < size();++i) if(p(i) != o.p(i) || exp(i) != o.exp(i)) return false; return true; } fmpz_poly_factorxx& operator=(const fmpz_poly_factorxx& o) { fmpz_poly_factor_set(inner, o.inner); return *this; } ulong size() const {return inner->num;} slong exp(slong i) const {return inner->exp[i];} slong& exp(slong i) {return inner->exp[i];} fmpz_polyxx_srcref p(slong i) const {return fmpz_polyxx_srcref::make(inner->p + i);} fmpz_polyxx_ref p(slong i) {return fmpz_polyxx_ref::make(inner->p + i);} fmpzxx_srcref content() const {return fmpzxx_srcref::make(& inner->c);} fmpzxx_ref content() {return fmpzxx_ref::make(& inner->c);} fmpz_poly_factor_t& _data() {return inner;} const fmpz_poly_factor_t& _data() const {return inner;} void realloc(slong a) {fmpz_poly_factor_realloc(inner, a);} void fit_length(slong a) {fmpz_poly_factor_fit_length(inner, a);} void print() const {fmpz_poly_factor_print(inner);} template void insert(const Fmpz_poly& p, slong e, typename mp::enable_if >::type* = 0) {fmpz_poly_factor_insert(_data(), p.evaluate()._poly(), e);} void concat(const fmpz_poly_factorxx& o) {fmpz_poly_factor_concat(_data(), o._data());} template void set_factor_squarefree(const Fmpz_poly& p, typename mp::enable_if >::type* = 0) {fmpz_poly_factor_squarefree(_data(), p.evaluate()._poly());} template void set_factor_zassenhaus_recombination( const fmpz_poly_factorxx& lifted_fac, const Fmpz_poly& F, const Fmpz& P, slong exp, typename mp::enable_if >::type* = 0, typename mp::enable_if >::type* = 0) { fmpz_poly_factor_zassenhaus_recombination(_data(), lifted_fac._data(), F.evaluate()._poly(), P.evaluate()._fmpz(), exp); } template void set_factor_zassenhaus(const Fmpz_poly& p, typename mp::enable_if >::type* = 0) {fmpz_poly_factor_zassenhaus(_data(), p.evaluate()._poly());} template void set_hensel_lift_once(const Fmpz_poly& f, const nmod_poly_factorxx& local_fac, slong N, typename mp::enable_if >::type* = 0) { fmpz_poly_hensel_lift_once(_data(), f.evaluate()._poly(), local_fac._data(), N); } }; template inline fmpz_poly_factorxx factor_squarefree(const Fmpz_poly& p, typename mp::enable_if >* = 0) { fmpz_poly_factorxx res; res.set_factor_squarefree(p); return res; } template inline fmpz_poly_factorxx factor_zassenhaus(const Fmpz_poly& p, typename mp::enable_if >* = 0) { fmpz_poly_factorxx res; res.set_factor_zassenhaus(p); return res; } template inline fmpz_poly_factorxx hensel_lift_once(const Fmpz_poly& f, const nmod_poly_factorxx& local_fac, slong N, typename mp::enable_if >* = 0) { fmpz_poly_factorxx res; res.set_hensel_lift_once(f, local_fac, N); return res; } inline void print(const fmpz_poly_factorxx& f) { f.print(); } } // flint #endif flint2-2.8.4/fmpz_poly_mat.h000066400000000000000000000215541414523752600157740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define FMPZ_POLY_MAT_INLINE static __inline__ #endif #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #ifdef __cplusplus extern "C" { #endif /* Types *********************************************************************/ 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]; 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 *********************************************************/ FLINT_DLL void fmpz_poly_mat_init(fmpz_poly_mat_t mat, slong rows, slong cols); FLINT_DLL void fmpz_poly_mat_init_set(fmpz_poly_mat_t mat, const fmpz_poly_mat_t src); FLINT_DLL 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++) fmpz_poly_swap(fmpz_poly_mat_entry(mat2, i, j), fmpz_poly_mat_entry(mat1, i, j)); } FLINT_DLL void fmpz_poly_mat_set(fmpz_poly_mat_t mat1, const fmpz_poly_mat_t mat2); FLINT_DLL void fmpz_poly_mat_clear(fmpz_poly_mat_t mat); /* Comparison ****************************************************************/ FLINT_DLL int fmpz_poly_mat_equal(const fmpz_poly_mat_t mat1, const fmpz_poly_mat_t mat2); FLINT_DLL int fmpz_poly_mat_is_zero(const fmpz_poly_mat_t mat); FLINT_DLL 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 *********************************************************/ FLINT_DLL void fmpz_poly_mat_zero(fmpz_poly_mat_t mat); FLINT_DLL void fmpz_poly_mat_one(fmpz_poly_mat_t mat); /* Random matrices ***********************************************************/ FLINT_DLL void fmpz_poly_mat_randtest(fmpz_poly_mat_t mat, flint_rand_t state, slong len, flint_bitcnt_t bits); FLINT_DLL void fmpz_poly_mat_randtest_unsigned(fmpz_poly_mat_t mat, flint_rand_t state, slong len, flint_bitcnt_t bits); FLINT_DLL 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 */ FLINT_DLL 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); FLINT_DLL void fmpz_poly_mat_window_clear(fmpz_poly_mat_t window); FLINT_DLL void fmpz_poly_mat_concat_horizontal(fmpz_poly_mat_t res, const fmpz_poly_mat_t mat1, const fmpz_poly_mat_t mat2); FLINT_DLL 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 **********************************************************/ FLINT_DLL void fmpz_poly_mat_print(const fmpz_poly_mat_t mat, const char * x); /* Norms *********************************************************************/ FLINT_DLL slong fmpz_poly_mat_max_bits(const fmpz_poly_mat_t A); FLINT_DLL slong fmpz_poly_mat_max_length(const fmpz_poly_mat_t A); /* Transpose *****************************************************************/ FLINT_DLL void fmpz_poly_mat_transpose(fmpz_poly_mat_t B, const fmpz_poly_mat_t A); /* Truncation ****************************************************************/ FLINT_DLL void fmpz_poly_mat_truncate(fmpz_poly_mat_t A, slong len); /* Scalar arithmetic *********************************************************/ FLINT_DLL void fmpz_poly_mat_scalar_mul_fmpz_poly(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, const fmpz_poly_t c); FLINT_DLL void fmpz_poly_mat_scalar_mul_fmpz(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, const fmpz_t c); /* Matrix arithmetic *********************************************************/ FLINT_DLL void fmpz_poly_mat_add(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B); FLINT_DLL void fmpz_poly_mat_sub(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B); FLINT_DLL void fmpz_poly_mat_neg(fmpz_poly_mat_t B, const fmpz_poly_mat_t A); FLINT_DLL void fmpz_poly_mat_mul(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B); FLINT_DLL void fmpz_poly_mat_mul_classical(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B); FLINT_DLL void fmpz_poly_mat_mul_KS(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B); FLINT_DLL void fmpz_poly_mat_mullow(fmpz_poly_mat_t C, const fmpz_poly_mat_t A, const fmpz_poly_mat_t B, slong len); FLINT_DLL void fmpz_poly_mat_sqr(fmpz_poly_mat_t B, const fmpz_poly_mat_t A); FLINT_DLL void fmpz_poly_mat_sqr_classical(fmpz_poly_mat_t B, const fmpz_poly_mat_t A); FLINT_DLL void fmpz_poly_mat_sqr_KS(fmpz_poly_mat_t B, const fmpz_poly_mat_t A); FLINT_DLL void fmpz_poly_mat_sqrlow(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, slong len); FLINT_DLL void fmpz_poly_mat_pow(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, ulong exp); FLINT_DLL void fmpz_poly_mat_pow_trunc(fmpz_poly_mat_t B, const fmpz_poly_mat_t A, ulong exp, slong len); FLINT_DLL void fmpz_poly_mat_prod(fmpz_poly_mat_t res, fmpz_poly_mat_t * const factors, slong n); /* Evaluation ****************************************************************/ FLINT_DLL void fmpz_poly_mat_evaluate_fmpz(fmpz_mat_t B, const fmpz_poly_mat_t A, const fmpz_t x); /* Row reduction *************************************************************/ FLINT_DLL slong fmpz_poly_mat_find_pivot_any(const fmpz_poly_mat_t mat, slong start_row, slong end_row, slong c); FLINT_DLL slong fmpz_poly_mat_find_pivot_partial(const fmpz_poly_mat_t mat, slong start_row, slong end_row, slong c); FLINT_DLL 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); FLINT_DLL slong fmpz_poly_mat_rref(fmpz_poly_mat_t B, fmpz_poly_t den, const fmpz_poly_mat_t A); /* Trace *********************************************************************/ FLINT_DLL void fmpz_poly_mat_trace(fmpz_poly_t trace, const fmpz_poly_mat_t mat); /* Determinant and rank ******************************************************/ FLINT_DLL void fmpz_poly_mat_det(fmpz_poly_t det, const fmpz_poly_mat_t A); FLINT_DLL void fmpz_poly_mat_det_fflu(fmpz_poly_t det, const fmpz_poly_mat_t A); FLINT_DLL void fmpz_poly_mat_det_interpolate(fmpz_poly_t det, const fmpz_poly_mat_t A); FLINT_DLL slong fmpz_poly_mat_rank(const fmpz_poly_mat_t A); /* Inverse *******************************************************************/ FLINT_DLL int fmpz_poly_mat_inv(fmpz_poly_mat_t Ainv, fmpz_poly_t den, const fmpz_poly_mat_t A); /* Nullspace *****************************************************************/ FLINT_DLL slong fmpz_poly_mat_nullspace(fmpz_poly_mat_t res, const fmpz_poly_mat_t mat); /* Solving *******************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 flint2-2.8.4/fmpz_poly_mat/000077500000000000000000000000001414523752600156145ustar00rootroot00000000000000flint2-2.8.4/fmpz_poly_mat/add.c000066400000000000000000000015171414523752600165140ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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)); } flint2-2.8.4/fmpz_poly_mat/clear.c000066400000000000000000000014031414523752600170440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_poly_mat/concat_horizontal.c000066400000000000000000000020541414523752600215010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } } } flint2-2.8.4/fmpz_poly_mat/concat_vertical.c000066400000000000000000000020521414523752600211170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_mat.h" 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)); } } } flint2-2.8.4/fmpz_poly_mat/det.c000066400000000000000000000024101414523752600165310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fmpz_poly_mat/det_fflu.c000066400000000000000000000017231414523752600175530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fmpz_poly_mat/det_interpolate.c000066400000000000000000000024121414523752600211410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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); } flint2-2.8.4/fmpz_poly_mat/equal.c000066400000000000000000000015341414523752600170720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_poly_mat/evaluate_fmpz.c000066400000000000000000000014171414523752600206250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_poly_mat/fflu.c000066400000000000000000000044401414523752600167160ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_div(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; } flint2-2.8.4/fmpz_poly_mat/find_pivot_any.c000066400000000000000000000014241414523752600207710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_poly_mat/find_pivot_partial.c000066400000000000000000000026771414523752600216510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_poly_mat/init.c000066400000000000000000000023151414523752600167240ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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; } flint2-2.8.4/fmpz_poly_mat/init_set.c000066400000000000000000000011531414523752600175760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" 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); } flint2-2.8.4/fmpz_poly_mat/inlines.c000066400000000000000000000010721414523752600174210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_POLY_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "fmpz_poly_mat.h" flint2-2.8.4/fmpz_poly_mat/inv.c000066400000000000000000000043361414523752600165620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } } flint2-2.8.4/fmpz_poly_mat/is_one.c000066400000000000000000000017561414523752600172450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_poly_mat/is_zero.c000066400000000000000000000014031414523752600174300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_poly_mat/max_bits.c000066400000000000000000000017351414523752600175740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_poly_mat/max_length.c000066400000000000000000000014341414523752600201100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_poly_mat/mul.c000066400000000000000000000013371414523752600165610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fmpz_poly_mat/mul_KS.c000066400000000000000000000043731414523752600171610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_poly_mat/mul_classical.c000066400000000000000000000031521414523752600205740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_poly_mat/mullow.c000066400000000000000000000032201414523752600172740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_poly_mat/neg.c000066400000000000000000000013461414523752600165350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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)); } flint2-2.8.4/fmpz_poly_mat/nullspace.c000066400000000000000000000037111414523752600177500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_poly_mat/one.c000066400000000000000000000012461414523752600165440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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)); } flint2-2.8.4/fmpz_poly_mat/pow.c000066400000000000000000000026601414523752600165710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fmpz_poly_mat/pow_trunc.c000066400000000000000000000032211414523752600177760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fmpz_poly_mat/print.c000066400000000000000000000016601414523752600171170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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"); } flint2-2.8.4/fmpz_poly_mat/prod.c000066400000000000000000000026111414523752600167240ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_poly_mat/randtest.c000066400000000000000000000013451414523752600176070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_poly_mat/randtest_sparse.c000066400000000000000000000021621414523752600211620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "ulong_extras.h" 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)); } } } } flint2-2.8.4/fmpz_poly_mat/randtest_unsigned.c000066400000000000000000000013671414523752600215070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" 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); } flint2-2.8.4/fmpz_poly_mat/rank.c000066400000000000000000000015261414523752600167170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_poly_mat/rref.c000066400000000000000000000051531414523752600167220ustar00rootroot00000000000000/* 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 2.1 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_div(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; } flint2-2.8.4/fmpz_poly_mat/scalar_mul_fmpz.c000066400000000000000000000016071414523752600211420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #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); } flint2-2.8.4/fmpz_poly_mat/scalar_mul_fmpz_poly.c000066400000000000000000000015751414523752600222110ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" 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); } flint2-2.8.4/fmpz_poly_mat/set.c000066400000000000000000000014261414523752600165560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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)); } } flint2-2.8.4/fmpz_poly_mat/solve.c000066400000000000000000000012701414523752600171100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_poly_mat/solve_fflu.c000066400000000000000000000024011414523752600201210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_poly_mat/solve_fflu_precomp.c000066400000000000000000000045341414523752600216570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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) { /* Not implemented */ flint_abort(); } else { slong i, j; if (perm == NULL) flint_abort(); 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_div(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_div(XX(i, k), XX(i, k), LU(i, i)); } } fmpz_poly_clear(T); } flint2-2.8.4/fmpz_poly_mat/sqr.c000066400000000000000000000012141414523752600165630ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_poly_mat/sqr_KS.c000066400000000000000000000032631414523752600171660ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); /* Should use fmpz_mat_sqr */ fmpz_mat_mul(BB, AA, 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); } flint2-2.8.4/fmpz_poly_mat/sqr_classical.c000066400000000000000000000025141414523752600206050ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_poly_mat/sqrlow.c000066400000000000000000000032241414523752600173100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_poly_mat/sub.c000066400000000000000000000015171414523752600165550ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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)); } flint2-2.8.4/fmpz_poly_mat/swap.c000066400000000000000000000012211414523752600167260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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) { if (A != B) { fmpz_poly_mat_struct tmp; tmp = *A; *A = *B; *B = tmp; } } flint2-2.8.4/fmpz_poly_mat/test/000077500000000000000000000000001414523752600165735ustar00rootroot00000000000000flint2-2.8.4/fmpz_poly_mat/test/t-add.c000066400000000000000000000106301414523752600177300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-concat_horizontal.c000066400000000000000000000037461414523752600227320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "ulong_extras.h" int main(void) { fmpz_poly_mat_t A, B, C; fmpz_poly_mat_t window1, window2; slong i; FLINT_TEST_INIT(state); flint_printf("concat_horizontal...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-concat_vertical.c000066400000000000000000000037371414523752600223520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "ulong_extras.h" int main(void) { fmpz_poly_mat_t A, B, C; fmpz_poly_mat_t window1, window2; slong i; FLINT_TEST_INIT(state); flint_printf("concat_vertical...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-det.c000066400000000000000000000047741414523752600177700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("det...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-det_interpolate.c000066400000000000000000000033121414523752600223610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("det_interpolate...."); fflush(stdout); 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"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-init_clear.c000066400000000000000000000022721414523752600213140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-inv.c000066400000000000000000000076731414523752600200110ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("inv...."); fflush(stdout); /* 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"); 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"); abort(); } } else { if (!fmpz_poly_equal(den, det)) { fmpz_poly_neg(det, det); flint_printf("FAIL: den != det(A)\n"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-mul.c000066400000000000000000000112421414523752600177750ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-mul_KS.c000066400000000000000000000110251414523752600203710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mul_KS...."); fflush(stdout); 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"); 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"); 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"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-mullow.c000066400000000000000000000110631414523752600205200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mullow...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-neg.c000066400000000000000000000055261414523752600177610ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("neg...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-nullspace.c000066400000000000000000000041221414523752600211650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("nullspace...."); fflush(stdout); 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"); abort(); } if (fmpz_poly_mat_rank(N) != nullity) { flint_printf("FAIL: wrong rank(N) != nullity!\n"); abort(); } fmpz_poly_mat_mul(AN, A, N); if (!fmpz_poly_mat_is_zero(AN)) { flint_printf("FAIL: A * N != 0\n"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(N); fmpz_poly_mat_clear(AN); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-one.c000066400000000000000000000035521414523752600177660ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("one/is_one...."); fflush(stdout); 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"); 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"); abort(); } } fmpz_poly_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-pow.c000066400000000000000000000053461414523752600200150ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("pow...."); fflush(stdout); 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"); 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"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-pow_trunc.c000066400000000000000000000056761414523752600212360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("pow_trunc...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-prod.c000066400000000000000000000037661414523752600201600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("prod...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-rank.c000066400000000000000000000036571414523752600201460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("rank...."); fflush(stdout); 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); abort(); } fmpz_clear(x); fmpz_mat_clear(Ax); fmpz_poly_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-rref.c000066400000000000000000000111151414523752600201350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_poly_mat.h" #include "perm.h" #include "ulong_extras.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; } int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("rref...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-solve_fflu.c000066400000000000000000000066421414523752600213540ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("solve_fflu...."); fflush(stdout); 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"); 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"); abort(); } } if (solved != !fmpz_poly_is_zero(den)) { flint_printf("FAIL: return value does not match denominator\n"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-sqr.c000066400000000000000000000055501414523752600200120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("sqr...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-sqr_KS.c000066400000000000000000000054421414523752600204070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("sqr_KS...."); fflush(stdout); 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"); 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"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-sqrlow.c000066400000000000000000000055131414523752600205330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("sqrlow...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-sub.c000066400000000000000000000106301414523752600177710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_mat_clear(A); fmpz_poly_mat_clear(B); fmpz_poly_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-trace.c000066400000000000000000000044301414523752600202770ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("trace...."); fflush(stdout); /* 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-window_init_clear.c000066400000000000000000000032741414523752600227060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("window_init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/test/t-zero.c000066400000000000000000000032041414523752600201560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpz_poly.h" #include "fmpz_poly_mat.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("zero/is_zero...."); fflush(stdout); 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"); 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"); abort(); } } fmpz_poly_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_poly_mat/trace.c000066400000000000000000000014511414523752600170570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } } flint2-2.8.4/fmpz_poly_mat/transpose.c000066400000000000000000000023511414523752600177770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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_printf("Exception (fmpz_poly_mat_transpose). Incompatible dimensions.\n"); flint_abort(); } 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)); } } flint2-2.8.4/fmpz_poly_mat/truncate.c000066400000000000000000000013271414523752600176100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_poly_mat/window_clear.c000066400000000000000000000010671414523752600204410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_mat.h" void fmpz_poly_mat_window_clear(fmpz_poly_mat_t window) { if (window->r != 0) flint_free(window->rows); } flint2-2.8.4/fmpz_poly_mat/window_init.c000066400000000000000000000021251414523752600203120ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fmpz_poly_mat/zero.c000066400000000000000000000012271414523752600167410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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)); } flint2-2.8.4/fmpz_poly_matxx.h000066400000000000000000000417261414523752600163570ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_POLY_MATXX_H #define FMPZ_POLY_MATXX_H FMPZ_POLY_MATXX_H #include "fmpz_poly_mat.h" #include "fmpz_matxx.h" #include "fmpz_polyxx.h" #include "permxx.h" #include "flintxx/matrix.h" namespace flint { FLINT_DEFINE_UNOP(prod) namespace detail { template struct fmpz_poly_matxx_traits : matrices::generic_traits { }; } // detail template class fmpz_poly_matxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef detail::fmpz_poly_matxx_traits traits_t; FLINTXX_DEFINE_BASICS(fmpz_poly_matxx_expression) FLINTXX_DEFINE_CTORS(fmpz_poly_matxx_expression) FLINTXX_DEFINE_C_REF(fmpz_poly_matxx_expression, fmpz_poly_mat_struct, _mat) template static evaluated_t create_temporary_rowscols( const Expr&, slong rows, slong cols) { return evaluated_t(rows, cols); } FLINTXX_DEFINE_MATRIX_METHODS(traits_t) // static functions for fmpz_poly_matxx template static fmpz_poly_matxx_expression from_ground(const Fmpz_matxx& f) { return _from_ground(f.evaluate()); } template static fmpz_poly_matxx_expression _from_ground(const Fmpz_matxx& f) { fmpz_poly_matxx_expression res(f.rows(), f.cols()); for(slong i = 0;i < f.rows();++i) for(slong j = 0;j < f.rows();++j) res.at(i, j).set_coeff(0, f.at(i, j)); return res; } static fmpz_poly_matxx_expression randtest(slong rows, slong cols, frandxx& state, slong len, flint_bitcnt_t bits) { fmpz_poly_matxx_expression res(rows, cols); res.set_randtest(state, len, bits); return res; } static fmpz_poly_matxx_expression randtest_unsigned(slong rows, slong cols, frandxx& state, slong len, flint_bitcnt_t bits) { fmpz_poly_matxx_expression res(rows, cols); res.set_randtest_unsigned(state, len, bits); return res; } static fmpz_poly_matxx_expression randtest_sparse(slong rows, slong cols, frandxx& state, slong len, flint_bitcnt_t bits, float density) { fmpz_poly_matxx_expression res(rows, cols); res.set_randtest_sparse(state, len, bits, density); return res; } static fmpz_poly_matxx_expression zero(slong rows, slong cols) {return fmpz_poly_matxx_expression(rows, cols);} static fmpz_poly_matxx_expression one(slong rows, slong cols) { fmpz_poly_matxx_expression res(rows, cols); res.set_one(); return res; } // these only make sense with targets void set_randtest(frandxx& state, slong len, flint_bitcnt_t bits) {fmpz_poly_mat_randtest(_mat(), state._data(), len, bits);} void set_randtest_unsigned(frandxx& state, slong len, flint_bitcnt_t bits) {fmpz_poly_mat_randtest_unsigned(_mat(), state._data(), len, bits);} void set_randtest_sparse(frandxx& state, slong len, flint_bitcnt_t bits, float density) {fmpz_poly_mat_randtest_sparse(_mat(), state._data(), len, bits, density);} void truncate(slong len) {fmpz_poly_mat_truncate(_mat(), len);} void set_zero() {fmpz_poly_mat_zero(_mat());} void set_one() {fmpz_poly_mat_one(_mat());} // these cause evaluation slong rank() const {return fmpz_poly_mat_rank(this->evaluate()._mat());} bool is_zero() const {return fmpz_poly_mat_is_zero(this->evaluate()._mat());} bool is_one() const {return fmpz_poly_mat_is_one(this->evaluate()._mat());} bool is_empty() const {return fmpz_poly_mat_is_empty(this->evaluate()._mat());} bool is_square() const {return fmpz_poly_mat_is_square(this->evaluate()._mat());} slong max_length() const {return fmpz_poly_mat_max_length(this->evaluate()._mat());} slong max_bits() const {return fmpz_poly_mat_max_bits(this->evaluate()._mat());} slong find_pivot_any(slong start, slong end, slong c) const { return fmpz_poly_mat_find_pivot_any( this->evaluate()._mat(), start, end, c); } slong find_pivot_partial(slong start, slong end, slong c) const { return fmpz_poly_mat_find_pivot_partial( this->evaluate()._mat(), start, end, c); } // forwarded lazy ops FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval) FLINTXX_DEFINE_MEMBER_3OP(mullow) FLINTXX_DEFINE_MEMBER_3OP(pow_trunc) FLINTXX_DEFINE_MEMBER_BINOP(solve) FLINTXX_DEFINE_MEMBER_BINOP(solve_fflu) FLINTXX_DEFINE_MEMBER_BINOP(mul_KS) FLINTXX_DEFINE_MEMBER_BINOP(mul_classical) FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_BINOP(sqrlow) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, det) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, det_fflu) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, det_interpolate) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpz_polyxx, trace) FLINTXX_DEFINE_MEMBER_UNOP(sqr) FLINTXX_DEFINE_MEMBER_UNOP(sqr_classical) FLINTXX_DEFINE_MEMBER_UNOP(sqr_KS) FLINTXX_DEFINE_MEMBER_UNOP(transpose) //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(nullspace) // TODO //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(???, inv) // TODO //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(???, rref) // TODO FLINTXX_DEFINE_MEMBER_FFLU }; namespace detail { struct fmpz_poly_mat_data; } // detail typedef fmpz_poly_matxx_expression fmpz_poly_matxx; typedef fmpz_poly_matxx_expression > fmpz_poly_matxx_ref; typedef fmpz_poly_matxx_expression > fmpz_poly_matxx_srcref; template<> struct matrix_traits { template static slong rows(const M& m) { return fmpz_poly_mat_nrows(m._mat()); } template static slong cols(const M& m) { return fmpz_poly_mat_ncols(m._mat()); } template static fmpz_polyxx_srcref at(const M& m, slong i, slong j) { return fmpz_polyxx_srcref::make(fmpz_poly_mat_entry(m._mat(), i, j)); } template static fmpz_polyxx_ref at(M& m, slong i, slong j) { return fmpz_polyxx_ref::make(fmpz_poly_mat_entry(m._mat(), i, j)); } }; namespace detail { template<> struct fmpz_poly_matxx_traits : matrices::generic_traits_srcref { }; template<> struct fmpz_poly_matxx_traits : matrices::generic_traits_ref { }; template<> struct fmpz_poly_matxx_traits : matrices::generic_traits_nonref { }; struct fmpz_poly_mat_data { typedef fmpz_poly_mat_t& data_ref_t; typedef const fmpz_poly_mat_t& data_srcref_t; fmpz_poly_mat_t inner; fmpz_poly_mat_data(slong m, slong n) { fmpz_poly_mat_init(inner, m, n); } fmpz_poly_mat_data(const fmpz_poly_mat_data& o) { fmpz_poly_mat_init_set(inner, o.inner); } fmpz_poly_mat_data(fmpz_poly_matxx_srcref o) { fmpz_poly_mat_init_set(inner, o._data().inner); } ~fmpz_poly_mat_data() {fmpz_poly_mat_clear(inner);} }; } // detail #define FMPZ_POLY_MATXX_COND_S FLINTXX_COND_S(fmpz_poly_matxx) #define FMPZ_POLY_MATXX_COND_T FLINTXX_COND_T(fmpz_poly_matxx) namespace matrices { template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; } // matrices FLINTXX_DEFINE_TEMPORARY_RULES(fmpz_poly_matxx) namespace rules { FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLY_MATXX_COND_T, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_set(to._mat(), from._mat())) FLINTXX_DEFINE_SWAP(fmpz_poly_matxx, fmpz_poly_mat_swap(e1._mat(), e2._mat())) FLINTXX_DEFINE_EQUALS(fmpz_poly_matxx, fmpz_poly_mat_equal(e1._mat(), e2._mat())) FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPZ_POLY_MATXX_COND_S, const char*, (fmpz_poly_mat_print(from._mat(), extra), 1)) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_mul(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZXX_COND_S, fmpz_poly_mat_scalar_mul_fmpz(to._mat(), e1._mat(), e2._fmpz())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_mat_scalar_mul_fmpz_poly(to._mat(), e1._mat(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_add(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_sub(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_neg(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(transpose_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_transpose(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(trace_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_trace(to._poly(), from._mat())) FLINT_DEFINE_THREEARY_EXPR_COND3(mat_at_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S, traits::fits_into_slong, traits::fits_into_slong, fmpz_poly_set(to._poly(), fmpz_poly_mat_entry(e1._mat(), e2, e3))) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpz_matxx, FMPZ_POLY_MATXX_COND_S, FMPZXX_COND_S, fmpz_poly_mat_evaluate_fmpz(to._mat(), e1._mat(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(mul_classical_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_mul_classical(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(mul_KS_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_mul_KS(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_THREEARY_EXPR_COND3(mullow_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, traits::fits_into_slong, fmpz_poly_mat_mullow(to._mat(), e1._mat(), e2._mat(), e3)) FLINT_DEFINE_UNARY_EXPR_COND(sqr_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_sqr(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_classical_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_sqr_classical(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_KS_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_sqr_KS(to._mat(), from._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(sqrlow_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, traits::fits_into_slong, fmpz_poly_mat_sqrlow(to._mat(), e1._mat(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, traits::is_unsigned_integer, fmpz_poly_mat_pow(to._mat(), e1._mat(), e2)) FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_op, fmpz_poly_matxx, FMPZ_POLY_MATXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong, fmpz_poly_mat_pow_trunc(to._mat(), e1._mat(), e2, e3)) FLINT_DEFINE_UNARY_EXPR_COND(det_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_det(to._poly(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(det_fflu_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_det_fflu(to._poly(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(det_interpolate_op, fmpz_polyxx, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_det_interpolate(to._poly(), from._mat())) namespace rdetail { typedef make_ltuple::type >::type fmpz_poly_mat_inv_rt; typedef make_ltuple::type >::type fmpz_poly_mat_nullspace_rt; } FLINT_DEFINE_UNARY_EXPR_COND(inv_op, rdetail::fmpz_poly_mat_inv_rt, FMPZ_POLY_MATXX_COND_S, to.template get<0>() = fmpz_poly_mat_inv(to.template get<1>()._mat(), to.template get<2>()._poly(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(nullspace_op, rdetail::fmpz_poly_mat_nullspace_rt, FMPZ_POLY_MATXX_COND_S, to.template get<0>() = fmpz_poly_mat_nullspace( to.template get<1>()._mat(), from._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(solve_op, rdetail::fmpz_poly_mat_inv_rt, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, to.template get<0>() = fmpz_poly_mat_solve(to.template get<1>()._mat(), to.template get<2>()._poly(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(solve_fflu_op, rdetail::fmpz_poly_mat_inv_rt, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, to.template get<0>() = fmpz_poly_mat_solve_fflu( to.template get<1>()._mat(), to.template get<2>()._poly(), e1._mat(), e2._mat())) namespace rdetail { typedef make_ltuple::type>::type fmpz_poly_matxx_fflu_rt; } // rdetail FLINT_DEFINE_THREEARY_EXPR_COND3(fflu_op, rdetail::fmpz_poly_matxx_fflu_rt, FMPZ_POLY_MATXX_COND_S, traits::is_maybe_perm, tools::is_bool, to.template get<0>() = fmpz_poly_mat_fflu(to.template get<1>()._mat(), to.template get<2>()._poly(), maybe_perm_data(e2), e1._mat(), e3)) FLINT_DEFINE_UNARY_EXPR_COND(rref_op, rdetail::fmpz_poly_matxx_fflu_rt, FMPZ_POLY_MATXX_COND_S, to.template get<0>() = fmpz_poly_mat_rref(to.template get<1>()._mat(), to.template get<2>()._poly(), from._mat())) FLINT_DEFINE_THREEARY_EXPR_COND3(solve_fflu_precomp_op, fmpz_poly_matxx, traits::is_permxx, FMPZ_POLY_MATXX_COND_S, FMPZ_POLY_MATXX_COND_S, fmpz_poly_mat_solve_fflu_precomp(to._mat(), e1._data(), e2._mat(), e3._mat())) } // rules //////////////////////////////////////////////////////////////////////////// // fmpz_poly_mat_vecxx and prod //////////////////////////////////////////////////////////////////////////// namespace detail { struct fmpz_poly_mat_vector_data { slong size; fmpz_poly_mat_t* array; fmpz_poly_mat_vector_data(slong n, slong rows, slong cols) : size(n) { array = new fmpz_poly_mat_t[n]; for(slong i = 0; i < n; ++i) fmpz_poly_mat_init(array[i], rows, cols); } ~fmpz_poly_mat_vector_data() { for(slong i = 0; i < size; ++i) fmpz_poly_mat_clear(array[i]); delete[] array; } fmpz_poly_mat_vector_data(const fmpz_poly_mat_vector_data& o) : size(o.size) { array = new fmpz_poly_mat_t[size]; for(slong i = 0; i < size; ++i) fmpz_poly_mat_init_set(array[i], o.array[i]); } fmpz_poly_matxx_ref at(slong i) {return fmpz_poly_matxx_ref::make(array[i]);} fmpz_poly_matxx_srcref at(slong i) const {return fmpz_poly_matxx_srcref::make(array[i]);} bool equals(const fmpz_poly_mat_vector_data& o) const { if(size != o.size) return false; for(slong i = 0; i < size; ++i) if(!fmpz_poly_mat_equal(array[i], o.array[i])) return false; return true; } }; } // detail // TODO temporary allocation typedef vector_expression< detail::wrapped_vector_traits, operations::immediate, detail::fmpz_poly_mat_vector_data> fmpz_poly_mat_vecxx; // TODO references template<> struct enable_vector_rules : mp::false_ { }; namespace matrices { template<> struct outsize { template static slong rows(const Mat& m) { return m._data().head[0].rows(); } template static slong cols(const Mat& m) { return m._data().head[0].cols(); } }; } namespace rules { // TODO hack to make code look like references are implemented template struct FMPZ_POLY_MAT_VECXX_COND_S : mp::equal_types { }; #define FMPZ_POLY_MAT_VECXX_COND_T FMPZ_POLY_MAT_VECXX_COND_S // TODO references FLINT_DEFINE_GET(equals, bool, fmpz_poly_mat_vecxx, e1._data().equals(e2._data())) FLINT_DEFINE_UNARY_EXPR_COND(prod_op, fmpz_poly_matxx, FMPZ_POLY_MAT_VECXX_COND_S, fmpz_poly_mat_prod(to._mat(), (fmpz_poly_mat_t * const) from._array(), from.size())) } // rules } // flint #endif flint2-2.8.4/fmpz_poly_q.h000066400000000000000000000134121414523752600154450ustar00rootroot00000000000000/* Copyright (C) 2009, 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 2.1 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 FLINT_DLL #else #define FMPZ_POLY_Q_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #ifdef __cplusplus extern "C" { #endif typedef struct { fmpz_poly_struct *num; fmpz_poly_struct *den; } fmpz_poly_q_struct; typedef fmpz_poly_q_struct fmpz_poly_q_t[1]; /* Accessing numerator and denominator ***************************************/ #define fmpz_poly_q_numref(op) ((op)->num) #define fmpz_poly_q_denref(op) ((op)->den) FLINT_DLL void fmpz_poly_q_canonicalise(fmpz_poly_q_t rop); FLINT_DLL int fmpz_poly_q_is_canonical(const fmpz_poly_q_t op); /* Memory management *********************************************************/ FLINT_DLL void fmpz_poly_q_init(fmpz_poly_q_t rop); FLINT_DLL void fmpz_poly_q_clear(fmpz_poly_q_t rop); /* Randomisation *************************************************************/ FLINT_DLL 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); FLINT_DLL 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 ****************************************************************/ FLINT_DLL void fmpz_poly_q_set(fmpz_poly_q_t rop, const fmpz_poly_q_t op); FLINT_DLL void fmpz_poly_q_set_si(fmpz_poly_q_t rop, slong op); FLINT_DLL 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); } FLINT_DLL 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 **************************************************/ FLINT_DLL void fmpz_poly_q_add_in_place(fmpz_poly_q_t rop, const fmpz_poly_q_t op); FLINT_DLL void fmpz_poly_q_sub_in_place(fmpz_poly_q_t rop, const fmpz_poly_q_t op); FLINT_DLL void fmpz_poly_q_add(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2); FLINT_DLL void fmpz_poly_q_sub(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2); FLINT_DLL void fmpz_poly_q_addmul(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2); FLINT_DLL 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 ****************************************/ FLINT_DLL void fmpz_poly_q_scalar_mul_si(fmpz_poly_q_t rop, const fmpz_poly_q_t op, slong x); FLINT_DLL void fmpz_poly_q_scalar_mul_mpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpz_t x); FLINT_DLL void fmpz_poly_q_scalar_mul_mpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpq_t x); FLINT_DLL void fmpz_poly_q_scalar_div_si(fmpz_poly_q_t rop, const fmpz_poly_q_t op, slong x); FLINT_DLL void fmpz_poly_q_scalar_div_mpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpz_t x); FLINT_DLL void fmpz_poly_q_scalar_div_mpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpq_t x); /* Multiplication and division ***********************************************/ FLINT_DLL void fmpz_poly_q_mul(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2); FLINT_DLL void fmpz_poly_q_div(fmpz_poly_q_t rop, const fmpz_poly_q_t op1, const fmpz_poly_q_t op2); /* Powering ******************************************************************/ FLINT_DLL void fmpz_poly_q_pow(fmpz_poly_q_t rop, const fmpz_poly_q_t op, ulong exp); /* Derivative ****************************************************************/ FLINT_DLL void fmpz_poly_q_derivative(fmpz_poly_q_t rop, const fmpz_poly_q_t op); /* Evaluation ****************************************************************/ FLINT_DLL int fmpz_poly_q_evaluate(mpq_t rop, const fmpz_poly_q_t f, const mpq_t a); /* Input and output **********************************************************/ FLINT_DLL int fmpz_poly_q_set_str(fmpz_poly_q_t rop, const char *s); FLINT_DLL char * fmpz_poly_q_get_str(const fmpz_poly_q_t op); FLINT_DLL char * fmpz_poly_q_get_str_pretty(const fmpz_poly_q_t op, const char *x); FLINT_DLL int fmpz_poly_q_print(const fmpz_poly_q_t op); FLINT_DLL int fmpz_poly_q_print_pretty(const fmpz_poly_q_t op, const char *x); #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpz_poly_q/000077500000000000000000000000001414523752600152735ustar00rootroot00000000000000flint2-2.8.4/fmpz_poly_q/add.c000066400000000000000000000154001414523752600161670ustar00rootroot00000000000000/* 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 2.1 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_div(r2, rop->den, d); fmpz_poly_div(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_div(rop->num, rop->num, r2); fmpz_poly_div(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_div(r2, op1->den, d); /* +ve leading coeff */ fmpz_poly_div(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_div(rop->num, rop->num, r2); fmpz_poly_div(rop->den, rop->den, r2); } } fmpz_poly_clear(d); fmpz_poly_clear(r2); fmpz_poly_clear(s2); } } flint2-2.8.4/fmpz_poly_q/addmul.c000066400000000000000000000012701414523752600167050ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_poly_q/canonicalise.c000066400000000000000000000021011414523752600200610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_poly_q_canonicalise). Denominator is zero.\n"); flint_abort(); } 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_div(rop->num, rop->num, gcd); fmpz_poly_div(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); } } flint2-2.8.4/fmpz_poly_q/clear.c000066400000000000000000000013211414523752600165220ustar00rootroot00000000000000/* 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 2.1 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; } } flint2-2.8.4/fmpz_poly_q/derivative.c000066400000000000000000000040401414523752600175770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_div(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_div(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); } flint2-2.8.4/fmpz_poly_q/div.c000066400000000000000000000070751414523752600162320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_poly_q_div). Division by zero.\n"); flint_abort(); } 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_div(rop->num, op2->den, rop->den); fmpz_poly_mul(rop->num, op1->num, rop->num); fmpz_poly_div(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_div(rop->den, op2->num, rop->num); fmpz_poly_mul(rop->den, op1->den, rop->den); fmpz_poly_div(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_div(t, op1->num, rop->num); fmpz_poly_div(u, op2->num, rop->num); fmpz_poly_div(rop->num, op2->den, rop->den); fmpz_poly_mul(rop->num, t, rop->num); fmpz_poly_div(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); } } flint2-2.8.4/fmpz_poly_q/evaluate.c000066400000000000000000000031551414523752600172510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" int fmpz_poly_q_evaluate(mpq_t rop, const fmpz_poly_q_t f, const mpq_t a) { if (flint_mpz_cmp_si(mpq_denref(a), 1)) /* a is not an integer */ { mpq_t mpqnum, mpqden; mpq_init(mpqden); fmpz_poly_evaluate_mpq(mpqden, f->den, a); if (mpq_sgn(mpqden) == 0) { mpq_clear(mpqden); return 1; } mpq_init(mpqnum); fmpz_poly_evaluate_mpq(mpqnum, f->num, a); mpq_div(rop, mpqnum, mpqden); mpq_clear(mpqnum); mpq_clear(mpqden); return 0; } else /* a is an integer */ { fmpz_t num, den, a2; fmpz_init(num); fmpz_init(den); fmpz_init(a2); fmpz_set_mpz(a2, mpq_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_get_mpz(mpq_numref(rop), num); fmpz_get_mpz(mpq_denref(rop), den); mpq_canonicalize(rop); fmpz_clear(a2); fmpz_clear(num); fmpz_clear(den); return 0; } } flint2-2.8.4/fmpz_poly_q/get_str.c000066400000000000000000000031771414523752600171160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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_printf("Exception (fmpz_poly_q_get_str). Memory allocation failed.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpz_poly_q/get_str_pretty.c000066400000000000000000000036411414523752600205210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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_printf("Exception (fmpz_poly_q_get_str_pretty). Memory allocation failed.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpz_poly_q/init.c000066400000000000000000000012351414523752600164030ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_poly_q/inlines.c000066400000000000000000000010661414523752600171030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_POLY_Q_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "fmpz_poly_q.h" flint2-2.8.4/fmpz_poly_q/inv.c000066400000000000000000000022511414523752600162330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fmpz_poly_q_inv). Zero is not invertible.\n"); flint_abort(); } 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); } } } flint2-2.8.4/fmpz_poly_q/is_canonical.c000066400000000000000000000013741414523752600200660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fmpz_poly_q/mul.c000066400000000000000000000067531414523752600162470ustar00rootroot00000000000000/* 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 2.1 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_div(rop->num, op2->num, rop->den); fmpz_poly_mul(rop->num, op1->num, rop->num); fmpz_poly_div(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_div(rop->den, op2->den, rop->num); fmpz_poly_mul(rop->den, op1->den, rop->den); fmpz_poly_div(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_div(t, op1->num, rop->num); fmpz_poly_div(u, op2->den, rop->num); fmpz_poly_div(rop->num, op2->num, rop->den); fmpz_poly_mul(rop->num, t, rop->num); fmpz_poly_div(rop->den, op1->den, rop->den); fmpz_poly_mul(rop->den, rop->den, u); fmpz_poly_clear(t); fmpz_poly_clear(u); } } } flint2-2.8.4/fmpz_poly_q/pow.c000066400000000000000000000012661414523752600162510ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/fmpz_poly_q/print.c000066400000000000000000000011601414523752600165710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/fmpz_poly_q/print_pretty.c000066400000000000000000000012201414523752600201750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/fmpz_poly_q/randtest.c000066400000000000000000000025011414523752600172610ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_poly_q/scalar_div_mpq.c000066400000000000000000000020061414523752600204210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" void fmpz_poly_q_scalar_div_mpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpq_t x) { fmpz_t num, den; if (mpz_sgn(mpq_numref(x)) == 0) { flint_printf("Exception (fmpz_poly_q_scalar_div_mpq). Division by zero.\n"); flint_abort(); } fmpz_init(num); fmpz_init(den); fmpz_set_mpz(num, mpq_numref(x)); fmpz_set_mpz(den, mpq_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); } flint2-2.8.4/fmpz_poly_q/scalar_div_mpz.c000066400000000000000000000015771414523752600204460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" void fmpz_poly_q_scalar_div_mpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpz_t x) { fmpz_t y; if (mpz_sgn(x) == 0) { flint_printf("Exception (fmpz_poly_q_scalar_div_mpz). Division by zero.\n"); flint_abort(); } fmpz_init(y); fmpz_set_mpz(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); } flint2-2.8.4/fmpz_poly_q/scalar_div_si.c000066400000000000000000000042121414523752600202400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" 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_printf("Exception (fmpz_poly_q_scalar_div_si). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/fmpz_poly_q/scalar_mul_mpq.c000066400000000000000000000015501414523752600204370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" void fmpz_poly_q_scalar_mul_mpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpq_t x) { fmpz_t num, den; fmpz_init(num); fmpz_init(den); fmpz_set_mpz(num, mpq_numref(x)); fmpz_set_mpz(den, mpq_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); } flint2-2.8.4/fmpz_poly_q/scalar_mul_mpz.c000066400000000000000000000013551414523752600204530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" void fmpz_poly_q_scalar_mul_mpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpz_t x) { fmpz_t y; fmpz_init(y); fmpz_set_mpz(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); } flint2-2.8.4/fmpz_poly_q/scalar_mul_si.c000066400000000000000000000026231414523752600202570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" 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); } flint2-2.8.4/fmpz_poly_q/set.c000066400000000000000000000011321414523752600162270ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/fmpz_poly_q/set_si.c000066400000000000000000000010431414523752600167230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly_q.h" 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); } flint2-2.8.4/fmpz_poly_q/set_str.c000066400000000000000000000041271414523752600171260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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_printf("Exception (fmpz_poly_q_set_str). Memory allocation failed.\n"); flint_abort(); } 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; } } flint2-2.8.4/fmpz_poly_q/sub.c000066400000000000000000000107661414523752600162420ustar00rootroot00000000000000/* 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 2.1 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_div(r2, op1->den, d); /* +ve leading coeff */ fmpz_poly_div(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_div(rop->num, rop->num, r2); fmpz_poly_div(rop->den, rop->den, r2); } } fmpz_poly_clear(d); fmpz_poly_clear(r2); fmpz_poly_clear(s2); } } flint2-2.8.4/fmpz_poly_q/submul.c000066400000000000000000000012701414523752600167460ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fmpz_poly_q/swap.c000066400000000000000000000013011414523752600164040ustar00rootroot00000000000000/* 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 2.1 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; } } flint2-2.8.4/fmpz_poly_q/test/000077500000000000000000000000001414523752600162525ustar00rootroot00000000000000flint2-2.8.4/fmpz_poly_q/test/t-add.c000066400000000000000000000070611414523752600174130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add... "); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-addmul.c000066400000000000000000000051261414523752600201310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("addmul... "); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-all.c000066400000000000000000001217021414523752600174320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_scalar_mul_mpz(char * in, mpz_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_mpz(rop, op, x); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_scalar_mul_mpz: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_scalar_mul_mpq(char * in, mpq_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_mpq(rop, op, x); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_scalar_mul_mpq: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); 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); abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_scalar_div_mpz(char * in, mpz_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_mpz(rop, op, x); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_scalar_div_mpz: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); abort(); } fmpz_poly_q_clear(op); fmpz_poly_q_clear(rop); flint_free(res); } void test_scalar_div_mpq(char * in, mpq_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_mpq(rop, op, x); res = fmpz_poly_q_get_str(rop); ans = !strcmp(out, res); if (!ans) { flint_printf("test_scalar_div_mpq: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", out, res); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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; mpq_t rop, a; char *res = NULL; fmpz_poly_q_init(op); fmpz_poly_q_set_str(op, in); mpq_init(a); flint_mpq_set_si(a, numa, numb); mpq_init(rop); pole = fmpz_poly_q_evaluate(rop, op, a); if (pole && strcmp(out, "P")) { flint_printf("test_evaluate: failed\n"); flint_printf(" Expected \"%s\", got a pole\n", out); abort(); } if (!pole && !strcmp(out, "P")) { res = mpq_get_str(NULL, 10, rop); flint_printf("test_evaluate: failed\n"); flint_printf(" Expected a pole, got \"%s\"\n", res); abort(); } if (!pole) { res = mpq_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); abort(); } } fmpz_poly_q_clear(op); mpq_clear(rop); mpq_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); 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); 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); abort(); } fmpz_poly_q_clear(rop); fmpz_poly_q_clear(op1); fmpz_poly_q_clear(op2); flint_free(res); } int main(int argc, char *argv[]) { int ans; char *str, *strout; fmpz_poly_t zpoly; fmpz_poly_q_t qpoly1; mpz_t mpzzero, mpzone, mpztwo; mpq_t mpqzero, mpqone, mpqtwo, mpqtwoinv; FLINT_TEST_INIT(state); flint_printf("all... "); fflush(stdout); /* 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"); 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); 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); 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); 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); 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); 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); 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); 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 devision ************************************/ flint_mpz_init_set_si(mpzzero, 0); flint_mpz_init_set_si(mpzone, 1); flint_mpz_init_set_si(mpztwo, 2); mpq_init(mpqzero); flint_mpq_set_si(mpqzero, 0, 1); mpq_init(mpqone); flint_mpq_set_si(mpqone, 1, 1); mpq_init(mpqtwo); flint_mpq_set_si(mpqtwo, 2, 1); mpq_init(mpqtwoinv); flint_mpq_set_si(mpqtwoinv, 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_mpz("0", mpzone, "0"); test_scalar_mul_mpz("0", mpzzero, "0"); test_scalar_mul_mpz("1 2", mpzzero, "0"); test_scalar_mul_mpz("1 1/1 2", mpztwo, "1 1"); test_scalar_mul_mpq("0", mpqone, "0"); test_scalar_mul_mpq("0", mpqzero, "0"); test_scalar_mul_mpq("1 2", mpqzero, "0"); test_scalar_mul_mpq("1 1/1 2", mpqtwo, "1 1"); test_scalar_mul_mpq("1 -2/1 1", mpqtwoinv, "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_mpz("0", mpzone, "0"); test_scalar_div_mpz("1 2", mpztwo, "1 1"); test_scalar_div_mpz("1 1/1 2", mpztwo, "1 1/1 4"); test_scalar_div_mpq("0", mpqone, "0"); test_scalar_div_mpq("1 2", mpqone, "1 2"); test_scalar_div_mpq("1 1/1 2", mpqtwo, "1 1/1 4"); test_scalar_div_mpq("1 -2/1 1", mpqtwoinv, "1 -4"); mpz_clear(mpzzero); mpz_clear(mpzone); mpz_clear(mpztwo); mpq_clear(mpqzero); mpq_clear(mpqone); mpq_clear(mpqtwo); mpq_clear(mpqtwoinv); /* 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"); 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"); 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"); 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"); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-derivative.c000066400000000000000000000067101414523752600210250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("derivative... "); fflush(stdout); /* 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-div.c000066400000000000000000000070751414523752600174520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div... "); fflush(stdout); /* 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-evaluate.c000066400000000000000000000041521414523752600204670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate..."); fflush(stdout); /* Check aliasing */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { int ans1, ans2; mpq_t a, b; fmpz_t num, den; fmpz_poly_q_t f; mpq_init(a); mpq_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_get_mpz(mpq_numref(a), num); fmpz_get_mpz(mpq_denref(a), den); mpq_canonicalize(a); ans1 = fmpz_poly_q_evaluate(b, f, a); ans2 = fmpz_poly_q_evaluate(a, f, a); result = (ans1 == ans2) && mpq_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"); gmp_printf("a = %Qd\n", a); gmp_printf("b = %Qd\n", b); flint_printf("ans1 = %d\n", ans1); flint_printf("ans2 = %d\n", ans2); abort(); } mpq_clear(a); mpq_clear(b); fmpz_clear(num); fmpz_clear(den); fmpz_poly_q_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-init_clear.c000066400000000000000000000022261414523752600207720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear... "); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-inv.c000066400000000000000000000041471414523752600174610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("inv... "); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-mul.c000066400000000000000000000070421414523752600174570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul... "); fflush(stdout); /* 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-neg.c000066400000000000000000000041251414523752600174320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg... "); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-pow.c000066400000000000000000000027751414523752600174770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow... "); fflush(stdout); /* 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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-scalar_div_mpq.c000066400000000000000000000067731414523752600216600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_div_mpq... "); fflush(stdout); /* 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; mpq_t y; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_init(x1); fmpz_init(x2); mpq_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_get_mpz(mpq_numref(y), x1); fmpz_get_mpz(mpq_denref(y), x2); mpq_canonicalize(y); fmpz_poly_q_scalar_div_mpq(a, b, y); fmpz_poly_q_scalar_div_mpq(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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_clear(x1); fmpz_clear(x2); mpq_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; mpq_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); mpq_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_get_mpz(mpq_numref(y), x1); fmpz_get_mpz(mpq_denref(y), x2); mpq_canonicalize(y); fmpz_poly_q_scalar_div_mpq(c, a, y); fmpz_poly_q_scalar_div_mpq(d, b, y); fmpz_poly_q_add(d, c, d); fmpz_poly_q_add(c, a, b); fmpz_poly_q_scalar_div_mpq(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); 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); mpq_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-scalar_div_mpz.c000066400000000000000000000062131414523752600216560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_div_mpz... "); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_t x; mpz_t y; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_init(x); mpz_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_get_mpz(y, x); fmpz_poly_q_scalar_div_mpz(a, b, y); fmpz_poly_q_scalar_div_mpz(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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_clear(x); mpz_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; mpz_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); mpz_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_get_mpz(y, x); fmpz_poly_q_scalar_div_mpz(c, a, y); fmpz_poly_q_scalar_div_mpz(d, b, y); fmpz_poly_q_add(d, c, d); fmpz_poly_q_add(c, a, b); fmpz_poly_q_scalar_div_mpz(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 = %Zd\n\n", y); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); fmpz_clear(x); mpz_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-scalar_div_si.c000066400000000000000000000056771414523752600215000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_div_si... "); fflush(stdout); /* 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"); 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); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-scalar_mul_mpq.c000066400000000000000000000067511414523752600216670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_mpq... "); fflush(stdout); /* 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; mpq_t y; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_init(x1); fmpz_init(x2); mpq_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_get_mpz(mpq_numref(y), x1); fmpz_get_mpz(mpq_denref(y), x2); mpq_canonicalize(y); fmpz_poly_q_scalar_mul_mpq(a, b, y); fmpz_poly_q_scalar_mul_mpq(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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_clear(x1); fmpz_clear(x2); mpq_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; mpq_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); mpq_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_get_mpz(mpq_numref(y), x1); fmpz_get_mpz(mpq_denref(y), x2); mpq_canonicalize(y); fmpz_poly_q_scalar_mul_mpq(c, a, y); fmpz_poly_q_scalar_mul_mpq(d, b, y); fmpz_poly_q_add(d, c, d); fmpz_poly_q_add(c, a, b); fmpz_poly_q_scalar_mul_mpq(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); 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); mpq_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-scalar_mul_mpz.c000066400000000000000000000061671414523752600217010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_mpz... "); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { fmpz_poly_q_t a, b; fmpz_t x; mpz_t y; fmpz_poly_q_init(a); fmpz_poly_q_init(b); fmpz_init(x); mpz_init(y); fmpz_poly_q_randtest(b, state, n_randint(state, 50), 50, n_randint(state, 50), 50); fmpz_randtest(x, state, 50); fmpz_get_mpz(y, x); fmpz_poly_q_scalar_mul_mpz(a, b, y); fmpz_poly_q_scalar_mul_mpz(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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_clear(x); mpz_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; mpz_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); mpz_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_get_mpz(y, x); fmpz_poly_q_scalar_mul_mpz(c, a, y); fmpz_poly_q_scalar_mul_mpz(d, b, y); fmpz_poly_q_add(d, c, d); fmpz_poly_q_add(c, a, b); fmpz_poly_q_scalar_mul_mpz(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 = %Zd\n\n", y); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); fmpz_clear(x); mpz_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-scalar_mul_si.c000066400000000000000000000055311414523752600215000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_si... "); fflush(stdout); /* 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"); 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); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); fmpz_poly_q_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-set_equal.c000066400000000000000000000045771414523752600206560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set/equal... "); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(x1); fmpz_clear(x2); fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-set_si_equal.c000066400000000000000000000044321414523752600213370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_si_equal... "); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-sub.c000066400000000000000000000047541414523752600174620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add... "); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-submul.c000066400000000000000000000051261414523752600201720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("submul... "); fflush(stdout); /* 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"); 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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-swap.c000066400000000000000000000031251414523752600176320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("swap... "); fflush(stdout); 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"); abort(); } fmpz_poly_q_clear(a); fmpz_poly_q_clear(b); fmpz_poly_q_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_q/test/t-zero.c000066400000000000000000000024361414523752600176430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "fmpz_poly_q.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("zero... "); fflush(stdout); 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"); abort(); } fmpz_poly_q_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fmpz_poly_qxx.h000066400000000000000000000251761414523752600160370ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_POLY_QXX_H #define FMPZ_POLY_QXX_H FMPZ_POLY_QXX_H #include #include #include "flint.h" #include "fmpz_poly_q.h" #include "fmpz_polyxx.h" #include "fmpqxx.h" #include "flintxx/expression.h" #include "flintxx/flint_classes.h" namespace flint { FLINT_DEFINE_UNOP(fmpz_poly_qxx_num) FLINT_DEFINE_UNOP(fmpz_poly_qxx_den) namespace detail { template struct fmpz_poly_q_traits { typedef FLINT_UNOP_BUILD_RETTYPE( fmpz_poly_qxx_num, fmpz_polyxx, Polyq) num_ref_t; typedef FLINT_UNOP_BUILD_RETTYPE( fmpz_poly_qxx_den, fmpz_polyxx, Polyq) den_ref_t; typedef num_ref_t num_srcref_t; typedef den_ref_t den_srcref_t; static num_ref_t num(const Polyq& p) {return fmpz_poly_qxx_num(p);} static den_ref_t den(const Polyq& p) {return fmpz_poly_qxx_den(p);} }; } // detail template class fmpz_poly_qxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef detail::fmpz_poly_q_traits poly_traits_t; typedef typename poly_traits_t::num_ref_t num_ref_t; typedef typename poly_traits_t::num_srcref_t num_srcref_t; typedef typename poly_traits_t::den_ref_t den_ref_t; typedef typename poly_traits_t::den_srcref_t den_srcref_t; FLINTXX_DEFINE_BASICS(fmpz_poly_qxx_expression) FLINTXX_DEFINE_CTORS(fmpz_poly_qxx_expression) FLINTXX_DEFINE_C_REF(fmpz_poly_qxx_expression, fmpz_poly_q_struct, _polyq) // static methods which only make sense with fmpq_polyxx static fmpz_poly_qxx_expression randtest(frandxx& state, slong len1, flint_bitcnt_t bits1, slong len2, flint_bitcnt_t bits2) { fmpz_poly_qxx_expression res; fmpz_poly_q_randtest(res._polyq(), state._data(), len1, bits1, len2, bits2); return res; } static fmpz_poly_qxx_expression randtest_not_zero(frandxx& state, slong len1, flint_bitcnt_t bits1, slong len2, flint_bitcnt_t bits2) { fmpz_poly_qxx_expression res; fmpz_poly_q_randtest_not_zero(res._polyq(), state._data(), len1, bits1, len2, bits2); return res; } static fmpz_poly_qxx_expression zero(){return fmpz_poly_qxx_expression();} static fmpz_poly_qxx_expression one() { fmpz_poly_qxx_expression res; res.set_one(); return res; } // Numerator and denominator access num_ref_t num() {return poly_traits_t::num(*this);} num_srcref_t num() const {return poly_traits_t::num(*this);} den_ref_t den() {return poly_traits_t::den(*this);} den_srcref_t den() const {return poly_traits_t::den(*this);} bool is_canonical() const {return fmpz_poly_q_is_canonical(_polyq());} // these only make sense with target immediates void canonicalise() {fmpz_poly_q_canonicalise(_polyq());} void set_zero() {fmpz_poly_q_zero(_polyq());} void set_one() {fmpz_poly_q_one(_polyq());} // These cause evaluation std::string pretty(const char* x) const { char* str = fmpz_poly_q_get_str_pretty(this->evaluate()._polyq(), x); std::string res(str); flint_free(str); return res; } bool is_one() const {return fmpz_poly_q_is_one(this->evaluate()._polyq());} bool is_zero() const {return fmpz_poly_q_is_zero(this->evaluate()._polyq());} // forwarded lazy member functions FLINTXX_DEFINE_MEMBER_UNOP(inv) FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_UNOP(derivative) }; namespace detail { struct fmpz_poly_q_data; } typedef fmpz_poly_qxx_expression fmpz_poly_qxx; typedef fmpz_poly_qxx_expression > fmpz_poly_qxx_ref; typedef fmpz_poly_qxx_expression > fmpz_poly_qxx_srcref; namespace detail { template<> struct fmpz_poly_q_traits { typedef fmpz_polyxx_srcref num_ref_t; typedef fmpz_polyxx_srcref num_srcref_t; typedef fmpz_polyxx_srcref den_ref_t; typedef fmpz_polyxx_srcref den_srcref_t; template static num_srcref_t num(const P& p) {return num_srcref_t::make(fmpz_poly_q_numref(p._polyq()));} template static den_srcref_t den(const P& p) {return num_srcref_t::make(fmpz_poly_q_denref(p._polyq()));} }; template<> struct fmpz_poly_q_traits { typedef fmpz_polyxx_ref num_ref_t; typedef fmpz_polyxx_ref den_ref_t; typedef fmpz_polyxx_ref num_srcref_t; typedef fmpz_polyxx_ref den_srcref_t; template static num_ref_t num(P p) {return num_ref_t::make(fmpz_poly_q_numref(p._polyq()));} template static den_ref_t den(P p) {return num_ref_t::make(fmpz_poly_q_denref(p._polyq()));} }; template<> struct fmpz_poly_q_traits { typedef fmpz_polyxx_ref num_ref_t; typedef fmpz_polyxx_ref den_ref_t; typedef fmpz_polyxx_srcref num_srcref_t; typedef fmpz_polyxx_srcref den_srcref_t; template static num_ref_t num(P& p) {return num_ref_t::make(fmpz_poly_q_numref(p._polyq()));} template static den_ref_t den(P& p) {return num_ref_t::make(fmpz_poly_q_denref(p._polyq()));} template static num_srcref_t num(const P& p) {return num_srcref_t::make(fmpz_poly_q_numref(p._polyq()));} template static den_srcref_t den(const P& p) {return num_srcref_t::make(fmpz_poly_q_denref(p._polyq()));} }; struct fmpz_poly_q_data { fmpz_poly_q_t inner; typedef fmpz_poly_q_t& data_ref_t; typedef const fmpz_poly_q_t& data_srcref_t; fmpz_poly_q_data() {fmpz_poly_q_init(inner);} ~fmpz_poly_q_data() {fmpz_poly_q_clear(inner);} fmpz_poly_q_data(const fmpz_poly_q_data& o) { fmpz_poly_q_init(inner); fmpz_poly_q_set(inner, o.inner); } fmpz_poly_q_data(fmpz_poly_qxx_srcref r) { fmpz_poly_q_init(inner); fmpz_poly_q_set(inner, r._polyq()); } fmpz_poly_q_data(const char* str) { fmpz_poly_q_init(inner); execution_check(!fmpz_poly_q_set_str(inner, str), "construct from string", "fmpz_poly_qxx"); } }; } // detail namespace rules { #define FMPZ_POLY_QXX_COND_S FLINTXX_COND_S(fmpz_poly_qxx) #define FMPZ_POLY_QXX_COND_T FLINTXX_COND_T(fmpz_poly_qxx) FLINTXX_DEFINE_TO_STR(fmpz_poly_qxx, fmpz_poly_q_get_str(from._polyq())) FLINTXX_DEFINE_SWAP(fmpz_poly_qxx, fmpz_poly_q_swap(e1._polyq(), e2._polyq())) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLY_QXX_COND_T, FMPZ_POLY_QXX_COND_S, fmpz_poly_q_set(to._polyq(), from._polyq())) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLY_QXX_COND_T, traits::fits_into_slong, fmpz_poly_q_set_si(to._polyq(), from)) FLINTXX_DEFINE_ASSIGN_STR(fmpz_poly_qxx, execution_check( !fmpz_poly_q_set_str(to._polyq(), from), "assign string", "fmpz_poly_qxx")) FLINT_DEFINE_PRINT_COND(FMPZ_POLY_QXX_COND_S, fmpz_poly_q_print(from._polyq())) FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPZ_POLY_QXX_COND_S, const char*, fmpz_poly_q_print_pretty(from._polyq(), extra)) FLINTXX_DEFINE_EQUALS(fmpz_poly_qxx, fmpz_poly_q_equal(e1._polyq(), e2._polyq())) FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, fmpz_poly_q_neg(to._polyq(), from._polyq())) FLINT_DEFINE_UNARY_EXPR_COND(inv_op, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, fmpz_poly_q_inv(to._polyq(), from._polyq())) FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, FMPZ_POLY_QXX_COND_S, fmpz_poly_q_add(to._polyq(), e1._polyq(), e2._polyq())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, FMPZ_POLY_QXX_COND_S, fmpz_poly_q_sub(to._polyq(), e1._polyq(), e2._polyq())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, traits::fits_into_slong, fmpz_poly_q_scalar_mul_si(to._polyq(), e1._polyq(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, traits::fits_into_slong, fmpz_poly_q_scalar_div_si(to._polyq(), e1._polyq(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, FMPZ_POLY_QXX_COND_S, fmpz_poly_q_mul(to._polyq(), e1._polyq(), e2._polyq())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, FMPZ_POLY_QXX_COND_S, fmpz_poly_q_div(to._polyq(), e1._polyq(), e2._polyq())) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, traits::is_unsigned_integer, fmpz_poly_q_pow(to._polyq(), e1._polyq(), e2)) FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, fmpz_poly_q_derivative(to._polyq(), from._polyq())) FLINT_DEFINE_UNARY_EXPR_COND(fmpz_poly_qxx_num_op, fmpz_polyxx, FMPZ_POLY_QXX_COND_S, fmpz_poly_set(to._poly(), fmpz_poly_q_numref(from._polyq()))) FLINT_DEFINE_UNARY_EXPR_COND(fmpz_poly_qxx_den_op, fmpz_polyxx, FMPZ_POLY_QXX_COND_S, fmpz_poly_set(to._poly(), fmpz_poly_q_denref(from._polyq()))) // XXX these should really be in fmpz_poly_q.h ... #if 0 FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, FMPZXX_COND_S, to.numref() = e1.numref()*e2;to.denref() = e1.denref();to.canonicalise()) FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, FMPZXX_COND_S, to.denref() = e1.denref()*e2;to.numref() = e1.numref();to.canonicalise()) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, FMPQXX_COND_S, to.numref() = e1.numref()*e2.num();to.denref() = e1.denref()*e2.den(); to.canonicalise()) FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpz_poly_qxx, FMPZ_POLY_QXX_COND_S, FMPQXX_COND_S, to.numref() = e1.numref()*e2.den();to.denref() = e1.denref()*e2.num(); to.canonicalise()) #endif } // rules // NB: addmul is not actually optimised currently } // flint #endif flint2-2.8.4/fmpz_polyxx.h000066400000000000000000001066421414523752600155150ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_POLYXX_H #define FMPZ_POLYXX_H #include #include #include "flint.h" #include "fmpz_poly.h" #include "fmpzxx.h" #include "fmpz_vecxx.h" #include "flintxx/expression.h" #include "flintxx/flint_classes.h" #include "flintxx/flint_exception.h" #include "flintxx/frandxx.h" #include "flintxx/ltuple.h" #include "flintxx/traits.h" #include "flintxx/traits_fwd.h" // TODO exhibit this as a specialisation of a generic poly // TODO newton basis? // TODO power series class? // TODO input // TODO addmul // TODO more hensel lifting? namespace flint { // function "declarations" FLINT_DEFINE_UNOP(sqr_karatsuba) FLINT_DEFINE_UNOP(sqrt_classical) FLINT_DEFINE_BINOP(evaluate_divconquer) FLINT_DEFINE_BINOP(evaluate_horner) FLINT_DEFINE_BINOP(gcd_heuristic) FLINT_DEFINE_BINOP(gcd_modular) FLINT_DEFINE_BINOP(gcd_subresultant) FLINT_DEFINE_BINOP(mul_karatsuba) FLINT_DEFINE_BINOP(mulmid_classical) FLINT_DEFINE_BINOP(mul_SS) FLINT_DEFINE_BINOP(divides) FLINT_DEFINE_BINOP(pow_addchains) FLINT_DEFINE_BINOP(pow_binomial) FLINT_DEFINE_BINOP(pow_multinomial) FLINT_DEFINE_BINOP(pseudo_div) FLINT_DEFINE_BINOP(pseudo_divrem) FLINT_DEFINE_BINOP(pseudo_divrem_basecase) FLINT_DEFINE_BINOP(pseudo_divrem_cohen) FLINT_DEFINE_BINOP(pseudo_divrem_divconquer) FLINT_DEFINE_BINOP(pseudo_rem) FLINT_DEFINE_BINOP(pseudo_rem_cohen) FLINT_DEFINE_BINOP(sqrlow) FLINT_DEFINE_BINOP(sqrlow_classical) FLINT_DEFINE_BINOP(sqrlow_karatsuba_n) FLINT_DEFINE_BINOP(sqrlow_KS) FLINT_DEFINE_BINOP(taylor_shift_divconquer) FLINT_DEFINE_BINOP(xgcd_modular) FLINT_DEFINE_THREEARY(mulhigh_karatsuba_n) FLINT_DEFINE_THREEARY(mulhigh_n) FLINT_DEFINE_THREEARY(mullow_karatsuba_n) FLINT_DEFINE_THREEARY(mullow_SS) FLINT_DEFINE_BINOP(fmpz_polyxx_interpolate) FLINT_DEFINE_UNOP(fmpz_polyxx_product_roots) FLINT_DEFINE_UNOP(fmpz_polyxx_lead) FLINT_DEFINE_BINOP(fmpz_polyxx_get_coeff) FLINT_DEFINE_BINOP(fmpz_polyxx_bit_unpack) FLINT_DEFINE_BINOP(fmpz_polyxx_bit_unpack_unsigned) FLINT_DEFINE_SEVENARY(hensel_lift) FLINT_DEFINE_SEVENARY(hensel_lift_without_inverse) FLINT_DEFINE_SIXARY(hensel_lift_only_inverse) namespace detail { template struct fmpz_poly_traits { typedef FLINT_UNOP_BUILD_RETTYPE( fmpz_polyxx_lead, fmpzxx, Poly) lead_ref_t; typedef lead_ref_t lead_srcref_t; static lead_ref_t lead(const Poly& p) {return fmpz_polyxx_lead(p);} template struct coeff { typedef FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_get_coeff, Poly, T) ref_t; typedef ref_t srcref_t; static ref_t get(const Poly& p, const T& t) {return fmpz_polyxx_get_coeff(p, t);} }; }; } template class fmpz_polyxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef detail::fmpz_poly_traits poly_traits_t; FLINTXX_DEFINE_BASICS(fmpz_polyxx_expression) FLINTXX_DEFINE_CTORS(fmpz_polyxx_expression) FLINTXX_DEFINE_C_REF(fmpz_polyxx_expression, fmpz_poly_struct, _poly) // static methods which only make sense with fmpz_polyxx static fmpz_polyxx_expression randtest(frandxx& state, slong len, flint_bitcnt_t bits) { fmpz_polyxx_expression res; fmpz_poly_randtest(res._poly(), state._data(), len, bits); return res; } static fmpz_polyxx_expression randtest_unsigned(frandxx& state, slong len, flint_bitcnt_t bits) { fmpz_polyxx_expression res; fmpz_poly_randtest_unsigned(res._poly(), state._data(), len, bits); return res; } static fmpz_polyxx_expression randtest_not_zero(frandxx& state, slong len, flint_bitcnt_t bits) { fmpz_polyxx_expression res; fmpz_poly_randtest_not_zero(res._poly(), state._data(), len, bits); return res; } template static FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_interpolate, Fmpz_vec1, Fmpz_vec2) interpolate(const Fmpz_vec1& xs, const Fmpz_vec2& ys) { return fmpz_polyxx_interpolate(xs, ys); } template static FLINT_UNOP_ENABLE_RETTYPE(fmpz_polyxx_product_roots, Fmpz_vec) product_roots(const Fmpz_vec& xs) { return fmpz_polyxx_product_roots(xs); } template static FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_bit_unpack, Arg1, Arg2) bit_unpack(const Arg1& a1, const Arg2& a2) { return fmpz_polyxx_bit_unpack(a1, a2); } template static FLINT_BINOP_ENABLE_RETTYPE(fmpz_polyxx_bit_unpack_unsigned, Arg1, Arg2) bit_unpack_unsigned(const Arg1& a1, const Arg2& a2) { return fmpz_polyxx_bit_unpack_unsigned(a1, a2); } template static fmpz_polyxx_expression from_ground(const T& t) { fmpz_polyxx_expression res; fmpzxx u; u = t; res.set_coeff(0, u); return res; } template static fmpz_polyxx_expression _lift(const Nmod_poly& poly) { fmpz_polyxx_expression res(poly.length()); fmpz_poly_set_nmod_poly(res._poly(), poly._poly()); return res; } template static fmpz_polyxx_expression lift(const Nmod_poly& poly, typename mp::enable_if >::type* = 0) { return _lift(poly.evaluate()); } template static fmpz_polyxx_expression _lift_unsigned(const Nmod_poly& poly) { fmpz_polyxx_expression res(poly.length()); fmpz_poly_set_nmod_poly_unsigned(res._poly(), poly.evaluate()._poly()); return res; } template static fmpz_polyxx_expression lift_unsigned(const Nmod_poly& poly, typename mp::enable_if >::type* = 0) { return _lift_unsigned(poly.evaluate()); } static fmpz_polyxx_expression zero() {return fmpz_polyxx_expression();} static fmpz_polyxx_expression one() { fmpz_polyxx_expression res; res.set_one(); return res; } // These only make sense with immediates void realloc(slong alloc) {fmpz_poly_realloc(_poly(), alloc);} void fit_length(slong len) {fmpz_poly_fit_length(_poly(), len);} void _normalise() {_fmpz_poly_normalise(_poly());} void _set_length(slong len) {_fmpz_poly_set_length(_poly(), len);} void zero_coeffs(slong i, slong j) {fmpz_poly_zero_coeffs(_poly(), i, j);} void set_zero() {fmpz_poly_zero(_poly());} void set_one() {fmpz_poly_one(_poly());} // The result of these are undefined if n is >= length // You also may have to call _normalise(). template typename poly_traits_t::template coeff::ref_t coeff(const T& n) { return poly_traits_t::template coeff::get(*this, n); } template typename poly_traits_t::template coeff::srcref_t coeff(const T& n) const { return poly_traits_t::template coeff::get(*this, n); } typename poly_traits_t::lead_ref_t lead() { return poly_traits_t::lead(*this); } typename poly_traits_t::lead_srcref_t lead() const { return poly_traits_t::lead(*this); } // These only make sense with target immediates template typename mp::enable_if >::type set_coeff(slong n, const Fmpz& x) { fmpz_poly_set_coeff_fmpz(_poly(), n, x.evaluate()._fmpz()); } template typename mp::enable_if >::type set_coeff(slong n, T x) { fmpz_poly_set_coeff_si(_poly(), n, x); } template typename mp::enable_if >::type set_coeff(slong n, T x) { fmpz_poly_set_coeff_ui(_poly(), n, x); } void truncate(slong n) {fmpz_poly_truncate(_poly(), n);} // These cause evaluation slong length() const {return fmpz_poly_length(this->evaluate()._poly());} slong degree() const {return fmpz_poly_degree(this->evaluate()._poly());} bool is_one() const {return fmpz_poly_is_one(this->evaluate()._poly());} bool is_zero() const {return fmpz_poly_is_zero(this->evaluate()._poly());} bool is_unit() const {return fmpz_poly_is_unit(this->evaluate()._poly());} ulong max_limbs() const {return fmpz_poly_max_limbs(this->evaluate()._poly());} slong max_bits() const {return fmpz_poly_max_bits(this->evaluate()._poly());} std::string pretty(const char* x) const { char* str = fmpz_poly_get_str_pretty(this->evaluate()._poly(), x); std::string res(str); flint_free(str); return res; } void signature(slong& r1, slong& r2) const { fmpz_poly_signature(&r1, &r2, this->evaluate()._poly()); } int read_pretty(char** x, FILE* f = stdin) { return fmpz_poly_fread_pretty(f, _poly(), x); } // lazy member forwarding FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval) FLINTXX_DEFINE_MEMBER_BINOP_(get_coeff, fmpz_polyxx_get_coeff) FLINTXX_DEFINE_MEMBER_BINOP(bit_pack) FLINTXX_DEFINE_MEMBER_BINOP(compose_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(compose_horner) FLINTXX_DEFINE_MEMBER_BINOP(div_basecase) FLINTXX_DEFINE_MEMBER_BINOP(div_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(divexact) FLINTXX_DEFINE_MEMBER_BINOP(divides) FLINTXX_DEFINE_MEMBER_BINOP(divrem) FLINTXX_DEFINE_MEMBER_BINOP(divrem_basecase) FLINTXX_DEFINE_MEMBER_BINOP(divrem_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(div_root) FLINTXX_DEFINE_MEMBER_BINOP(evaluate_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(evaluate_horner) FLINTXX_DEFINE_MEMBER_BINOP(fdiv_2exp) FLINTXX_DEFINE_MEMBER_BINOP(gcd) FLINTXX_DEFINE_MEMBER_BINOP(gcd_heuristic) FLINTXX_DEFINE_MEMBER_BINOP(gcd_modular) FLINTXX_DEFINE_MEMBER_BINOP(gcd_subresultant) FLINTXX_DEFINE_MEMBER_BINOP(inv_series) FLINTXX_DEFINE_MEMBER_BINOP(inv_series_newton) FLINTXX_DEFINE_MEMBER_BINOP(lcm) FLINTXX_DEFINE_MEMBER_BINOP(mul_2exp) FLINTXX_DEFINE_MEMBER_BINOP(mul_classical) FLINTXX_DEFINE_MEMBER_BINOP(mul_karatsuba) FLINTXX_DEFINE_MEMBER_BINOP(mul_KS) FLINTXX_DEFINE_MEMBER_BINOP(mulmid_classical) FLINTXX_DEFINE_MEMBER_BINOP(mul_SS) FLINTXX_DEFINE_MEMBER_BINOP(shift_left) FLINTXX_DEFINE_MEMBER_BINOP(shift_right) FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_BINOP(pow_addchains) FLINTXX_DEFINE_MEMBER_BINOP(pow_binexp) FLINTXX_DEFINE_MEMBER_BINOP(pow_binomial) FLINTXX_DEFINE_MEMBER_BINOP(pow_multinomial) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_div) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_divrem) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_divrem_basecase) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_divrem_cohen) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_divrem_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_rem) FLINTXX_DEFINE_MEMBER_BINOP(pseudo_rem_cohen) FLINTXX_DEFINE_MEMBER_BINOP(resultant) FLINTXX_DEFINE_MEMBER_BINOP(reverse) FLINTXX_DEFINE_MEMBER_BINOP(revert_series) FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange) FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange_fast) FLINTXX_DEFINE_MEMBER_BINOP(revert_series_newton) FLINTXX_DEFINE_MEMBER_BINOP(smod) FLINTXX_DEFINE_MEMBER_BINOP(sqrlow) FLINTXX_DEFINE_MEMBER_BINOP(sqrlow_classical) FLINTXX_DEFINE_MEMBER_BINOP(sqrlow_karatsuba_n) FLINTXX_DEFINE_MEMBER_BINOP(sqrlow_KS) FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift) FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift_horner) FLINTXX_DEFINE_MEMBER_BINOP(tdiv) FLINTXX_DEFINE_MEMBER_BINOP(tdiv_2exp) FLINTXX_DEFINE_MEMBER_BINOP(xgcd) FLINTXX_DEFINE_MEMBER_BINOP(xgcd_modular) FLINTXX_DEFINE_MEMBER_UNOP(derivative) FLINTXX_DEFINE_MEMBER_UNOP(primitive_part) FLINTXX_DEFINE_MEMBER_UNOP(sqr) FLINTXX_DEFINE_MEMBER_UNOP(sqr_classical) FLINTXX_DEFINE_MEMBER_UNOP(sqr_karatsuba) FLINTXX_DEFINE_MEMBER_UNOP(sqr_KS) FLINTXX_DEFINE_MEMBER_UNOP(sqrt) FLINTXX_DEFINE_MEMBER_UNOP(sqrt_classical) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, bound_roots) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, twonorm) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, content) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(fmpzxx, height) FLINTXX_DEFINE_MEMBER_3OP(compose_series) FLINTXX_DEFINE_MEMBER_3OP(compose_series_brent_kung) FLINTXX_DEFINE_MEMBER_3OP(compose_series_horner) FLINTXX_DEFINE_MEMBER_3OP(div_series) FLINTXX_DEFINE_MEMBER_3OP(mulhigh_classical) FLINTXX_DEFINE_MEMBER_3OP(mulhigh_karatsuba_n) FLINTXX_DEFINE_MEMBER_3OP(mulhigh_n) FLINTXX_DEFINE_MEMBER_3OP(mullow) FLINTXX_DEFINE_MEMBER_3OP(mullow_classical) FLINTXX_DEFINE_MEMBER_3OP(mullow_karatsuba_n) FLINTXX_DEFINE_MEMBER_3OP(mullow_KS) FLINTXX_DEFINE_MEMBER_3OP(mullow_SS) FLINTXX_DEFINE_MEMBER_3OP(pow_trunc) FLINTXX_DEFINE_MEMBER_4OP(CRT) }; namespace detail { struct fmpz_poly_data; } typedef fmpz_polyxx_expression fmpz_polyxx; typedef fmpz_polyxx_expression > fmpz_polyxx_ref; typedef fmpz_polyxx_expression > fmpz_polyxx_srcref; namespace detail { template<> struct fmpz_poly_traits { typedef fmpzxx_srcref lead_srcref_t; typedef fmpzxx_srcref lead_ref_t; template static lead_srcref_t lead(const P& p) {return lead_srcref_t::make(fmpz_poly_lead(p._poly()));} template struct coeff { typedef typename mp::enable_if< traits::is_integer, fmpzxx_srcref>::type ref_t; typedef ref_t srcref_t; template static srcref_t get(const P& p, const T& n) {return srcref_t::make(fmpz_poly_coeff_ptr(p._poly(), n));} }; }; template<> struct fmpz_poly_traits { typedef fmpzxx_ref lead_ref_t; typedef fmpzxx_ref lead_srcref_t; template static lead_ref_t lead(P p) {return lead_ref_t::make(fmpz_poly_lead(p._poly()));} template struct coeff { typedef fmpzxx_ref ref_t; typedef fmpzxx_ref srcref_t; template static ref_t get(P p, const T& n) {return ref_t::make(fmpz_poly_get_coeff_ptr(p._poly(), n));} }; }; template<> struct fmpz_poly_traits { typedef fmpzxx_ref lead_ref_t; typedef fmpzxx_srcref lead_srcref_t; template static lead_ref_t lead(P& p) {return lead_ref_t::make(fmpz_poly_lead(p._poly()));} template static lead_srcref_t lead(const P& p) {return lead_srcref_t::make(fmpz_poly_lead(p._poly()));} template struct coeff { typedef fmpzxx_ref ref_t; typedef fmpzxx_srcref srcref_t; template static ref_t get(P& p, const T& n) {return ref_t::make(fmpz_poly_get_coeff_ptr(p._poly(), n));} template static srcref_t get(const P& p, const T& n) {return srcref_t::make(fmpz_poly_get_coeff_ptr(p._poly(), n));} }; }; struct fmpz_poly_data { fmpz_poly_t inner; typedef fmpz_poly_t& data_ref_t; typedef const fmpz_poly_t& data_srcref_t; fmpz_poly_data() {fmpz_poly_init(inner);} ~fmpz_poly_data() {fmpz_poly_clear(inner);} fmpz_poly_data(const fmpz_poly_data& o) { fmpz_poly_init(inner); fmpz_poly_set(inner, o.inner); } fmpz_poly_data(fmpz_polyxx_srcref r) { fmpz_poly_init(inner); fmpz_poly_set(inner, r._poly()); } fmpz_poly_data(slong alloc) { fmpz_poly_init2(inner, alloc); } fmpz_poly_data(const char* str) { fmpz_poly_init(inner); execution_check(!fmpz_poly_set_str(inner, str), "construct from string", "fmpz_polyxx"); } }; } // detail namespace traits { template struct is_fmpz_polyxx : mp::or_< traits::is_T_expr, flint_classes::is_source > { }; } // traits namespace mp { template struct all_fmpz_polyxx : mp::and_, all_fmpz_polyxx > { }; template struct all_fmpz_polyxx : traits::is_fmpz_polyxx { }; template struct enable_all_fmpz_polyxx : mp::enable_if, Out> { }; } // mp namespace rules { #define FMPZ_POLYXX_COND_S FLINTXX_COND_S(fmpz_polyxx) #define FMPZ_POLYXX_COND_T FLINTXX_COND_T(fmpz_polyxx) FLINTXX_DEFINE_EQUALS(fmpz_polyxx, fmpz_poly_equal(e1._poly(), e2._poly())) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLYXX_COND_T, FMPZ_POLYXX_COND_S, fmpz_poly_set(to._poly(), from._poly())) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLYXX_COND_T, traits::is_signed_integer, fmpz_poly_set_si(to._poly(), from)) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLYXX_COND_T, traits::is_unsigned_integer, fmpz_poly_set_ui(to._poly(), from)) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_POLYXX_COND_T, FMPZXX_COND_S, fmpz_poly_set_fmpz(to._poly(), from._fmpz())) FLINTXX_DEFINE_ASSIGN_STR(fmpz_polyxx, execution_check( !fmpz_poly_set_str(to._poly(), from), "assign string", "fmpz_polyxx")) FLINT_DEFINE_PRINT_COND(FMPZ_POLYXX_COND_S, fmpz_poly_fprint(to, from._poly())) FLINT_DEFINE_PRINT_PRETTY_COND_2(FMPZ_POLYXX_COND_S, const char*, fmpz_poly_fprint_pretty(to, from._poly(), extra)) FLINT_DEFINE_READ_COND(FMPZ_POLYXX_COND_T, fmpz_poly_fread(from, to._poly())) FLINTXX_DEFINE_TO_STR(fmpz_polyxx, fmpz_poly_get_str(from._poly())) FLINTXX_DEFINE_SWAP(fmpz_polyxx, fmpz_poly_swap(e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(reverse_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::fits_into_slong, fmpz_poly_reverse(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_add(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_sub(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_neg(to._poly(), from._poly())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_scalar_mul_fmpz(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_signed_integer, fmpz_poly_scalar_mul_si(to._poly(), e1._poly(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, fmpz_poly_scalar_mul_ui(to._poly(), e1._poly(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(mul_2exp_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, fmpz_poly_scalar_mul_2exp(to._poly(), e1._poly(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(divided_by, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_scalar_fdiv_fmpz(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, fmpz_poly_scalar_fdiv_ui(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_signed_integer, fmpz_poly_scalar_fdiv_si(to._poly(), e1._poly(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(fdiv_2exp_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, fmpz_poly_scalar_fdiv_2exp(to._poly(), e1._poly(), e2)) #define FMPZ_POLYXX_DEFINE_SCALAR_DIVFUNCS(name) \ FLINT_DEFINE_CBINARY_EXPR_COND2(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, FMPZXX_COND_S, \ fmpz_poly_scalar_##name##_fmpz(to._poly(), e1._poly(), e2._fmpz())) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, \ fmpz_poly_scalar_##name##_ui(to._poly(), e1._poly(), e2)) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, traits::is_signed_integer, \ fmpz_poly_scalar_##name##_si(to._poly(), e1._poly(), e2)) FMPZ_POLYXX_DEFINE_SCALAR_DIVFUNCS(tdiv) FMPZ_POLYXX_DEFINE_SCALAR_DIVFUNCS(divexact) FLINT_DEFINE_CBINARY_EXPR_COND2(tdiv_2exp_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, fmpz_poly_scalar_tdiv_2exp(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_scalar_mod_fmpz(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(smod_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_scalar_smod_fmpz(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(bit_pack_op, fmpzxx, FMPZ_POLYXX_COND_S, traits::fits_into_flint_bitcnt_t, fmpz_poly_bit_pack(to._fmpz(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_polyxx_bit_unpack_op, fmpz_polyxx, FMPZXX_COND_S, traits::fits_into_flint_bitcnt_t, fmpz_poly_bit_unpack(to._poly(), e1._fmpz(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_polyxx_bit_unpack_unsigned_op, fmpz_polyxx, FMPZXX_COND_S, traits::fits_into_flint_bitcnt_t, fmpz_poly_bit_unpack_unsigned(to._poly(), e1._fmpz(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(times, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_mul(to._poly(), e1._poly(), e2._poly())) #define FMPZ_POLYXX_DEFINE_MUL(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, \ fmpz_poly_##name(to._poly(), e1._poly(), e2._poly())) FMPZ_POLYXX_DEFINE_MUL(mul_classical) FMPZ_POLYXX_DEFINE_MUL(mulmid_classical) FMPZ_POLYXX_DEFINE_MUL(mul_karatsuba) FMPZ_POLYXX_DEFINE_MUL(mul_SS) FMPZ_POLYXX_DEFINE_MUL(mul_KS) FLINT_DEFINE_UNARY_EXPR_COND(sqr_KS_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_sqr_KS(to._poly(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_karatsuba_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_sqr_karatsuba(to._poly(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_classical_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_sqr_classical(to._poly(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_sqr(to._poly(), from._poly())) #define FMPZ_POLYXX_DEFINE_SQRLOW(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, traits::fits_into_slong, \ fmpz_poly_##name(to._poly(), e1._poly(), e2)) FMPZ_POLYXX_DEFINE_SQRLOW(sqrlow_KS) FMPZ_POLYXX_DEFINE_SQRLOW(sqrlow_karatsuba_n) FMPZ_POLYXX_DEFINE_SQRLOW(sqrlow_classical) FMPZ_POLYXX_DEFINE_SQRLOW(sqrlow) #define FMPZ_POLYXX_DEFINE_POW(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, \ fmpz_poly_##name(to._poly(), e1._poly(), e2)) FMPZ_POLYXX_DEFINE_POW(pow_multinomial) FMPZ_POLYXX_DEFINE_POW(pow_binomial) FMPZ_POLYXX_DEFINE_POW(pow_addchains) FMPZ_POLYXX_DEFINE_POW(pow_binexp) FMPZ_POLYXX_DEFINE_POW(pow) FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::fits_into_slong, fmpz_poly_shift_left(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::fits_into_slong, fmpz_poly_shift_right(to._poly(), e1._poly(), e2)) FLINT_DEFINE_UNARY_EXPR_COND(height_op, fmpzxx, FMPZ_POLYXX_COND_S, fmpz_poly_height(to._fmpz(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(twonorm_op, fmpzxx, FMPZ_POLYXX_COND_S, fmpz_poly_2norm(to._fmpz(), from._poly())) FMPZ_POLYXX_DEFINE_MUL(gcd) FMPZ_POLYXX_DEFINE_MUL(gcd_subresultant) FMPZ_POLYXX_DEFINE_MUL(gcd_heuristic) FMPZ_POLYXX_DEFINE_MUL(gcd_modular) FMPZ_POLYXX_DEFINE_MUL(lcm) FLINT_DEFINE_BINARY_EXPR_COND2(resultant_op, fmpzxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_resultant(to._fmpz(), e1._poly(), e2._poly())) FLINT_DEFINE_UNARY_EXPR_COND(content_op, fmpzxx, FMPZ_POLYXX_COND_S, fmpz_poly_content(to._fmpz(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(primitive_part_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_primitive_part(to._poly(), from._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(div_basecase_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_div_basecase(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(div_divconquer_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_div_divconquer(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_div(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(rem_basecase_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_rem_basecase(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_rem(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(div_root_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_div_root(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_newton_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::fits_into_slong, fmpz_poly_inv_series_newton(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::fits_into_slong, fmpz_poly_inv_series(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(pseudo_rem_cohen_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_pseudo_rem_cohen(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, fmpz_poly_derivative(to._poly(), from._poly())) FMPZ_POLYXX_DEFINE_MUL(compose) FMPZ_POLYXX_DEFINE_MUL(compose_horner) FMPZ_POLYXX_DEFINE_MUL(compose_divconquer) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpzxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_evaluate_fmpz(to._fmpz(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_divconquer_op, fmpzxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_evaluate_divconquer_fmpz(to._fmpz(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_horner_op, fmpzxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_evaluate_horner_fmpz(to._fmpz(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, fmpz_vecxx, FMPZ_POLYXX_COND_S, FMPZ_VECXX_COND_S, fmpz_poly_evaluate_fmpz_vec(to._data().array, e1._poly(), e2._data().array, e2.size())) FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_polyxx_interpolate_op, fmpz_polyxx, FMPZ_VECXX_COND_S, FMPZ_VECXX_COND_S, fmpz_poly_interpolate_fmpz_vec(to._poly(), e1._data().array, e2._data().array, e2.size())) FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_horner_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_taylor_shift_horner(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_divconquer_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_taylor_shift_divconquer(to._poly(), e1._poly(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, fmpz_poly_taylor_shift(to._poly(), e1._poly(), e2._fmpz())) FMPZ_POLYXX_DEFINE_SQRLOW(revert_series) FMPZ_POLYXX_DEFINE_SQRLOW(revert_series_newton) FMPZ_POLYXX_DEFINE_SQRLOW(revert_series_lagrange_fast) FMPZ_POLYXX_DEFINE_SQRLOW(revert_series_lagrange) FLINT_DEFINE_UNARY_EXPR_COND(sqrt_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, execution_check(fmpz_poly_sqrt(to._poly(), from._poly()), "sqrt", "fmpz_polyxx")) FLINT_DEFINE_UNARY_EXPR_COND(sqrt_classical_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, execution_check(fmpz_poly_sqrt_classical(to._poly(), from._poly()), "sqrt_classical", "fmpz_polyxx")) FLINT_DEFINE_UNARY_EXPR_COND(fmpz_polyxx_product_roots_op, fmpz_polyxx, FMPZ_VECXX_COND_S, fmpz_poly_product_roots_fmpz_vec(to._poly(), from._data().array, from.size())) FLINT_DEFINE_BINARY_EXPR_COND2(fmpz_polyxx_get_coeff_op, fmpzxx, FMPZ_POLYXX_COND_S, traits::is_integer, fmpz_poly_get_coeff_fmpz(to._fmpz(), e1._poly(), e2)) FLINT_DEFINE_UNARY_EXPR_COND(fmpz_polyxx_lead_op, fmpzxx, FMPZ_POLYXX_COND_S, fmpz_set(to._fmpz(), fmpz_poly_lead(from._poly()))) FLINT_DEFINE_UNARY_EXPR_COND(bound_roots_op, fmpzxx, FMPZ_POLYXX_COND_S, fmpz_poly_bound_roots(to._fmpz(), from._poly())) namespace rdetail { typedef make_ltuple::type>::type fmpz_polyxx_pair; typedef make_ltuple::type>::type fmpzxx_fmpz_polyxx_pair; } // rdetail #define FMPZ_POLYXX_DEFINE_DIVREM(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, rdetail::fmpz_polyxx_pair, \ FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, \ fmpz_poly_##name(to.template get<0>()._poly(), to.template get<1>()._poly(), \ e1._poly(), e2._poly())) FMPZ_POLYXX_DEFINE_DIVREM(divrem_basecase) FMPZ_POLYXX_DEFINE_DIVREM(divrem_divconquer) FMPZ_POLYXX_DEFINE_DIVREM(divrem) FMPZ_POLYXX_DEFINE_DIVREM(pseudo_divrem_cohen) #define FMPZ_POLYXX_DEFINE_MULFUNC(name) \ FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, traits::fits_into_slong, \ fmpz_poly_##name(to._poly(), e1._poly(), e2._poly(), e3)) FMPZ_POLYXX_DEFINE_MULFUNC(mullow_classical) FMPZ_POLYXX_DEFINE_MULFUNC(mulhigh_classical) FMPZ_POLYXX_DEFINE_MULFUNC(mullow_karatsuba_n) FMPZ_POLYXX_DEFINE_MULFUNC(mulhigh_karatsuba_n) FMPZ_POLYXX_DEFINE_MULFUNC(mullow_KS) FMPZ_POLYXX_DEFINE_MULFUNC(mullow_SS) FMPZ_POLYXX_DEFINE_MULFUNC(mullow) FMPZ_POLYXX_DEFINE_MULFUNC(mulhigh_n) FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_op, rdetail::fmpzxx_fmpz_polyxx_pair, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_xgcd(to.template get<0>()._fmpz(), to.template get<1>()._poly(), to.template get<2>()._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_modular_op, rdetail::fmpzxx_fmpz_polyxx_pair, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_xgcd_modular(to.template get<0>()._fmpz(), to.template get<1>()._poly(), to.template get<2>()._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_op, fmpz_polyxx, FMPZ_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong, fmpz_poly_pow_trunc(to._poly(), e1._poly(), e2, e3)) #define FMPZ_POLYXX_DEFINE_SERIES(name) \ FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, fmpz_polyxx, \ FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, traits::fits_into_slong, \ fmpz_poly_##name(to._poly(), e1._poly(), e2._poly(), e3)) FMPZ_POLYXX_DEFINE_SERIES(div_series) FMPZ_POLYXX_DEFINE_SERIES(compose_series_brent_kung) FMPZ_POLYXX_DEFINE_SERIES(compose_series_horner) FMPZ_POLYXX_DEFINE_SERIES(compose_series) namespace rdetail { typedef make_ltuple::type>::type fmpz_polyxx_pair_ulong; typedef make_ltuple::type>::type fmpz_polyxx_ulong; typedef make_ltuple::type>::type bool_fmpz_polyxx; } #define FMPZ_POLYXX_DEFINE_PSEUDO_DIVREM(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, rdetail::fmpz_polyxx_pair_ulong, \ FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, \ fmpz_poly_##name(to.template get<0>()._poly(), to.template get<1>()._poly(), \ &to.template get<2>(), e1._poly(), e2._poly())) FMPZ_POLYXX_DEFINE_PSEUDO_DIVREM(pseudo_divrem_basecase) FMPZ_POLYXX_DEFINE_PSEUDO_DIVREM(pseudo_divrem_divconquer) FMPZ_POLYXX_DEFINE_PSEUDO_DIVREM(pseudo_divrem) FLINT_DEFINE_BINARY_EXPR_COND2(pseudo_div_op, rdetail::fmpz_polyxx_ulong, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_pseudo_div(to.template get<0>()._poly(), &to.template get<1>(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(pseudo_rem_op, rdetail::fmpz_polyxx_ulong, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, fmpz_poly_pseudo_rem(to.template get<0>()._poly(), &to.template get<1>(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(divides_op, rdetail::bool_fmpz_polyxx, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, to.template get<0> () = fmpz_poly_divides(to.template get<1>()._poly(), e1._poly(), e2._poly())) namespace rdetail { typedef make_ltuple::type>::type fmpz_polyxx_quadruple; } FLINT_DEFINE_SEVENARY_EXPR_COND7(hensel_lift_op, rdetail::fmpz_polyxx_quadruple, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_poly_hensel_lift(to.template get<0>()._poly(), to.template get<1>()._poly(), to.template get<2>()._poly(), to.template get<3>()._poly(), e1._poly(), e2._poly(), e3._poly(), e4._poly(), e5._poly(), e6._fmpz(), e7._fmpz())) FLINT_DEFINE_SEVENARY_EXPR_COND7(hensel_lift_without_inverse_op, rdetail::fmpz_polyxx_pair, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_poly_hensel_lift_without_inverse(to.template get<0>()._poly(), to.template get<1>()._poly(), e1._poly(), e2._poly(), e3._poly(), e4._poly(), e5._poly(), e6._fmpz(), e7._fmpz())) FLINT_DEFINE_SIXARY_EXPR_COND6(hensel_lift_only_inverse_op, rdetail::fmpz_polyxx_pair, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZ_POLYXX_COND_S, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_poly_hensel_lift_only_inverse(to.template get<0>()._poly(), to.template get<1>()._poly(), e1._poly(), e2._poly(), e3._poly(), e4._poly(), e5._fmpz(), e6._fmpz())) } // rules // immediate functions // TODO make lazy when we have nmod class template inline typename mp::enable_all_fmpz_polyxx::type evaluate_mod(const Poly& p, mp_limb_t x, mp_limb_t n) { return fmpz_poly_evaluate_mod(p.evaluate()._poly(), x, n); } template int read_pretty(Fmpz_poly& f, char** x, typename mp::enable_if >::type* = 0) { return f.read_pretty(x); } template int read_pretty(FILE* fi, Fmpz_poly& f, char** x, typename mp::enable_if >::type* = 0) { return f.read_pretty(x, fi); } } // flint #include "nmod_polyxx.h" // modular reconstruction code #include "fmpz_poly_factorxx.h" #endif flint2-2.8.4/fmpz_vec.h000066400000000000000000000244661414523752600147320ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FMPZ_VEC_INLINE static __inline__ #endif #include #include "fmpz.h" #include "flint.h" #include "mpf_vec.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 *******************************************************/ FLINT_DLL fmpz * _fmpz_vec_init(slong len); FLINT_DLL void _fmpz_vec_clear(fmpz * vec, slong len); /* Randomisation ***********************************************************/ FLINT_DLL void _fmpz_vec_randtest(fmpz * f, flint_rand_t state, slong len, flint_bitcnt_t bits); FLINT_DLL void _fmpz_vec_randtest_unsigned(fmpz * f, flint_rand_t state, slong len, flint_bitcnt_t bits); /* Norms *******************************************************************/ FLINT_DLL slong _fmpz_vec_max_bits(const fmpz * vec, slong len); FLINT_DLL slong _fmpz_vec_max_bits_ref(const fmpz * vec, slong len); FLINT_DLL void _fmpz_vec_sum_max_bits(slong * sumabs, slong * maxabs, const fmpz * coeffs, slong length); FLINT_DLL mp_size_t _fmpz_vec_max_limbs(const fmpz * vec, slong len); FLINT_DLL void _fmpz_vec_height(fmpz_t height, const fmpz * vec, slong len); FLINT_DLL slong _fmpz_vec_height_index(const fmpz * vec, slong len); /* Input and output ********************************************************/ FLINT_DLL int _fmpz_vec_fprint(FILE * file, const fmpz * vec, slong len); FMPZ_VEC_INLINE int _fmpz_vec_print(const fmpz * vec, slong len) { return _fmpz_vec_fprint(stdout, vec, len); } FLINT_DLL int _fmpz_vec_fread(FILE * file, fmpz ** vec, slong * len); FMPZ_VEC_INLINE int _fmpz_vec_read(fmpz ** vec, slong * len) { return _fmpz_vec_fread(stdin, vec, len); } /* Conversions *************************************************************/ FLINT_DLL void _fmpz_vec_set_nmod_vec(fmpz * res, mp_srcptr poly, slong len, nmod_t mod); FLINT_DLL void _fmpz_vec_get_nmod_vec(mp_ptr res, const fmpz * poly, slong len, nmod_t mod); FLINT_DLL slong _fmpz_vec_get_fft(mp_limb_t ** coeffs_f, const fmpz * coeffs_m, slong l, slong length); FLINT_DLL void _fmpz_vec_set_fft(fmpz * coeffs_m, slong length, const mp_ptr * coeffs_f, slong limbs, slong sign); FLINT_DLL slong _fmpz_vec_get_d_vec_2exp(double * appv, const fmpz * vec, slong len); FLINT_DLL void _fmpz_vec_get_mpf_vec(mpf * appv, const fmpz * vec, slong len); /* Assignment and basic manipulation ***************************************/ FLINT_DLL void _fmpz_vec_set(fmpz * vec1, const fmpz * vec2, slong len2); FLINT_DLL void _fmpz_vec_swap(fmpz * vec1, fmpz * vec2, slong len2); FLINT_DLL void _fmpz_vec_zero(fmpz * vec, slong len); FLINT_DLL void _fmpz_vec_neg(fmpz * vec1, const fmpz * vec2, slong len2); FLINT_DLL void _fmpz_vec_scalar_abs(fmpz * vec1, const fmpz * vec2, slong len2); /* Comparison **************************************************************/ FLINT_DLL int _fmpz_vec_equal(const fmpz * vec1, const fmpz * vec2, slong len); FLINT_DLL int _fmpz_vec_is_zero(const fmpz * vec, slong len); FLINT_DLL void _fmpz_vec_max(fmpz * vec1, const fmpz * vec2, const fmpz * vec3, slong len); FLINT_DLL void _fmpz_vec_max_inplace(fmpz * vec1, const fmpz * vec2, slong len); FLINT_DLL void _fmpz_vec_min(fmpz * vec1, const fmpz * vec2, const fmpz * vec3, slong len); FLINT_DLL void _fmpz_vec_min_inplace(fmpz * vec1, const fmpz * vec2, slong len); /* Sorting ******************************************************************/ FLINT_DLL void _fmpz_vec_sort(fmpz * vec, slong len); /* Addition ****************************************************************/ FLINT_DLL void _fmpz_vec_add(fmpz * res, const fmpz * vec1, const fmpz * vec2, slong len2); FLINT_DLL void _fmpz_vec_sub(fmpz * res, const fmpz * vec1, const fmpz * vec2, slong len2); /* Scalar multiplication and division **************************************/ FLINT_DLL void _fmpz_vec_scalar_mul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c); FLINT_DLL void _fmpz_vec_scalar_mul_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c); FLINT_DLL void _fmpz_vec_scalar_mul_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x); FLINT_DLL void _fmpz_vec_scalar_mul_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp); FLINT_DLL void _fmpz_vec_scalar_divexact_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x); FLINT_DLL void _fmpz_vec_scalar_divexact_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c); FLINT_DLL void _fmpz_vec_scalar_divexact_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c); FLINT_DLL void _fmpz_vec_scalar_fdiv_q_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t c); FLINT_DLL void _fmpz_vec_scalar_fdiv_q_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c); FLINT_DLL void _fmpz_vec_scalar_fdiv_q_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c); FLINT_DLL void _fmpz_vec_scalar_fdiv_q_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp); FLINT_DLL void _fmpz_vec_scalar_fdiv_r_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp); FLINT_DLL void _fmpz_vec_scalar_tdiv_q_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t c); FLINT_DLL void _fmpz_vec_scalar_tdiv_q_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c); FLINT_DLL void _fmpz_vec_scalar_tdiv_q_ui(fmpz * vec1, const fmpz * vec2, slong len2, ulong c); FLINT_DLL void _fmpz_vec_scalar_tdiv_q_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp); FLINT_DLL void _fmpz_vec_scalar_addmul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c); FLINT_DLL void _fmpz_vec_scalar_addmul_fmpz(fmpz * poly1, const fmpz * poly2, slong len2, const fmpz_t x); FLINT_DLL void _fmpz_vec_scalar_addmul_si_2exp(fmpz * vec1, const fmpz * vec2, slong len2, slong c, ulong exp); FLINT_DLL void _fmpz_vec_scalar_submul_si(fmpz * vec1, const fmpz * vec2, slong len2, slong c); FLINT_DLL void _fmpz_vec_scalar_submul_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x); FLINT_DLL void _fmpz_vec_scalar_submul_si_2exp(fmpz * vec1, const fmpz * vec2, slong len2, slong c, ulong exp); /* Vector sum and product **************************************************/ FLINT_DLL void _fmpz_vec_sum(fmpz_t res, const fmpz * vec, slong len); FLINT_DLL void _fmpz_vec_prod(fmpz_t res, const fmpz * vec, slong len); /* Reduction mod p **********************************************************/ FLINT_DLL void _fmpz_vec_scalar_mod_fmpz(fmpz *res, const fmpz *vec, slong len, const fmpz_t p); FLINT_DLL void _fmpz_vec_scalar_smod_fmpz(fmpz *res, const fmpz *vec, slong len, const fmpz_t p); /* Gaussian content ********************************************************/ FLINT_DLL void _fmpz_vec_content(fmpz_t res, const fmpz * vec, slong len); FLINT_DLL void _fmpz_vec_content_chained(fmpz_t res, const fmpz * vec, slong len, const fmpz_t inp); FLINT_DLL void _fmpz_vec_lcm(fmpz_t res, const fmpz * vec, slong len); /* Dot product *************************************************************/ FLINT_DLL void _fmpz_vec_dot(fmpz_t res, const fmpz * vec1, const fmpz * vec2, slong len2); FLINT_DLL void _fmpz_vec_dot_ptr(fmpz_t c, const fmpz * vec1, fmpz ** const vec2, slong offset, slong len); #ifdef __cplusplus } #endif #endif flint2-2.8.4/fmpz_vec/000077500000000000000000000000001414523752600145455ustar00rootroot00000000000000flint2-2.8.4/fmpz_vec/add.c000066400000000000000000000011711414523752600154410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_vec/clear.c000066400000000000000000000011521414523752600157760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); } flint2-2.8.4/fmpz_vec/content.c000066400000000000000000000025601414523752600163660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_vec/content_chained.c000066400000000000000000000023711414523752600200410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fmpz_vec/dot.c000066400000000000000000000012441414523752600155000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" void _fmpz_vec_dot(fmpz_t res, const fmpz * vec1, const fmpz * vec2, slong len2) { slong i; fmpz_zero(res); for (i = 0; i < len2; i++) fmpz_addmul(res, vec1 + i, vec2 + i); } flint2-2.8.4/fmpz_vec/dot_ptr.c000066400000000000000000000014561414523752600163720ustar00rootroot00000000000000/* 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 2.1 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" 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); } flint2-2.8.4/fmpz_vec/equal.c000066400000000000000000000013041414523752600160160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_vec/fprint.c000066400000000000000000000025501414523752600162150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" /* 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, "%li", 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; } flint2-2.8.4/fmpz_vec/fread.c000066400000000000000000000027551414523752600160030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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_printf("Exception (_fmpz_vec_fread). Length does not fit into a slong.\n"); flint_abort(); } 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; } flint2-2.8.4/fmpz_vec/get_d_vec_2exp.c000066400000000000000000000016101414523752600175640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_vec.h" slong _fmpz_vec_get_d_vec_2exp(double *appv, const fmpz * vec, slong len) { slong *exp, i, maxexp = 0L; exp = (slong *) flint_malloc(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] = ldexp(appv[i], exp[i] - maxexp); flint_free(exp); return maxexp; } flint2-2.8.4/fmpz_vec/get_fft.c000066400000000000000000000045031414523752600163310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fft.h" slong _fmpz_vec_get_fft(mp_limb_t ** coeffs_f, const fmpz * coeffs_m, slong l, slong length) { slong size_f = l + 1; mp_limb_t * coeff; mp_limb_t mask = WORD(-1); slong bits = 0, limbs = 0, size_j, i, c; int sign = 1, signed_c; for (i = 0; i < length; i++, coeffs_m++) { c = *coeffs_m; 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; } else /* coeff is an mpz_t */ { __mpz_struct * mpz_ptr = COEFF_TO_PTR(c); size_j = mpz_ptr->_mp_size; if (size_j < 0) { signed_c = 1; size_j = -size_j; } coeff = mpz_ptr->_mp_d; } if (signed_c) sign = -1; if (size_j > limbs + 1) /* coeff is at least 1 limb bigger */ { limbs = size_j - 1; bits = FLINT_BIT_COUNT(coeff[size_j - 1]); if (bits == FLINT_BITS) mask = WORD(0); else mask = WORD(-1) - ((WORD(1)<. */ #include "fmpz_vec.h" void _fmpz_vec_get_mpf_vec(mpf * appv, const fmpz * vec, slong len) { slong i; for (i = 0; i < len; i++) { fmpz_get_mpf(appv + i, vec + i); } } flint2-2.8.4/fmpz_vec/get_nmod_vec.c000066400000000000000000000012651414523752600173460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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_fdiv_ui(poly + i, mod.n); } flint2-2.8.4/fmpz_vec/height.c000066400000000000000000000012551414523752600161640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_vec/height_index.c000066400000000000000000000040601414523752600173500ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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 * mpz_ptr = COEFF_TO_PTR(c); max_d = mpz_ptr->_mp_d; max_mpz_limbs = mpz_ptr->_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 * mpz_ptr = COEFF_TO_PTR(c); mpz_limbs = mpz_ptr->_mp_size; mpz_limbs = FLINT_ABS(mpz_limbs); if (mpz_limbs > max_mpz_limbs || ((mpz_limbs == max_mpz_limbs) && (mpn_cmp(mpz_ptr->_mp_d, max_d, max_mpz_limbs) > 0))) { max_d = mpz_ptr->_mp_d; max_mpz_limbs = mpz_limbs; max_i = i; } } } return max_i; } } flint2-2.8.4/fmpz_vec/init.c000066400000000000000000000010671414523752600156600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" fmpz * _fmpz_vec_init(slong len) { return (fmpz *) flint_calloc(len, sizeof(fmpz)); } flint2-2.8.4/fmpz_vec/inlines.c000066400000000000000000000010601414523752600163470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FMPZ_VEC_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "fmpz_vec.h" flint2-2.8.4/fmpz_vec/is_zero.c000066400000000000000000000011641414523752600163650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_vec/lcm.c000066400000000000000000000012411414523752600154620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_vec/max.c000066400000000000000000000017101414523752600154750ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_vec/max_bits.c000066400000000000000000000032611414523752600165210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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)); } flint2-2.8.4/fmpz_vec/max_bits_ref.c000066400000000000000000000014271414523752600173570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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; } flint2-2.8.4/fmpz_vec/max_limbs.c000066400000000000000000000013351414523752600166660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fmpz_vec/min.c000066400000000000000000000017101414523752600154730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_vec/neg.c000066400000000000000000000011361414523752600154630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_vec/prod.c000066400000000000000000000020321414523752600156520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fmpz_vec/randtest.c000066400000000000000000000032051414523752600165350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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); } } } flint2-2.8.4/fmpz_vec/scalar_abs.c000066400000000000000000000011451414523752600170040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/fmpz_vec/scalar_addmul_fmpz.c000066400000000000000000000020201414523752600205320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } } flint2-2.8.4/fmpz_vec/scalar_addmul_si.c000066400000000000000000000013661414523752600202050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_addmul_si_2exp.c000066400000000000000000000034461414523752600211440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_divexact_fmpz.c000066400000000000000000000017751414523752600211130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } } flint2-2.8.4/fmpz_vec/scalar_divexact_si.c000066400000000000000000000012531414523752600205410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_divexact_ui.c000066400000000000000000000013101414523752600205350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_fdiv_q_2exp.c000066400000000000000000000013141414523752600204430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_fdiv_q_fmpz.c000066400000000000000000000013121414523752600205370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_fdiv_q_si.c000066400000000000000000000012471414523752600202050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_fdiv_q_ui.c000066400000000000000000000012471414523752600202070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_fdiv_r_2exp.c000066400000000000000000000013231414523752600204440ustar00rootroot00000000000000/* Copyright (C) 2010 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_mod_fmpz.c000066400000000000000000000011751414523752600200550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_mul_2exp.c000066400000000000000000000012001414523752600177620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_mul_fmpz.c000066400000000000000000000020131414523752600200630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } } flint2-2.8.4/fmpz_vec/scalar_mul_si.c000066400000000000000000000011671414523752600175330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_mul_ui.c000066400000000000000000000011671414523752600175350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_smod_fmpz.c000066400000000000000000000015301414523752600202330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_submul_fmpz.c000066400000000000000000000020561414523752600206040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } } flint2-2.8.4/fmpz_vec/scalar_submul_si.c000066400000000000000000000014401414523752600202370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_submul_si_2exp.c000066400000000000000000000035211414523752600211770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_tdiv_q_2exp.c000066400000000000000000000012121414523752600204560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_tdiv_q_fmpz.c000066400000000000000000000012461414523752600205630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_tdiv_q_si.c000066400000000000000000000012031414523752600202130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/scalar_tdiv_q_ui.c000066400000000000000000000012031414523752600202150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" 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); } flint2-2.8.4/fmpz_vec/set.c000066400000000000000000000012101414523752600154760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fmpz_vec/set_fft.c000066400000000000000000000043001414523752600163400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fft.h" void _fmpz_vec_set_fft(fmpz * coeffs_m, slong length, const mp_ptr * coeffs_f, slong limbs, slong sign) { slong i, size; mp_limb_t * data; __mpz_struct * mpz_ptr; if (sign) { for (i = 0; i < length; i++) { mpz_ptr = _fmpz_promote(coeffs_m); data = FLINT_MPZ_REALLOC(mpz_ptr, limbs); if ((coeffs_f[i][limbs - 1] >> (FLINT_BITS - 1)) || coeffs_f[i][limbs]) { mpn_neg_n(data, coeffs_f[i], limbs); mpn_add_1(data, data, limbs, WORD(1)); size = limbs; while ((size) && (data[size - 1] == 0)) size--; /* normalise */ mpz_ptr->_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 */ mpz_ptr->_mp_size = size; if (size <= 1) _fmpz_demote_val(coeffs_m); /* coefficient may be small */ } coeffs_m++; } } else { for (i = 0; i < length; i++) { mpz_ptr = _fmpz_promote(coeffs_m); data = FLINT_MPZ_REALLOC(mpz_ptr, limbs); flint_mpn_copyi(data, coeffs_f[i], limbs); size = limbs; while ((size) && (data[size - 1] == WORD(0))) size--; /* normalise */ mpz_ptr->_mp_size = size; if (size <= 1) _fmpz_demote_val(coeffs_m); /* coefficient may be small */ coeffs_m++; } } } flint2-2.8.4/fmpz_vec/set_nmod_vec.c000066400000000000000000000012651414523752600173620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_vec/sort.c000066400000000000000000000014071414523752600157020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_vec/sub.c000066400000000000000000000011711414523752600155020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_vec/sum.c000066400000000000000000000014431414523752600155170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fmpz_vec/sum_max_bits.c000066400000000000000000000033251414523752600174060ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fmpz_vec/swap.c000066400000000000000000000011401414523752600156570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_vec/test/000077500000000000000000000000001414523752600155245ustar00rootroot00000000000000flint2-2.8.4/fmpz_vec/test/t-add.c000066400000000000000000000044551414523752600166710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); /* 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-content.c000066400000000000000000000032161414523752600176050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("content...."); fflush(stdout); /* 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"); abort(); } fmpz_clear(a); fmpz_clear(c); fmpz_clear(d); _fmpz_vec_clear(f, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-dot.c000066400000000000000000000042151414523752600167210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("dot...."); fflush(stdout); /* 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(res1); fmpz_clear(res2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-get_d_vec_2exp.c000066400000000000000000000037221414523752600210120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "d_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("get_d_vec_2exp...."); fflush(stdout); 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"); abort(); } _fmpz_vec_clear(a, len); _d_vec_clear(d1); _d_vec_clear(d2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-get_mpf_vec.c000066400000000000000000000032221414523752600204060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpf_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("get_mpf_vec...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { int result; fmpz *a; mpf *d1, *d2; slong bits, len; len = n_randint(state, 100); a = _fmpz_vec_init(len); d1 = _mpf_vec_init(len, 200); d2 = _mpf_vec_init(len, 200); bits = 1 + n_randint(state, 200); _fmpz_vec_randtest(a, state, len, bits); _fmpz_vec_get_mpf_vec(d1, a, len / 2); _fmpz_vec_get_mpf_vec(d1 + len / 2, a + len / 2, (len + 1) / 2); _fmpz_vec_get_mpf_vec(d2, a, len); result = (_mpf_vec_equal(d1, d2, len)); if (!result) { flint_printf("FAIL:\n"); _fmpz_vec_print(a, len), flint_printf("\n"); abort(); } _fmpz_vec_clear(a, len); _mpf_vec_clear(d1, len); _mpf_vec_clear(d2, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-get_set_fft.c000066400000000000000000000062371414523752600204320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fft.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get/set_fft...."); fflush(stdout); /* 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); bt = _fmpz_vec_get_fft(ii, a, limbs, 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"); 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); bt = _fmpz_vec_get_fft(ii, a, limbs, 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"); abort(); } flint_free(ii); _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-get_set_nmod_vec.c000066400000000000000000000036441414523752600214440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include "nmod_vec.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get/set_nmod_vec...."); fflush(stdout); /* 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _nmod_vec_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-height.c000066400000000000000000000030501414523752600173770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("height...."); fflush(stdout); 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"); abort(); } fmpz_clear(h); _fmpz_vec_clear(a, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-height_index.c000066400000000000000000000030301414523752600205640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.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; } int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("height_index...."); fflush(stdout); 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); abort(); } _fmpz_vec_clear(a, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-init_clear.c000066400000000000000000000017471414523752600202530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-is_zero.c000066400000000000000000000034361414523752600176110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_zero...."); fflush(stdout); /* 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"); 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"); abort(); } _fmpz_vec_clear(a, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-lcm.c000066400000000000000000000034031414523752600167040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("lcm...."); fflush(stdout); /* 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"); abort(); } fmpz_clear(a); fmpz_clear(c); fmpz_clear(d); _fmpz_vec_clear(f, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-max_bits.c000066400000000000000000000025561414523752600177470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("max_bits...."); fflush(stdout); 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); abort(); } _fmpz_vec_clear(a, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-max_limbs.c000066400000000000000000000030611414523752600201040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("max_limbs...."); fflush(stdout); 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); abort(); } _fmpz_vec_clear(a, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-neg.c000066400000000000000000000040541414523752600167050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg...."); fflush(stdout); /* 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-prod.c000066400000000000000000000032131414523752600170740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("prod...."); fflush(stdout); 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"); abort(); } _fmpz_vec_clear(a, len1 + len2); fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_abs.c000066400000000000000000000041151414523752600202240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_abs...."); fflush(stdout); /* 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_addmul_fmpz.c000066400000000000000000000055631414523752600217710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_addmul_fmpz...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(n1); _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_addmul_si.c000066400000000000000000000035421414523752600214230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_addmul_si...."); fflush(stdout); /* 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_addmul_si_2exp.c000066400000000000000000000036511414523752600223620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_addmul_si_2exp...."); fflush(stdout); /* 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_divexact_fmpz.c000066400000000000000000000051441414523752600223250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_divexact_fmpz...."); fflush(stdout); /* 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(n); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_divexact_si.c000066400000000000000000000045451414523752600217700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_divexact_si...."); fflush(stdout); /* 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_divexact_ui.c000066400000000000000000000044641414523752600217720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_divexact_ui...."); fflush(stdout); /* 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_fdiv_q_fmpz.c000066400000000000000000000064351414523752600217720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_fdiv_q_fmpz...."); fflush(stdout); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_mod_fmpz.c000066400000000000000000000047541414523752600213030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mod_fmpz...."); fflush(stdout); /* 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_mul_2exp.c000066400000000000000000000046721414523752600212220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_2exp...."); fflush(stdout); /* 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_mul_fmpz.c000066400000000000000000000101331414523752600213050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpz...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(n1); fmpz_clear(n2); fmpz_clear(n); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_mul_si.c000066400000000000000000000046171414523752600207560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_si...."); fflush(stdout); /* 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"); 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); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(x); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_mul_ui.c000066400000000000000000000045201414523752600207510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_ui...."); fflush(stdout); /* 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(x); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_smod_fmpz.c000066400000000000000000000060061414523752600214560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_smod_fmpz...."); fflush(stdout); /* 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); fmpz_clear(p); fmpz_clear(lo); fmpz_clear(hi); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_submul_fmpz.c000066400000000000000000000055631414523752600220320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_submul_fmpz...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(n1); _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_submul_si.c000066400000000000000000000035241414523752600214640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_submul_si...."); fflush(stdout); /* 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-scalar_submul_si_2exp.c000066400000000000000000000036331414523752600224230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_submul_si_2exp...."); fflush(stdout); /* 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-set_equal.c000066400000000000000000000051541414523752600201200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set/equal...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-sub.c000066400000000000000000000062301414523752600167230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-sum.c000066400000000000000000000032071414523752600167370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sum...."); fflush(stdout); 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"); abort(); } _fmpz_vec_clear(a, len1 + len2); fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-sum_max_bits.c000066400000000000000000000033451414523752600206300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("sum_max_bits...."); fflush(stdout); 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"); flint_abort(); } if (max_bits != fmpz_bits(max)) { flint_printf("FAIL: max bits is wrong\n"); flint_abort(); } _fmpz_vec_clear(a, len); fmpz_clear(max); fmpz_clear(sum); fmpz_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-swap.c000066400000000000000000000030721414523752600171050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("swap...."); fflush(stdout); 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"); abort(); } _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/test/t-zero.c000066400000000000000000000024021414523752600171060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("zero...."); fflush(stdout); /* 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"); abort(); } _fmpz_vec_clear(a, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fmpz_vec/zero.c000066400000000000000000000010771414523752600156750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/fmpz_vecxx.h000066400000000000000000000050671414523752600153060ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_FMPZ_VECXX_H #define CXX_FMPZ_VECXX_H #include "fmpzxx.h" #include "fmpz_vec.h" #include "flintxx/vector.h" namespace flint { namespace detail { struct fmpz_vector_data { slong size; fmpz* array; fmpz_vector_data(slong n) : size(n), array(_fmpz_vec_init(n)) {} ~fmpz_vector_data() {_fmpz_vec_clear(array, size);} fmpz_vector_data(const fmpz_vector_data& o) : size(o.size), array(_fmpz_vec_init(o.size)) { _fmpz_vec_set(array, o.array, size); } fmpzxx_ref at(slong i) {return fmpzxx_ref::make(array + i);} fmpzxx_srcref at(slong i) const {return fmpzxx_srcref::make(array + i);} }; } // detail typedef vector_expression< detail::wrapped_vector_traits, operations::immediate, detail::fmpz_vector_data> fmpz_vecxx; // TODO references template<> struct enable_vector_rules : mp::false_ { }; namespace rules { // TODO hack to make code look like references are implemented template struct FMPZ_VECXX_COND_S : mp::equal_types { }; #define FMPZ_VECXX_COND_T FMPZ_VECXX_COND_S template struct to_string >::type> { static std::string get(const fmpz_vecxx& e, int base) { // TODO use _fmpz_vec_print somehow? std::ostringstream o; o << e.size(); if(e.size() == 0) { return o.str(); } o << " "; for(slong i = 0;i < e.size();++i) { o << e[i].to_string(base); if(i != e.size() - 1) o << " "; } return o.str(); } }; // TODO references FLINT_DEFINE_GET(equals, bool, fmpz_vecxx, e1.size() == e2.size() && _fmpz_vec_equal(e1._data().array, e2._data().array, e1.size())) FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpz_vecxx, FMPZ_VECXX_COND_S, FMPZ_VECXX_COND_S, _fmpz_vec_add(to._data().array, e1._data().array, e2._data().array, e1.size())) FLINT_DEFINE_DOIT_COND2(assignment, FMPZ_VECXX_COND_T, FMPZ_VECXX_COND_S, _fmpz_vec_set(to._array(), from._array(), to.size())) // TODO more } // rules } // flint #endif flint2-2.8.4/fmpzxx.h000066400000000000000000000632241414523752600144500ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_FMPZXX_H #define CXX_FMPZXX_H #include #include #include "flintxx/evaluation_tools.h" #include "flintxx/expression.h" #include "flintxx/expression_traits.h" #include "flintxx/flint_classes.h" #include "flintxx/frandxx.h" #include "flintxx/ltuple.h" #include "flintxx/stdmath.h" #include "fmpz.h" #undef clrbit /* no idea where these are coming from */ #undef setbit // TODO functions for addmul? inhomogeneous addmul? // TODO use evaluate_n in immediate functions? // TODO fmpz_abs_ubound_ui_2exp, lbound // TODO cmpabs // TODO xgcd_partial namespace flint { FLINT_DEFINE_BINOP(cdiv_q) FLINT_DEFINE_BINOP(fdiv_r) FLINT_DEFINE_BINOP(tdiv_q) FLINT_DEFINE_BINOP(fdiv_r_2exp) FLINT_DEFINE_BINOP(tdiv_q_2exp) FLINT_DEFINE_UNOP(fac) FLINT_DEFINE_UNOP(fib) FLINT_DEFINE_BINOP(rfac) FLINT_DEFINE_BINOP(bin) FLINT_DEFINE_BINOP(gcd) FLINT_DEFINE_BINOP(lcm) FLINT_DEFINE_BINOP(invmod) FLINT_DEFINE_BINOP(negmod) FLINT_DEFINE_THREEARY(mul2) FLINT_DEFINE_THREEARY(divexact2) FLINT_DEFINE_THREEARY(powm) FLINT_DEFINE_THREEARY(mul_tdiv_q_2exp) FLINT_DEFINE_BINOP(fdiv_qr) FLINT_DEFINE_BINOP(tdiv_qr) FLINT_DEFINE_BINOP(sqrtmod) FLINT_DEFINE_UNOP(sqrtrem) FLINT_DEFINE_BINOP(gcdinv) FLINT_DEFINE_BINOP(xgcd) FLINT_DEFINE_BINOP(remove) FLINT_DEFINE_FIVEARY(fmpzxx_bit_unpack) FLINT_DEFINE_THREEARY(fmpzxx_bit_unpack_unsigned) namespace mp { template struct enable_all_fmpzxx; } template class fmpzxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; FLINTXX_DEFINE_BASICS(fmpzxx_expression) FLINTXX_DEFINE_CTORS(fmpzxx_expression) FLINTXX_DEFINE_C_REF(fmpzxx_expression, fmpz, _fmpz) // these only make sense with fmpzxx FLINTXX_DEFINE_RANDFUNC(fmpz, randbits) FLINTXX_DEFINE_RANDFUNC(fmpz, randtest) FLINTXX_DEFINE_RANDFUNC(fmpz, randtest_unsigned) FLINTXX_DEFINE_RANDFUNC(fmpz, randtest_not_zero) template static fmpzxx_expression randm(frandxx& state, const Fmpz& m) { fmpzxx_expression res; fmpz_randm(res._fmpz(), state._data(), m.evaluate()._fmpz()); return res; } template static fmpzxx_expression randtest_mod(frandxx& state, const Fmpz& m) { fmpzxx_expression res; fmpz_randtest_mod(res._fmpz(), state._data(), m.evaluate()._fmpz()); return res; } template static fmpzxx_expression randtest_mod_signed(frandxx& state, const Fmpz& m) { fmpzxx_expression res; fmpz_randtest_mod_signed(res._fmpz(), state._data(), m.evaluate()._fmpz()); return res; } // TODO would these make more sense static? void set_ui_smod(mp_limb_t x, mp_limb_t m) { fmpz_set_ui_smod(this->_fmpz(), x, m); } void set_uiui(mp_limb_t hi, mp_limb_t lo) { fmpz_set_uiui(this->_fmpz(), hi, lo); } void neg_uiui(mp_limb_t hi, mp_limb_t lo) { fmpz_neg_uiui(this->_fmpz(), hi, lo); } // these only make sense with fmpzxx/fmpzxx_ref void clrbit(ulong i) {fmpz_clrbit(_fmpz(), i);} void combit(ulong i) {fmpz_combit(_fmpz(), i);} void setbit(ulong i) {fmpz_setbit(_fmpz(), i);} void set_zero() {fmpz_zero(_fmpz());} void set_one() {fmpz_one(_fmpz());} // These make sense with all expressions, but cause evaluation double get_d_2exp(slong& exp) const { return fmpz_get_d_2exp(&exp, this->evaluate()._fmpz()); } bool is_zero() const { return fmpz_is_zero(this->evaluate()._fmpz()); } bool is_one() const { return fmpz_is_one(this->evaluate()._fmpz()); } bool is_pm1() const { return fmpz_is_pm1(this->evaluate()._fmpz()); } bool is_even() const { return fmpz_is_even(this->evaluate()._fmpz()); } bool is_odd() const { return fmpz_is_odd(this->evaluate()._fmpz()); } bool is_square() const { return fmpz_is_square(this->evaluate()._fmpz()); } int popcnt() const { return fmpz_popcnt(this->evaluate()._fmpz()); } bool is_probabprime() const { return fmpz_is_probabprime(this->evaluate()._fmpz()); } bool is_prime_pseudosquare() const { return fmpz_is_prime_pseudosquare(this->evaluate()._fmpz()); } bool abs_fits_ui() const { return fmpz_abs_fits_ui(this->evaluate()._fmpz()); } bool fits_si() const { return fmpz_fits_si(this->evaluate()._fmpz()); } bool tstbit(ulong i) const { return fmpz_tstbit(this->evaluate()._fmpz(), i); } template typename mp::enable_all_fmpzxx::type divisible(const T2& t2) const { return fmpz_divisible(this->evaluate()._fmpz(), t2.evaluate()._fmpz()); } template typename mp::enable_if, bool>::type divisible(const T2& t2) const { return fmpz_divisible_si(this->evaluate()._fmpz(), t2); } template typename mp::enable_all_fmpzxx::type clog(const Fmpz2& b) const { return fmpz_clog(this->evaluate()._fmpz(), b.evaluate()._fmpz()); } template typename mp::enable_if, slong>::type clog(Int b) const { return fmpz_clog_ui(this->evaluate()._fmpz(), b); } template typename mp::enable_all_fmpzxx::type flog(const Fmpz2& b) const { return fmpz_flog(this->evaluate()._fmpz(), b.evaluate()._fmpz()); } template typename mp::enable_if, slong>::type flog(Int b) const { return fmpz_flog_ui(this->evaluate()._fmpz(), b); } double dlog() const { return fmpz_dlog(this->evaluate()._fmpz()); } template typename mp::enable_all_fmpzxx::type jacobi(const Fmpz2& p) const { return fmpz_jacobi(this->evaluate()._fmpz(), p.evaluate()._fmpz()); } size_t sizeinbase(int b) const {return fmpz_sizeinbase(this->evaluate()._fmpz(), b);} flint_bitcnt_t bits() const {return fmpz_bits(this->evaluate()._fmpz());} flint_bitcnt_t size() const {return fmpz_size(this->evaluate()._fmpz());} flint_bitcnt_t val2() const {return fmpz_val2(this->evaluate()._fmpz());} int sgn() const {return fmpz_sgn(this->evaluate()._fmpz());} // lazy function forwarding FLINTXX_DEFINE_MEMBER_3OP(divexact2) FLINTXX_DEFINE_MEMBER_3OP(mul2) FLINTXX_DEFINE_MEMBER_3OP(mul_tdiv_q_2exp) FLINTXX_DEFINE_MEMBER_3OP(powm) FLINTXX_DEFINE_MEMBER_BINOP(cdiv_q) FLINTXX_DEFINE_MEMBER_BINOP(divexact) FLINTXX_DEFINE_MEMBER_BINOP(fdiv_qr) FLINTXX_DEFINE_MEMBER_BINOP(fdiv_r) FLINTXX_DEFINE_MEMBER_BINOP(fdiv_r_2exp) FLINTXX_DEFINE_MEMBER_BINOP(gcd) FLINTXX_DEFINE_MEMBER_BINOP(gcdinv) FLINTXX_DEFINE_MEMBER_BINOP(invmod) FLINTXX_DEFINE_MEMBER_BINOP(lcm) FLINTXX_DEFINE_MEMBER_BINOP(negmod) FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_BINOP(remove) FLINTXX_DEFINE_MEMBER_BINOP(rfac) FLINTXX_DEFINE_MEMBER_BINOP(root) FLINTXX_DEFINE_MEMBER_BINOP(sqrtmod) FLINTXX_DEFINE_MEMBER_BINOP(tdiv_q) FLINTXX_DEFINE_MEMBER_BINOP(tdiv_q_2exp) FLINTXX_DEFINE_MEMBER_BINOP(tdiv_qr) FLINTXX_DEFINE_MEMBER_BINOP(xgcd) FLINTXX_DEFINE_MEMBER_UNOP(abs) FLINTXX_DEFINE_MEMBER_UNOP(sqrt) // FLINTXX_DEFINE_MEMBER_UNOP(sqrtrem) // TODO FLINTXX_DEFINE_MEMBER_5OP(CRT) template static FLINT_FIVEARY_ENABLE_RETTYPE(fmpzxx_bit_unpack, Arg1, Arg2, flint_bitcnt_t, int, bool) bit_unpack(const Arg1& arr, const Arg2& bits, flint_bitcnt_t shift = 0, int negate = 0, bool borrow = false) { return fmpzxx_bit_unpack(arr, bits, shift, negate, borrow); } template static FLINT_THREEARY_ENABLE_RETTYPE(fmpzxx_bit_unpack_unsigned, Arg1, Arg2, flint_bitcnt_t) bit_unpack_unsigned(const Arg1& arr, const Arg2& bits, flint_bitcnt_t shift = 0) { return fmpzxx_bit_unpack_unsigned(arr, bits, shift); } }; namespace detail { struct fmpz_data; } typedef fmpzxx_expression fmpzxx; typedef fmpzxx_expression > fmpzxx_ref; typedef fmpzxx_expression > fmpzxx_srcref; namespace detail { struct fmpz_data { typedef fmpz_t& data_ref_t; typedef const fmpz_t& data_srcref_t; fmpz_t inner; fmpz_data() {fmpz_init(inner);} ~fmpz_data() {fmpz_clear(inner);} fmpz_data(const fmpz_data& o) {fmpz_init_set(inner, o.inner);} template fmpz_data(const T& t) { init(t); } template typename mp::enable_if >::type init(T t) { fmpz_init_set_ui(inner, t); } template typename mp::enable_if >::type init(T t) { fmpz_init(inner); fmpz_set_si(inner, t); } void init(double d) { fmpz_init(inner); fmpz_set_d(inner, d); } void init(const char* str) { fmpz_init(inner); fmpz_set_str(inner, str, 10); } void init(const fmpzxx_srcref& r) { fmpz_init_set(inner, r._fmpz()); } }; } // detail /////////////////////////////////////////////////////////////////// // HELPERS /////////////////////////////////////////////////////////////////// namespace traits { template struct is_fmpzxx : mp::or_< traits::is_T_expr, flint_classes::is_source > { }; } // traits namespace mp { template struct all_fmpzxx : mp::and_, all_fmpzxx > { }; template struct all_fmpzxx : traits::is_fmpzxx { }; template struct enable_all_fmpzxx : mp::enable_if, Out> { }; } // mp /////////////////////////////////////////////////////////////////// // RULES /////////////////////////////////////////////////////////////////// namespace rules { #define FMPZXX_COND_S FLINTXX_COND_S(fmpzxx) #define FMPZXX_COND_T FLINTXX_COND_T(fmpzxx) FLINT_DEFINE_DOIT_COND2(assignment, FMPZXX_COND_T, FMPZXX_COND_S, fmpz_set(to._fmpz(), from._fmpz())) FLINT_DEFINE_DOIT_COND2(assignment, FMPZXX_COND_T, traits::is_unsigned_integer, fmpz_set_ui(to._fmpz(), from)) FLINT_DEFINE_DOIT_COND2(assignment, FMPZXX_COND_T, traits::is_signed_integer, fmpz_set_si(to._fmpz(), from)) FLINTXX_DEFINE_CMP(fmpzxx, fmpz_cmp(e1._fmpz(), e2._fmpz())) template struct cmp, traits::is_signed_integer > >::type> { static int get(const T& v, const U& t) { return fmpz_cmp_si(v._fmpz(), t); } }; template struct cmp >::type> { static int get(const fmpzxx& v, const T& t) { return fmpz_cmp_ui(v._fmpz(), t); } }; FLINTXX_DEFINE_ASSIGN_STR(fmpzxx, fmpz_set_str(to._fmpz(), from, 10)) FLINTXX_DEFINE_TO_STR(fmpzxx, fmpz_get_str(0, base, from._fmpz())) FLINTXX_DEFINE_SWAP(fmpzxx, fmpz_swap(e1._fmpz(), e2._fmpz())) FLINT_DEFINE_PRINT_COND(FMPZXX_COND_S, fmpz_fprint(to, from._fmpz())) FLINT_DEFINE_READ_COND(FMPZXX_COND_T, fmpz_fread(from, to._fmpz())) FLINT_DEFINE_GET_COND(conversion, slong, FMPZXX_COND_S, fmpz_get_si(from._fmpz())) FLINT_DEFINE_GET_COND(conversion, ulong, FMPZXX_COND_S, fmpz_get_ui(from._fmpz())) FLINT_DEFINE_GET_COND(conversion, double, FMPZXX_COND_S, fmpz_get_d(from._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(plus, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_add(to._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_CBINARY_EXPR_COND2(plus, fmpzxx, FMPZXX_COND_S, traits::is_unsigned_integer, fmpz_add_ui(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(plus, fmpzxx, FMPZXX_COND_S, traits::is_signed_integer, fmpz_add_si(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_mul(to._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpzxx, FMPZXX_COND_S, traits::is_unsigned_integer, fmpz_mul_ui(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(times, fmpzxx, FMPZXX_COND_S, traits::is_signed_integer, fmpz_mul_si(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_sub(to._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpzxx, FMPZXX_COND_S, traits::is_unsigned_integer, fmpz_sub_ui(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(minus, fmpzxx, FMPZXX_COND_S, traits::is_signed_integer, fmpz_sub_si(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_fdiv_q(to._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpzxx, FMPZXX_COND_S, traits::is_unsigned_integer, fmpz_fdiv_q_ui(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, fmpzxx, FMPZXX_COND_S, traits::is_signed_integer, fmpz_fdiv_q_si(to._fmpz(), e1._fmpz(), e2)) // TODO this interpretation of mod is not the same as for builtin types! FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_mod(to._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(modulo, fmpzxx, FMPZXX_COND_S, traits::is_unsigned_integer, fmpz_mod_ui(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(binary_and, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_and(to._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(binary_or, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_or(to._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(binary_xor, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_xor(to._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_UNARY_EXPR_COND(negate, fmpzxx, FMPZXX_COND_S, fmpz_neg(to._fmpz(), from._fmpz())) FLINT_DEFINE_UNARY_EXPR_COND(complement, fmpzxx, FMPZXX_COND_S, fmpz_complement(to._fmpz(), from._fmpz())) namespace rdetail { template void fmpzxx_shift(Fmpz1& to, const Fmpz2& from, T howmuch) { if(howmuch < 0) fmpz_fdiv_q_2exp(to._fmpz(), from._fmpz(), -howmuch); else fmpz_mul_2exp(to._fmpz(), from._fmpz(), howmuch); } } // rdetail FLINT_DEFINE_BINARY_EXPR_COND2(shift, fmpzxx, FMPZXX_COND_S, traits::is_integer, rdetail::fmpzxx_shift(to, e1, e2)) } // rules FLINTXX_DEFINE_TERNARY(fmpzxx, fmpz_addmul(to._fmpz(), e1._fmpz(), e2._fmpz()), fmpz_submul(to._fmpz(), e1._fmpz(), e2._fmpz()), FLINTXX_UNADORNED_MAKETYPES) /////////////////////////////////////////////////////////////////////////// // FUNCTIONS /////////////////////////////////////////////////////////////////////////// // These functions evaluate immediately, and (often) do not yield fmpzxxs template inline typename mp::enable_all_fmpzxx::type divisible(const T1& t1, const T2& t2) { return t1.divisible(t2); } template inline typename mp::enable_all_fmpzxx::type clog(const Fmpz1& x, const Fmpz2& b) { return x.clog(b); } template inline typename mp::enable_all_fmpzxx::type flog(const Fmpz1& x, const Fmpz2& b) { return x.flog(b); } template inline typename mp::enable_if, double>::type dlog(const Fmpz& x) { return x.dlog(); } template inline typename mp::enable_all_fmpzxx::type jacobi(const Fmpz1& a, const Fmpz2& p) { return a.jacobi(p); } template inline typename mp::enable_if, size_t>::type sizeinbase(const Fmpz& a, int b) { return a.sizeinbase(b); } template inline typename mp::enable_if, flint_bitcnt_t>::type bits(const Fmpz& a) { return a.bits(); } template inline typename mp::enable_if, flint_bitcnt_t>::type val2(const Fmpz& a) { return a.val2(); } template inline typename mp::enable_if, flint_bitcnt_t>::type size(const Fmpz& a) { return a.size(); } template inline typename mp::enable_if, int>::type sgn(const Fmpz& a) { return a.sgn(); } template inline bool bit_pack(std::vector& arr, flint_bitcnt_t bits, const Fmpz& coeff, flint_bitcnt_t shift = 0, int negate = 0, bool borrow = false, typename mp::enable_if >::type* = 0) { return fmpz_bit_pack(&arr.front(), shift, bits, coeff.evaluate()._fmpz(), negate, borrow); } // These functions are evaluated lazily namespace rules { FLINT_DEFINE_BINARY_EXPR_COND2(rfac_op, fmpzxx, FMPZXX_COND_S, traits::is_unsigned_integer, fmpz_rfac_ui(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_UNARY_EXPR_COND(fac_op, fmpzxx, traits::is_unsigned_integer, fmpz_fac_ui(to._fmpz(), from)) FLINT_DEFINE_UNARY_EXPR_COND(fib_op, fmpzxx, traits::is_unsigned_integer, fmpz_fib_ui(to._fmpz(), from)) FLINT_DEFINE_BINARY_EXPR_COND2(gcd_op, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_gcd(to._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(lcm_op, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_lcm(to._fmpz(), e1._fmpz(), e2._fmpz())) template struct binary_expression< T1, typename mp::enable_if< mp::and_< traits::is_unsigned_integer, traits::is_unsigned_integer >, operations::bin_op>::type, T2> { typedef fmpzxx return_t; template static void doit(V& to, const T1& t1, const T2& t2) { fmpz_bin_uiui(to._fmpz(), t1, t2); } }; #define FMPZXX_DEFINE_DIVFUNCS(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, \ fmpz_##name(to._fmpz(), e1._fmpz(), e2._fmpz())) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpzxx, FMPZXX_COND_S, \ traits::is_signed_integer, \ fmpz_##name##_si(to._fmpz(), e1._fmpz(), e2)) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, fmpzxx, FMPZXX_COND_S, \ traits::is_unsigned_integer, \ fmpz_##name##_ui(to._fmpz(), e1._fmpz(), e2)) FMPZXX_DEFINE_DIVFUNCS(cdiv_q) FMPZXX_DEFINE_DIVFUNCS(tdiv_q) FMPZXX_DEFINE_DIVFUNCS(divexact) FLINT_DEFINE_BINARY_EXPR_COND2(fdiv_r_op, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_fdiv_r(to._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(tdiv_q_2exp_op, fmpzxx, FMPZXX_COND_S, traits::is_unsigned_integer, fmpz_tdiv_q_2exp(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(fdiv_r_2exp_op, fmpzxx, FMPZXX_COND_S, traits::is_unsigned_integer, fmpz_fdiv_r_2exp(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(invmod_op, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_invmod(to._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(negmod_op, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_negmod(to._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_THREEARY_EXPR_COND3(mul2_op, fmpzxx, FMPZXX_COND_S, traits::is_unsigned_integer, traits::is_unsigned_integer, fmpz_mul2_uiui(to._fmpz(), e1._fmpz(), e2, e3)) FLINT_DEFINE_THREEARY_EXPR_COND3(divexact2_op, fmpzxx, FMPZXX_COND_S, traits::is_unsigned_integer, traits::is_unsigned_integer, fmpz_divexact2_uiui(to._fmpz(), e1._fmpz(), e2, e3)) FLINT_DEFINE_THREEARY_EXPR_COND3(powm_op, fmpzxx, FMPZXX_COND_S, traits::is_unsigned_integer, FMPZXX_COND_S, fmpz_powm_ui(to._fmpz(), e1._fmpz(), e2, e3._fmpz())) FLINT_DEFINE_THREEARY_EXPR_COND3(powm_op, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_powm(to._fmpz(), e1._fmpz(), e2._fmpz(), e3._fmpz())) FLINT_DEFINE_THREEARY_EXPR_COND3(mul_tdiv_q_2exp_op, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, traits::is_unsigned_integer, fmpz_mul_tdiv_q_2exp(to._fmpz(), e1._fmpz(), e2._fmpz(), e3)) FLINT_DEFINE_THREEARY_EXPR_COND3(mul_tdiv_q_2exp_op, fmpzxx, FMPZXX_COND_S, traits::fits_into_slong, traits::is_unsigned_integer, fmpz_mul_si_tdiv_q_2exp(to._fmpz(), e1._fmpz(), e2, e3)) // TODO addmul, submul? namespace rdetail { typedef make_ltuple::type>::type fmpzxx_pair; typedef make_ltuple::type>::type fmpzxx_triple; typedef make_ltuple::type>::type bool_fmpzxx_pair; } // rdetail FLINT_DEFINE_BINARY_EXPR_COND2(fdiv_qr_op, rdetail::fmpzxx_pair, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_fdiv_qr(to.template get<0>()._fmpz(), to.template get<1>()._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(tdiv_qr_op, rdetail::fmpzxx_pair, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_tdiv_qr(to.template get<0>()._fmpz(), to.template get<1>()._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(sqrtmod_op, rdetail::bool_fmpzxx_pair, FMPZXX_COND_S, FMPZXX_COND_S, to.template get<0>() = fmpz_sqrtmod( to.template get<1>()._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_UNARY_EXPR_COND(sqrtrem_op, rdetail::fmpzxx_pair, FMPZXX_COND_S, fmpz_sqrtrem(to.template get<0>()._fmpz(), to.template get<1>()._fmpz(), from._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(gcdinv_op, rdetail::fmpzxx_pair, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_gcdinv(to.template get<0>()._fmpz(), to.template get<1>()._fmpz(), e1._fmpz(), e2._fmpz())) FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_op, rdetail::fmpzxx_triple, FMPZXX_COND_S, FMPZXX_COND_S, fmpz_xgcd( to.template get<0>()._fmpz(), to.template get<1>()._fmpz(), to.template get<2>()._fmpz(), e1._fmpz(), e2._fmpz())) namespace rdetail { template struct is_mplimb_t_vec : mp::equal_types > { }; } FLINT_DEFINE_FIVEARY_EXPR_COND5(fmpzxx_bit_unpack_op, rdetail::bool_fmpzxx_pair, rdetail::is_mplimb_t_vec, traits::fits_into_flint_bitcnt_t, traits::fits_into_flint_bitcnt_t, traits::is_integer, tools::is_bool, to.template get<0>() = fmpz_bit_unpack(to.template get<1>()._fmpz(), &e1.front(), e3, e2, e4, e5)) FLINT_DEFINE_THREEARY_EXPR_COND3(fmpzxx_bit_unpack_unsigned_op, fmpzxx, rdetail::is_mplimb_t_vec, traits::fits_into_flint_bitcnt_t, traits::fits_into_flint_bitcnt_t, fmpz_bit_unpack_unsigned(to._fmpz(), &e1.front(), e3, e2)) // standard math functions (c/f stdmath.h) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, fmpzxx, FMPZXX_COND_S, traits::is_unsigned_integer, fmpz_pow_ui(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(root_op, fmpzxx, FMPZXX_COND_S, traits::fits_into_slong, fmpz_root(to._fmpz(), e1._fmpz(), e2)) FLINT_DEFINE_UNARY_EXPR_COND(sqrt_op, fmpzxx, FMPZXX_COND_S, fmpz_sqrt(to._fmpz(), from._fmpz())) FLINT_DEFINE_UNARY_EXPR_COND(abs_op, fmpzxx, FMPZXX_COND_S, fmpz_abs(to._fmpz(), from._fmpz())) namespace rdetail { typedef make_ltuple::type>::type slong_fmpzxx_pair; } // rdetail FLINT_DEFINE_BINARY_EXPR_COND2(remove_op, rdetail::slong_fmpzxx_pair, FMPZXX_COND_S, FMPZXX_COND_S, to.template get<0>() = fmpz_remove(to.template get<1>()._fmpz(), e1._fmpz(), e2._fmpz())) } // rules // chinese remaindering // TODO should this use nmod? class fmpz_combxx { private: fmpz_comb_t comb; mutable fmpz_comb_temp_t tmp; // not copyable fmpz_combxx(const fmpz_combxx&); public: fmpz_combxx(const std::vector& v) { fmpz_comb_init(comb, &v.front(), v.size()); fmpz_comb_temp_init(tmp, comb); } ~fmpz_combxx() { fmpz_comb_temp_clear(tmp); fmpz_comb_clear(comb); } const fmpz_comb_t& _comb() const {return comb;} fmpz_comb_temp_t& _temp() const {return tmp;} }; // TODO make lazy somehow? template inline typename mp::enable_if >::type multi_mod(std::vector& out, const Fmpz& in, const fmpz_combxx& comb) { fmpz_multi_mod_ui(&out.front(), in.evaluate()._fmpz(), comb._comb(), comb._temp()); } namespace rules { FLINT_DEFINE_FIVEARY_EXPR_COND5(CRT_op, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, traits::is_unsigned_integer, traits::is_unsigned_integer, tools::is_bool, fmpz_CRT_ui(to._fmpz(), e1._fmpz(), e2._fmpz(), e3, e4, e5)) FLINT_DEFINE_THREEARY_EXPR(multi_CRT_op, fmpzxx, std::vector, fmpz_combxx, bool, fmpz_multi_CRT_ui(to._fmpz(), &e1.front(), e2._comb(), e2._temp(), e3)) } // rules } // flint #include "fmpz_factorxx.h" #endif flint2-2.8.4/fprintf.c000066400000000000000000000056221414523752600145550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include "flint.h" int flint_fprintf(FILE * f, 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; size_t ret; /* deal with first substring */ size_t n = strcspn(str, "%"); strncpy(str2, str, n); str2[n] = '\0'; ret = fprintf(f, "%s", str2); 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 += fprintf(f, WORD_FMT "x", wu); ret += fprintf(f, "%s", str2 + 3); } else if (str[2] == 'u') { wu = (ulong) va_arg(ap, ulong); ret += fprintf(f, WORD_FMT "u", wu); ret += fprintf(f, "%s", str2 + 3); } else if (str[2] == 'd') { w = (slong) va_arg(ap, slong); ret += fprintf(f, WORD_FMT "d", w); ret += fprintf(f, "%s", str2 + 3); } else { w = (slong) va_arg(ap, slong); ret += fprintf(f, WORD_FMT "d", w); ret += fprintf(f, "%s", str2 + 2); } break; default: /* pass to fprintf */ 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 += fprintf(f, str2, w2, d); else if (args == 3) ret += fprintf(f, str2, w1, w2, d); else ret += fprintf(f, str2, d); } else { w3 = va_arg(ap, void *); if (args == 2) ret += fprintf(f, str2, w2, w3); else if (args == 3) ret += fprintf(f, str2, w1, w2, w3); else ret += fprintf(f, str2, w3); } } else ret += fprintf(f, "%s", str2); /* zero args */ } len -= n; str += n; } va_end(ap); flint_free(str2); return (int) ret; } flint2-2.8.4/fq.h000066400000000000000000000263361414523752600135250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef FQ_H #define FQ_H #ifdef FQ_INLINES_C #define FQ_INLINE FLINT_DLL #define FQ_TEMPLATES_INLINE FLINT_DLL #else #define FQ_INLINE static __inline__ #define FQ_TEMPLATES_INLINE static __inline__ #endif #include "fmpz_mod_poly.h" #include "fmpz_mod_mat.h" #include "ulong_extras.h" /* Data types and context ****************************************************/ #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]; FLINT_DLL void fq_ctx_init(fq_ctx_t ctx, const fmpz_t p, slong d, const char *var); FLINT_DLL int _fq_ctx_init_conway(fq_ctx_t ctx, const fmpz_t p, slong d, const char *var); FLINT_DLL void fq_ctx_init_conway(fq_ctx_t ctx, const fmpz_t p, slong d, const char *var); FLINT_DLL void fq_ctx_init_modulus(fq_ctx_t ctx, const fmpz_mod_poly_t modulus, const fmpz_mod_ctx_t ctxp, const char *var); FLINT_DLL void fq_ctx_randtest(fq_ctx_t ctx, flint_rand_t state); FLINT_DLL void fq_ctx_randtest_reducible(fq_ctx_t ctx, flint_rand_t state); FLINT_DLL 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 fmpz_mod_ctx_modulus(ctx->ctxp); } FQ_INLINE void fq_ctx_order(fmpz_t f, const fq_ctx_t ctx) { fmpz_pow_ui(f, fq_ctx_prime(ctx), fq_ctx_degree(ctx)); } FQ_INLINE 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; } FQ_INLINE void fq_ctx_print(const fq_ctx_t ctx) { fq_ctx_fprint(stdout, ctx); } /* Memory managment *********************************************************/ FQ_INLINE void fq_init(fq_t rop, const fq_ctx_t ctx) { fmpz_poly_init(rop); } FQ_INLINE void fq_init2(fq_t rop, const fq_ctx_t ctx) { fmpz_poly_init2(rop, fq_ctx_degree(ctx)); } FQ_INLINE void fq_clear(fq_t rop, const fq_ctx_t ctx) { fmpz_poly_clear(rop); } FQ_INLINE 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_vec_scalar_mod_fmpz(R, R, FLINT_MIN(d, lenR), fq_ctx_prime(ctx)); } FQ_INLINE void _fq_dense_reduce(fmpz* R, slong lenR, const fq_ctx_t ctx) { fmpz *q, *r; if (lenR < ctx->modulus->length) { _fmpz_vec_scalar_mod_fmpz(R, R, lenR, fq_ctx_prime(ctx)); return; } q = _fmpz_vec_init(lenR - ctx->modulus->length + 1); r = _fmpz_vec_init(ctx->modulus->length - 1); _fmpz_mod_poly_divrem_newton_n_preinv(q, r, R, lenR, ctx->modulus->coeffs, ctx->modulus->length, ctx->inv->coeffs, ctx->inv->length, fq_ctx_prime(ctx)); _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); } FQ_INLINE 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); } FQ_INLINE 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); } /* Basic arithmetic **********************************************************/ FLINT_DLL void fq_add(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx); FLINT_DLL void fq_sub(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx); FLINT_DLL void fq_sub_one(fq_t rop, const fq_t op1, const fq_ctx_t ctx); FLINT_DLL void fq_neg(fq_t rop, const fq_t op1, const fq_ctx_t ctx); FLINT_DLL void fq_mul(fq_t rop, const fq_t op1, const fq_t op2, const fq_ctx_t ctx); FLINT_DLL void fq_mul_fmpz(fq_t rop, const fq_t op, const fmpz_t x, const fq_ctx_t ctx); FLINT_DLL void fq_mul_si(fq_t rop, const fq_t op, slong x, const fq_ctx_t ctx); FLINT_DLL void fq_mul_ui(fq_t rop, const fq_t op, ulong x, const fq_ctx_t ctx); FLINT_DLL void fq_sqr(fq_t rop, const fq_t op, const fq_ctx_t ctx); FLINT_DLL void fq_inv(fq_t rop, const fq_t op1, const fq_ctx_t ctx); FLINT_DLL void _fq_pow(fmpz *rop, const fmpz *op, slong len, const fmpz_t e, const fq_ctx_t ctx); FLINT_DLL void fq_pow(fq_t rop, const fq_t op1, const fmpz_t e, const fq_ctx_t ctx); FLINT_DLL void fq_pow_ui(fq_t rop, const fq_t op, const ulong e, const fq_ctx_t ctx); /* Roots *********************************************************************/ FLINT_DLL int fq_sqrt(fq_t rop, const fq_t op, const fq_ctx_t ctx); FLINT_DLL void fq_pth_root(fq_t rop, const fq_t op1, const fq_ctx_t ctx); FLINT_DLL int fq_is_square(const fq_t op, const fq_ctx_t ctx); /* Randomisation *************************************************************/ FLINT_DLL void fq_randtest(fq_t rop, flint_rand_t state, const fq_ctx_t ctx); FLINT_DLL void fq_randtest_dense(fq_t rop, flint_rand_t state, const fq_ctx_t ctx); FLINT_DLL void fq_randtest_not_zero(fq_t rop, flint_rand_t state, const fq_ctx_t ctx); FLINT_DLL void fq_rand(fq_t rop, flint_rand_t state, const fq_ctx_t ctx); FLINT_DLL void fq_rand_not_zero(fq_t rop, flint_rand_t state, const fq_ctx_t ctx); /* Comparison ****************************************************************/ FQ_INLINE int fq_equal(const fq_t op1, const fq_t op2, const fq_ctx_t ctx) { return fmpz_poly_equal(op1, op2); } FQ_INLINE int fq_is_zero(const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_is_zero(op); } FQ_INLINE int fq_is_one(const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_is_one(op); } /* Assignments and conversions ***********************************************/ FQ_INLINE void fq_set(fq_t rop, const fq_t op, const fq_ctx_t ctx) { fmpz_poly_set(rop, op); } FQ_INLINE 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); } FQ_INLINE 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); } FQ_INLINE 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); } FQ_INLINE void fq_swap(fq_t op1, fq_t op2, const fq_ctx_t ctx) { fmpz_poly_swap(op1, op2); } FQ_INLINE void fq_zero(fq_t rop, const fq_ctx_t ctx) { fmpz_poly_zero(rop); } FQ_INLINE void fq_one(fq_t rop, const fq_ctx_t ctx) { fmpz_poly_one(rop); } FQ_INLINE 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_DLL void fq_get_fmpz_poly(fmpz_poly_t a, const fq_t b, const fq_ctx_t ctx); FLINT_DLL void fq_set_fmpz_poly(fq_t a, const fmpz_poly_t b, const fq_ctx_t ctx); FLINT_DLL void fq_get_fmpz_mod_poly(fmpz_mod_poly_t a, const fq_t b, const fq_ctx_t ctx); FLINT_DLL void fq_set_fmpz_mod_poly(fq_t a, const fmpz_mod_poly_t b, const fq_ctx_t ctx); /* Output ********************************************************************/ FQ_INLINE int fq_fprint(FILE * file, const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_fprint(file, op); } FQ_INLINE void fq_print(const fq_t op, const fq_ctx_t ctx) { fmpz_poly_print(op); } FQ_INLINE int fq_fprint_pretty(FILE * file, const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_fprint_pretty(file, op, ctx->var); } FQ_INLINE int fq_print_pretty(const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_print_pretty(op, ctx->var); } FLINT_DLL char * fq_get_str(const fq_t op, const fq_ctx_t ctx); FLINT_DLL char * fq_get_str_pretty(const fq_t op, const fq_ctx_t ctx); /* Special functions *********************************************************/ FLINT_DLL void _fq_trace(fmpz_t rop, const fmpz *op, slong len, const fq_ctx_t ctx); FLINT_DLL void fq_trace(fmpz_t rop, const fq_t op, const fq_ctx_t ctx); FLINT_DLL void _fq_frobenius(fmpz *rop, const fmpz *op, slong len, slong e, const fq_ctx_t ctx); FLINT_DLL void fq_frobenius(fq_t rop, const fq_t op, slong e, const fq_ctx_t ctx); FLINT_DLL void _fq_norm(fmpz_t rop, const fmpz *op, slong len, const fq_ctx_t ctx); FLINT_DLL void fq_norm(fmpz_t rop, const fq_t op, const fq_ctx_t ctx); /* Bit packing ******************************************************/ FLINT_DLL void fq_bit_pack(fmpz_t f, const fq_t op, flint_bitcnt_t bit_size, const fq_ctx_t ctx); FLINT_DLL void fq_bit_unpack(fq_t rop, const fmpz_t f, flint_bitcnt_t bit_size, const fq_ctx_t ctx); /* Inlines *******************************************************************/ FLINT_DLL 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 flint2-2.8.4/fq/000077500000000000000000000000001414523752600133425ustar00rootroot00000000000000flint2-2.8.4/fq/add.c000066400000000000000000000015511414523752600142400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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, fq_ctx_prime(ctx)); _fmpz_poly_set_length(rop, max); _fmpz_poly_normalise(rop); } flint2-2.8.4/fq/bit_pack.c000066400000000000000000000010351414523752600152610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/bit_unpack.c000066400000000000000000000011061414523752600156230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/ctx_clear.c000066400000000000000000000013321414523752600154510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/ctx_init.c000066400000000000000000000020641414523752600153310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq.h" #include "fq_poly.h" 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; } else { 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); } flint2-2.8.4/fq/ctx_init_conway.c000066400000000000000000000045371414523752600167200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq.h" /* from qadic/ctx_init_conway.c */ extern int flint_conway_polynomials []; int _fq_ctx_init_conway(fq_ctx_t ctx, const fmpz_t p, slong d, const char *var) { unsigned int position; if (fmpz_cmp_ui(p, 109987) > 0) { return 0; } for (position = 0; flint_conway_polynomials[position] != 0; position += 3+flint_conway_polynomials[position+1]) { /* Different prime? */ if (fmpz_cmp_ui(p, flint_conway_polynomials[position])) continue; /* Same degree? */ if (d == flint_conway_polynomials[position+1]) { fmpz_mod_ctx_t ctxp; fmpz_mod_poly_t mod; slong i; fmpz_mod_ctx_init(ctxp, p); fmpz_mod_poly_init(mod, ctxp); /* Copy the polynomial */ for (i = 0; i < d; i++) { int coeff = flint_conway_polynomials[position+2+i]; fmpz_mod_poly_set_coeff_ui(mod, i, coeff, ctxp); } fmpz_mod_poly_set_coeff_ui(mod, d, 1, ctxp); fq_ctx_init_modulus(ctx, mod, ctxp, var); fmpz_mod_poly_clear(mod, ctxp); fmpz_mod_ctx_clear(ctxp); return 1; } } return 0; } void fq_ctx_init_conway(fq_ctx_t ctx, const fmpz_t p, slong d, const char *var) { int result; if (fmpz_cmp_ui(p, 109987) > 0) { flint_printf("Exception (fq_ctx_init_conway). Conway polynomials \n"); flint_printf("are only available for primes up to 109987.\n"); flint_abort(); } result = _fq_ctx_init_conway(ctx, p, d, var); if (!result) { flint_printf ("Exception (fq_ctx_init_conway). The polynomial for \n(p,d) = ("); fmpz_print(p); flint_printf(",%wd) is not present in the database.\n", d); flint_abort(); } ctx->is_conway = 1; } flint2-2.8.4/fq/ctx_init_modulus.c000066400000000000000000000037541414523752600171100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq.h" #include "fq_poly.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_newton(ctx->inv, ctx->inv, ctx->modulus->length, ctx->ctxp); ctx->is_conway = 0; } flint2-2.8.4/fq/ctx_randtest.c000066400000000000000000000025451414523752600162160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq.h" void fq_ctx_randtest(fq_ctx_t ctx, flint_rand_t state) { fmpz_mod_poly_t modulus; fmpz_t p, x; slong d; fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, 6), 1)); d = n_randint(state, 10) + 1; fq_ctx_init_conway(ctx, p, d, "a"); fmpz_clear(p); /* Test non-monic modulus */ if (n_randint(state, 2)) { fmpz_mod_ctx_t ctxp; fmpz_mod_ctx_init(ctxp, p); fmpz_init_set(x, p); fmpz_sub_ui(x, x, 1); fmpz_mod_poly_init(modulus, ctxp); fmpz_mod_poly_set(modulus, ctx->modulus, ctxp); fmpz_randm(x, state, x); fmpz_add_ui(x, x, 1); fmpz_mod_poly_scalar_mul_fmpz(modulus, modulus, x, ctxp); fq_ctx_clear(ctx); fq_ctx_init_modulus(ctx, modulus, ctxp, "a"); fmpz_mod_poly_clear(modulus, ctxp); fmpz_mod_ctx_clear(ctxp); fmpz_clear(x); } } flint2-2.8.4/fq/ctx_randtest_reducible.c000066400000000000000000000016321414523752600202300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq.h" void fq_ctx_randtest_reducible(fq_ctx_t ctx, flint_rand_t state) { fmpz_mod_ctx_t ctxp; fmpz_mod_poly_t mod; fmpz_t p; slong d; fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, 6), 1)); d = n_randint(state, 10) + 1; fmpz_mod_ctx_init(ctxp, p); fmpz_mod_poly_init(mod, ctxp); fmpz_mod_poly_randtest_monic(mod, state, d + 1, ctxp); fq_ctx_init_modulus(ctx, mod, ctxp, "a"); fmpz_mod_poly_clear(mod, ctxp); fmpz_mod_ctx_clear(ctxp); fmpz_clear(p); } flint2-2.8.4/fq/div.c000066400000000000000000000007701414523752600142740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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/div.c" #undef CAP_T #undef T flint2-2.8.4/fq/frobenius.c000066400000000000000000000037001414523752600155020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.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); } } flint2-2.8.4/fq/gcdinv.c000066400000000000000000000044451414523752600147670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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, fq_ctx_prime(ctx)); 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_poly_scalar_mul_fmpz(rop->coeffs, rop->coeffs, rop->length, f, fq_ctx_prime(ctx)); _fmpz_mod_poly_scalar_mul_fmpz(inv->coeffs, inv->coeffs, inv->length, f, fq_ctx_prime(ctx)); cleanup: fmpz_clear(f); return; } flint2-2.8.4/fq/get_fmpz_mod_poly.c000066400000000000000000000013121414523752600172200ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/get_fmpz_poly.c000066400000000000000000000007631414523752600163720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/get_set_fmpz_mod_mat.c000066400000000000000000000020651414523752600176770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_mod_mat_set_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); } flint2-2.8.4/fq/get_str.c000066400000000000000000000007471414523752600151650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq.h" char * fq_get_str(const fq_t op, const fq_ctx_t ctx) { return fmpz_poly_get_str(op); } flint2-2.8.4/fq/get_str_pretty.c000066400000000000000000000007771414523752600165770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/inlines.c000066400000000000000000000013151414523752600151470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fq.h" void __fq_ctx_prime(fmpz_t p, fq_ctx_t ctx) { fmpz_set(p, fq_ctx_prime(ctx)); } flint2-2.8.4/fq/inv.c000066400000000000000000000032051414523752600143020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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, fq_ctx_prime(ctx)); } } void fq_inv(fq_t rop, const fq_t op, const fq_ctx_t ctx) { if (fq_is_zero(op, ctx)) { flint_printf("Exception (fq_inv). Zero is not invertible.\n"); flint_abort(); } 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); } } flint2-2.8.4/fq/is_invertible.c000066400000000000000000000010021414523752600163350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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/is_invertible.c" #undef CAP_T #undef T flint2-2.8.4/fq/is_invertible_f.c000066400000000000000000000010041414523752600166440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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/is_invertible_f.c" #undef CAP_T #undef T flint2-2.8.4/fq/is_square.c000066400000000000000000000007771414523752600155140ustar00rootroot00000000000000/* 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 2.1 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/is_square.c" #undef CAP_T #undef T flint2-2.8.4/fq/mul.c000066400000000000000000000011101414523752600142740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/mul_fmpz.c000066400000000000000000000011161414523752600153360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/mul_si.c000066400000000000000000000011031414523752600147710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/mul_ui.c000066400000000000000000000011031414523752600147730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/multiplicative_order.c000066400000000000000000000010111414523752600177250ustar00rootroot00000000000000/* 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 2.1 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/multiplicative_order.c" #undef CAP_T #undef T flint2-2.8.4/fq/neg.c000066400000000000000000000013251414523752600142600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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, fq_ctx_prime(ctx)); } flint2-2.8.4/fq/norm.c000066400000000000000000000033331414523752600144630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); const fmpz *p = fq_ctx_prime(ctx); if (d == 1) { fmpz_set(rop, op + 0); } else if (len == 1) { fmpz_powm_ui(rop, op + 0, d, p); } else { _fmpz_mod_poly_resultant(rop, ctx->modulus->coeffs, ctx->modulus->length, op, len, p); /* 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_powm_ui(f, ctx->modulus->coeffs + d, len - 1, p); fmpz_invmod(f, f, p); fmpz_mul(rop, f, rop); fmpz_mod(rop, rop, p); 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); } } flint2-2.8.4/fq/pow.c000066400000000000000000000077611414523752600143260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fq_pow). e < 0.\n"); flint_abort(); } 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); } } flint2-2.8.4/fq/pow_ui.c000066400000000000000000000011221414523752600150040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/profile/000077500000000000000000000000001414523752600150025ustar00rootroot00000000000000flint2-2.8.4/fq/profile/p-inv.c000066400000000000000000000027631414523752600162070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fq.h" #include #include "profiler.h" #ifndef REPS #define REPS 1000000 #endif int main() { 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; } flint2-2.8.4/fq/profile/p-mul.c000066400000000000000000000021111414523752600161730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fq.h" #include #include "profiler.h" #ifndef REPS #define REPS 1000000 #endif int main() { timeit_t t0; slong i; fmpz_t p; slong d,cpu,wall; 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_printf ( " cpu = %wd ms, wall = %wd ms \n " , cpu , wall ); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq/profile/p-reduce.c000066400000000000000000000032011414523752600166460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fq.h" #include #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; } flint2-2.8.4/fq/pth_root.c000066400000000000000000000013451414523752600153470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fq/rand.c000066400000000000000000000017151414523752600144360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/randtest.c000066400000000000000000000034041414523752600153330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/set_fmpz_mod_poly.c000066400000000000000000000021251414523752600172370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq/set_fmpz_poly.c000066400000000000000000000020671414523752600164050ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq/sqr.c000066400000000000000000000011241414523752600143110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq/sqrt.c000066400000000000000000000007721414523752600145050ustar00rootroot00000000000000/* 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 2.1 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/sqrt.c" #undef CAP_T #undef T flint2-2.8.4/fq/sub.c000066400000000000000000000015511414523752600143010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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, fq_ctx_prime(ctx)); _fmpz_poly_set_length(rop, max); _fmpz_poly_normalise(rop); } flint2-2.8.4/fq/sub_one.c000066400000000000000000000011021414523752600151320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fq/test/000077500000000000000000000000001414523752600143215ustar00rootroot00000000000000flint2-2.8.4/fq/test/t-add.c000066400000000000000000000011171414523752600154560ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-assign.c000066400000000000000000000010031414523752600162040ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-ctx_init.c000066400000000000000000000060611414523752600165520ustar00rootroot00000000000000/* 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 2.1 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 #ifdef T #include "templates.h" #include #include #include "fmpz_mod_poly.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, k, result; FLINT_TEST_INIT(state); flint_printf("ctx_init... "); fflush(stdout); for (i = 0; i < 3 * flint_test_multiplier(); i++) { fmpz_t p; slong d; TEMPLATE(T, ctx_t) ctx; fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, FLINT_MIN(FLINT_BITS - 1, 50)), 1)); d = n_randint(state, 20) + 1; TEMPLATE(T, ctx_init)(ctx, p, d, "a"); TEMPLATE(T, ctx_clear)(ctx); } for (i = 0; i < 3 * flint_test_multiplier(); i++) { fmpz_t p; slong d; TEMPLATE(T, ctx_t) ctx_conway, ctx_mod; TEMPLATE(T, t) a, b, lhs, rhs; fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; TEMPLATE(T, ctx_init_conway)(ctx_conway, p, d, "a"); TEMPLATE(T, ctx_init_modulus)(ctx_mod, ctx_conway->modulus, ctx_conway->ctxp, "a"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif #undef CAP_T #undef T flint2-2.8.4/fq/test/t-div.c000066400000000000000000000007771414523752600155230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq/test/t-frobenius.c000066400000000000000000000011251414523752600167210ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-get_set_fmpz_mod_poly.c000066400000000000000000000032461414523752600213230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("get/set_fmpz_mod_poly... "); fflush(stdout); 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_randtest(ctx, state); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq/test/t-get_set_fmpz_poly.c000066400000000000000000000032611414523752600204610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("get/set_fmpz_poly... "); fflush(stdout); 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_randtest(ctx, state); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq/test/t-inv.c000066400000000000000000000011161414523752600155210ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-is_invertible.c000066400000000000000000000010111414523752600175550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq/test/t-is_invertible_f.c000066400000000000000000000010131414523752600200640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq/test/t-is_primitive.c000066400000000000000000000010101414523752600174210ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-is_square.c000066400000000000000000000010071414523752600167170ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-mul.c000066400000000000000000000011171414523752600155230ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-mul_fmpz.c000066400000000000000000000011161414523752600165560ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-mul_si.c000066400000000000000000000011141414523752600162130ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-mul_ui.c000066400000000000000000000011141414523752600162150ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-multiplicative_order.c000066400000000000000000000010201414523752600211450ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-neg.c000066400000000000000000000011161414523752600154760ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-norm.c000066400000000000000000000011201414523752600156730ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-pow.c000066400000000000000000000011161414523752600155320ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-pth_root.c000066400000000000000000000011241414523752600165620ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-sqr.c000066400000000000000000000011171414523752600155330ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-sqrt.c000066400000000000000000000010011414523752600157070ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-sub.c000066400000000000000000000011161414523752600155160ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/test/t-trace.c000066400000000000000000000011211414523752600160170ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq/trace.c000066400000000000000000000026151414523752600146100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_default.h000066400000000000000000000605051414523752600152250ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FQ_DEFAULT_INLINE static __inline__ #endif #include "ulong_extras.h" #include "fmpz.h" #include "fq.h" #include "fq_nmod.h" #include "fq_zech.h" /* 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; } fq_default_struct; typedef fq_default_struct fq_default_t[1]; typedef struct { int type; union ctx { fq_ctx_t fq; fq_nmod_ctx_t fq_nmod; fq_zech_ctx_t fq_zech; } ctx; } fq_default_ctx_struct; typedef fq_default_ctx_struct fq_default_ctx_t[1]; FQ_DEFAULT_INLINE 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 == 1 || (type == 0 && bits*d <= 16 && n_pow(fmpz_get_ui(p), d) < (UWORD(1) << 16))) { ctx->type = 1; fq_zech_ctx_init(ctx->ctx.fq_zech, p, d, var); } else if (type == 2 || (type == 0 && fmpz_abs_fits_ui(p))) { ctx->type = 2; fq_nmod_ctx_init(ctx->ctx.fq_nmod, p, d, var); } else { ctx->type = 3; fq_ctx_init(ctx->ctx.fq, p, d, var); } } 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); } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fq_default_ctx_init_modulus_nmod_type(fq_default_ctx_t ctx, const nmod_poly_t modulus, const char * var, int type); FLINT_DLL 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) { if (ctx->type == 1) { fq_zech_ctx_clear(ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_ctx_clear(ctx->ctx.fq_nmod); } else { fq_ctx_clear(ctx->ctx.fq); } } FQ_DEFAULT_INLINE int fq_default_ctx_type(const fq_default_ctx_t ctx) { return ctx->type; } FQ_DEFAULT_INLINE slong fq_default_ctx_degree(const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_ctx_degree(ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_ctx_degree(ctx->ctx.fq_nmod); } else { return fq_ctx_degree(ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_ctx_prime(fmpz_t prime, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fmpz_set(prime, fq_zech_ctx_prime(ctx->ctx.fq_zech)); } else if (ctx->type == 2) { fmpz_set(prime, fq_nmod_ctx_prime(ctx->ctx.fq_nmod)); } else { fmpz_set(prime, fq_ctx_prime(ctx->ctx.fq)); } } FLINT_DLL 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 (ctx->type == 1) { fq_zech_ctx_order(f, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_ctx_order(f, ctx->ctx.fq_nmod); } else { fq_ctx_order(f, ctx->ctx.fq); } } FQ_DEFAULT_INLINE int fq_default_ctx_fprint(FILE * file, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_ctx_fprint(file, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_ctx_fprint(file, ctx->ctx.fq_nmod); } return fq_ctx_fprint(file, ctx->ctx.fq); } FQ_DEFAULT_INLINE void fq_default_ctx_print(const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_ctx_print(ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_ctx_print(ctx->ctx.fq_nmod); } else { fq_ctx_print(ctx->ctx.fq); } } /* Memory managment *********************************************************/ FQ_DEFAULT_INLINE void fq_default_init(fq_default_t rop, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_init(rop->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_init(rop->fq_nmod, ctx->ctx.fq_nmod); } else { fq_init(rop->fq, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_init2(fq_default_t rop, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_init2(rop->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_init2(rop->fq_nmod, ctx->ctx.fq_nmod); } else { fq_init2(rop->fq, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_clear(fq_default_t rop, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_clear(rop->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_clear(rop->fq_nmod, ctx->ctx.fq_nmod); } else { fq_clear(rop->fq, ctx->ctx.fq); } } /* Predicates ****************************************************************/ FQ_DEFAULT_INLINE int fq_default_is_invertible(const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_is_invertible(op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_is_invertible(op->fq_nmod, ctx->ctx.fq_nmod); } return fq_is_invertible(op->fq, ctx->ctx.fq); } /* Basic arithmetic **********************************************************/ 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) { if (ctx->type == 1) { fq_zech_add(rop->fq_zech, op1->fq_zech, op2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_add(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_add(rop->fq, op1->fq, op2->fq, ctx->ctx.fq); } } 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) { if (ctx->type == 1) { fq_zech_sub(rop->fq_zech, op1->fq_zech, op2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_sub(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_sub(rop->fq, op1->fq, op2->fq, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_sub_one(fq_default_t rop, const fq_default_t op1, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_sub_one(rop->fq_zech, op1->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_sub_one(rop->fq_nmod, op1->fq_nmod, ctx->ctx.fq_nmod); } else { fq_sub_one(rop->fq, op1->fq, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_neg(fq_default_t rop, const fq_default_t op1, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_neg(rop->fq_zech, op1->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_neg(rop->fq_nmod, op1->fq_nmod, ctx->ctx.fq_nmod); } else { fq_neg(rop->fq, op1->fq, ctx->ctx.fq); } } 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) { if (ctx->type == 1) { fq_zech_mul(rop->fq_zech, op1->fq_zech, op2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mul(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mul(rop->fq, op1->fq, op2->fq, ctx->ctx.fq); } } 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) { if (ctx->type == 1) { fq_zech_mul_fmpz(rop->fq_zech, op->fq_zech, x, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mul_fmpz(rop->fq_nmod, op->fq_nmod, x, ctx->ctx.fq_nmod); } else { fq_mul_fmpz(rop->fq, op->fq, x, ctx->ctx.fq); } } 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) { if (ctx->type == 1) { fq_zech_mul_si(rop->fq_zech, op->fq_zech, x, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mul_si(rop->fq_nmod, op->fq_nmod, x, ctx->ctx.fq_nmod); } else { fq_mul_si(rop->fq, op->fq, x, ctx->ctx.fq); } } 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) { if (ctx->type == 1) { fq_zech_mul_ui(rop->fq_zech, op->fq_zech, x, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mul_ui(rop->fq_nmod, op->fq_nmod, x, ctx->ctx.fq_nmod); } else { fq_mul_ui(rop->fq, op->fq, x, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_sqr(fq_default_t rop, const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_sqr(rop->fq_zech, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_sqr(rop->fq_nmod, op->fq_nmod, ctx->ctx.fq_nmod); } else { fq_sqr(rop->fq, op->fq, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_inv(fq_default_t rop, const fq_default_t op1, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_inv(rop->fq_zech, op1->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_inv(rop->fq_nmod, op1->fq_nmod, ctx->ctx.fq_nmod); } else { fq_inv(rop->fq, op1->fq, ctx->ctx.fq); } } 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) { if (ctx->type == 1) { fq_zech_div(rop->fq_zech, op1->fq_zech, op2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_div(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_div(rop->fq, op1->fq, op2->fq, ctx->ctx.fq); } } 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) { if (ctx->type == 1) { fq_zech_pow(rop->fq_zech, op1->fq_zech, e, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_pow(rop->fq_nmod, op1->fq_nmod, e, ctx->ctx.fq_nmod); } else { fq_pow(rop->fq, op1->fq, e, ctx->ctx.fq); } } 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) { if (ctx->type == 1) { fq_zech_pow_ui(rop->fq_zech, op->fq_zech, e, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_pow_ui(rop->fq_nmod, op->fq_nmod, e, ctx->ctx.fq_nmod); } else { fq_pow_ui(rop->fq, op->fq, e, ctx->ctx.fq); } } /* Roots *********************************************************************/ FQ_DEFAULT_INLINE int fq_default_sqrt(fq_default_t rop, const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_sqrt(rop->fq_zech, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_sqrt(rop->fq_nmod, op->fq_nmod, ctx->ctx.fq_nmod); } return fq_sqrt(rop->fq, op->fq, ctx->ctx.fq); } FQ_DEFAULT_INLINE void fq_default_pth_root(fq_default_t rop, const fq_default_t op1, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_pth_root(rop->fq_zech, op1->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_pth_root(rop->fq_nmod, op1->fq_nmod, ctx->ctx.fq_nmod); } else { fq_pth_root(rop->fq, op1->fq, ctx->ctx.fq); } } FQ_DEFAULT_INLINE int fq_default_is_square(const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_is_square(op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_is_square(op->fq_nmod, ctx->ctx.fq_nmod); } return fq_is_square(op->fq, ctx->ctx.fq); } /* Randomisation *************************************************************/ FQ_DEFAULT_INLINE void fq_default_randtest(fq_default_t rop, flint_rand_t state, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_randtest(rop->fq_zech, state, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_randtest(rop->fq_nmod, state, ctx->ctx.fq_nmod); } else { fq_randtest(rop->fq, state, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_randtest_not_zero(fq_default_t rop, flint_rand_t state, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_randtest_not_zero(rop->fq_zech, state, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_randtest_not_zero(rop->fq_nmod, state, ctx->ctx.fq_nmod); } else { fq_randtest_not_zero(rop->fq, state, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_rand(fq_default_t rop, flint_rand_t state, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_rand(rop->fq_zech, state, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_rand(rop->fq_nmod, state, ctx->ctx.fq_nmod); } else { fq_rand(rop->fq, state, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_rand_not_zero(fq_default_t rop, flint_rand_t state, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_rand_not_zero(rop->fq_zech, state, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_rand_not_zero(rop->fq_nmod, state, ctx->ctx.fq_nmod); } else { fq_rand_not_zero(rop->fq, state, ctx->ctx.fq); } } /* Comparison ****************************************************************/ FQ_DEFAULT_INLINE int fq_default_equal(const fq_default_t op1, const fq_default_t op2, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_equal(op1->fq_zech, op2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_equal(op1->fq_nmod, op2->fq_nmod, ctx->ctx.fq_nmod); } return fq_equal(op1->fq, op2->fq, ctx->ctx.fq); } FQ_DEFAULT_INLINE int fq_default_is_zero(const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_is_zero(op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_is_zero(op->fq_nmod, ctx->ctx.fq_nmod); } return fq_is_zero(op->fq, ctx->ctx.fq); } FQ_DEFAULT_INLINE int fq_default_is_one(const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_is_one(op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_is_one(op->fq_nmod, ctx->ctx.fq_nmod); } return fq_is_one(op->fq, ctx->ctx.fq); } /* 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) { if (ctx->type == 1) { fq_zech_set(rop->fq_zech, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_set(rop->fq_nmod, op->fq_nmod, ctx->ctx.fq_nmod); } else { fq_set(rop->fq, op->fq, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_set_fmpz(fq_default_t rop, const fmpz_t x, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_set_fmpz(rop->fq_zech, x, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_set_fmpz(rop->fq_nmod, x, ctx->ctx.fq_nmod); } else { fq_set_fmpz(rop->fq, x, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_set_ui(fq_default_t rop, const ulong x, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_set_ui(rop->fq_zech, x, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_set_ui(rop->fq_nmod, x, ctx->ctx.fq_nmod); } else { fq_set_ui(rop->fq, x, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_set_si(fq_default_t rop, const slong x, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_set_si(rop->fq_zech, x, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_set_si(rop->fq_nmod, x, ctx->ctx.fq_nmod); } else { fq_set_si(rop->fq, x, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_zero(fq_default_t rop, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_zero(rop->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_zero(rop->fq_nmod, ctx->ctx.fq_nmod); } else { fq_zero(rop->fq, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_one(fq_default_t rop, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_one(rop->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_one(rop->fq_nmod, ctx->ctx.fq_nmod); } else { fq_one(rop->fq, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_swap(fq_default_t op1, fq_default_t op2, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_swap(op1->fq_zech, op2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_swap(op1->fq_nmod, op2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_swap(op1->fq, op2->fq, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_gen(fq_default_t rop, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_gen(rop->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_gen(rop->fq_nmod, ctx->ctx.fq_nmod); } else { fq_gen(rop->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_get_nmod_poly(poly, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_get_nmod_poly(poly, op->fq_nmod, ctx->ctx.fq_nmod); } else { flint_printf("Impossible conversion\n"); flint_abort(); } } 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 (ctx->type == 1) { fq_zech_set_nmod_poly(op->fq_zech, poly, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_set_nmod_poly(op->fq_nmod, poly, ctx->ctx.fq_nmod); } else { flint_printf("Impossible conversion\n"); flint_abort(); } } FLINT_DLL void fq_default_get_fmpz_mod_poly(fmpz_mod_poly_t poly, const fq_default_t op, const fq_default_ctx_t ctx); FLINT_DLL void fq_default_set_fmpz_mod_poly(fq_default_t op, const fmpz_mod_poly_t poly, const fq_default_ctx_t ctx); FLINT_DLL void fq_default_get_fmpz_poly(fmpz_poly_t poly, const fq_default_t op, const fq_default_ctx_t ctx); FLINT_DLL 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 (ctx->type == 1) { nmod_poly_t p; ulong c0; nmod_poly_init(p, fmpz_get_ui(fq_zech_ctx_prime(ctx->ctx.fq_zech))); fq_zech_get_nmod_poly(p, op->fq_zech, ctx->ctx.fq_zech); c0 = nmod_poly_get_coeff_ui(p, n); fmpz_set_ui(c, c0); nmod_poly_clear(p); } else if (ctx->type == 2) { ulong c0 = nmod_poly_get_coeff_ui((nmod_poly_struct *) op->fq_nmod, n); fmpz_set_ui(c, c0); } else { fmpz_mod_ctx_t mod_ctx; fmpz_mod_ctx_init(mod_ctx, fq_ctx_prime(ctx->ctx.fq)); fmpz_mod_poly_get_coeff_fmpz(c, (fmpz_mod_poly_struct *) op->fq, n, mod_ctx); fmpz_mod_ctx_clear(mod_ctx); } } /* Output ********************************************************************/ FQ_DEFAULT_INLINE int fq_default_fprint(FILE * file, const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_fprint(file, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_fprint(file, op->fq_nmod, ctx->ctx.fq_nmod); } return fq_fprint(file, op->fq, ctx->ctx.fq); } FQ_DEFAULT_INLINE void fq_default_print(const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_print(op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_print(op->fq_nmod, ctx->ctx.fq_nmod); } else { fq_print(op->fq, ctx->ctx.fq); } } FQ_DEFAULT_INLINE int fq_default_fprint_pretty(FILE * file, const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_fprint_pretty(file, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_fprint_pretty(file, op->fq_nmod, ctx->ctx.fq_nmod); } return fq_fprint_pretty(file, op->fq, ctx->ctx.fq); } FQ_DEFAULT_INLINE void fq_default_print_pretty(const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_print_pretty(op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_print_pretty(op->fq_nmod, ctx->ctx.fq_nmod); } else { fq_print_pretty(op->fq, ctx->ctx.fq); } } FQ_DEFAULT_INLINE char * fq_default_get_str(const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_get_str(op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_get_str(op->fq_nmod, ctx->ctx.fq_nmod); } return fq_get_str(op->fq, ctx->ctx.fq); } FQ_DEFAULT_INLINE char * fq_default_get_str_pretty(const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_get_str_pretty(op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_get_str_pretty(op->fq_nmod, ctx->ctx.fq_nmod); } return fq_get_str_pretty(op->fq, ctx->ctx.fq); } /* Special functions *********************************************************/ FQ_DEFAULT_INLINE void fq_default_trace(fmpz_t rop, const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_trace(rop, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_trace(rop, op->fq_nmod, ctx->ctx.fq_nmod); } else { fq_trace(rop, op->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_frobenius(rop->fq_zech, op->fq_zech, e, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_frobenius(rop->fq_nmod, op->fq_nmod, e, ctx->ctx.fq_nmod); } else { fq_frobenius(rop->fq, op->fq, e, ctx->ctx.fq); } } FQ_DEFAULT_INLINE void fq_default_norm(fmpz_t rop, const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_norm(rop, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_norm(rop, op->fq_nmod, ctx->ctx.fq_nmod); } else { fq_norm(rop, op->fq, ctx->ctx.fq); } } #ifdef __cplusplus } #endif #endif flint2-2.8.4/fq_default/000077500000000000000000000000001414523752600150465ustar00rootroot00000000000000flint2-2.8.4/fq_default/ctx_init_modulus.c000066400000000000000000000040611414523752600206040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default.h" 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 == 1 || (type == 0 && bits*d <= 16 && n_pow(fmpz_get_ui(p), d) < (UWORD(1) << 16))) { nmod_poly_t nmodulus; fq_nmod_ctx_struct * fq_nmod_ctx; ctx->type = 1; nmod_poly_init(nmodulus, fmpz_get_ui(p)); fmpz_mod_poly_get_nmod_poly(nmodulus, modulus); fq_nmod_ctx = flint_malloc(sizeof(fq_nmod_ctx_struct)); fq_nmod_ctx_init_modulus(fq_nmod_ctx, nmodulus, var); if (fq_zech_ctx_init_fq_nmod_ctx_check(ctx->ctx.fq_zech, fq_nmod_ctx)) ctx->ctx.fq_zech->owns_fq_nmod_ctx = 1; else { *ctx->ctx.fq_nmod = *fq_nmod_ctx; flint_free(fq_nmod_ctx); ctx->type = 2; } nmod_poly_clear(nmodulus); } else if (type == 2 || (type == 0 && fmpz_abs_fits_ui(p))) { nmod_poly_t nmodulus; ctx->type = 2; nmod_poly_init(nmodulus, fmpz_get_ui(p)); fmpz_mod_poly_get_nmod_poly(nmodulus, modulus); fq_nmod_ctx_init_modulus(ctx->ctx.fq_nmod, nmodulus, var); nmod_poly_clear(nmodulus); } else { ctx->type = 3; fq_ctx_init_modulus(ctx->ctx.fq, 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); } flint2-2.8.4/fq_default/ctx_init_modulus_nmod.c000066400000000000000000000037211414523752600216230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default.h" 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 == 1 || (type == 0 && bits*d <= 16 && n_pow(p, d) < (UWORD(1) << 16))) { fq_nmod_ctx_struct * fq_nmod_ctx = flint_malloc(sizeof(fq_nmod_ctx_struct)); ctx->type = 1; fq_nmod_ctx_init_modulus(fq_nmod_ctx, modulus, var); if (fq_zech_ctx_init_fq_nmod_ctx_check(ctx->ctx.fq_zech, fq_nmod_ctx)) ctx->ctx.fq_zech->owns_fq_nmod_ctx = 1; else { *ctx->ctx.fq_nmod = *fq_nmod_ctx; flint_free(fq_nmod_ctx); ctx->type = 2; } } else if (type == 2 || type == 0) { ctx->type = 2; fq_nmod_ctx_init_modulus(ctx->ctx.fq_nmod, modulus, var); } else { fmpz_mod_ctx_t fmod_ctx; fmpz_mod_poly_t fmod; fmpz_t p; ctx->type = 3; 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); fq_ctx_init_modulus(ctx->ctx.fq, fmod, fmod_ctx, var); fmpz_mod_poly_clear(fmod, fmod_ctx); fmpz_mod_ctx_clear(fmod_ctx); fmpz_clear(p); } } 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); } flint2-2.8.4/fq_default/ctx_modulus.c000066400000000000000000000016301414523752600175600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default.h" void fq_default_ctx_modulus(fmpz_mod_poly_t p, const fq_default_ctx_t ctx) { if (ctx->type == 1) { nmod_poly_struct const * mod = fq_zech_ctx_modulus(ctx->ctx.fq_zech); fmpz_mod_poly_set_nmod_poly(p, mod); } else if (ctx->type == 2) { nmod_poly_struct const * mod = fq_nmod_ctx_modulus(ctx->ctx.fq_nmod); fmpz_mod_poly_set_nmod_poly(p, mod); } else { fmpz_mod_ctx_struct const * mod = ctx->ctx.fq->ctxp; fmpz_mod_poly_set(p, ctx->ctx.fq->modulus, mod); } } flint2-2.8.4/fq_default/get_fmpz_mod_poly.c000066400000000000000000000022441414523752600207310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 (ctx->type == 1) { nmod_poly_t p; ulong mod = fmpz_get_ui(fq_zech_ctx_prime(ctx->ctx.fq_zech)); nmod_poly_init(p, mod); fq_zech_get_nmod_poly(p, op->fq_zech, ctx->ctx.fq_zech); fmpz_mod_poly_set_nmod_poly(poly, p); nmod_poly_clear(p); } else if (ctx->type == 2) { nmod_poly_t p; ulong mod = fmpz_get_ui(fq_nmod_ctx_prime(ctx->ctx.fq_nmod)); nmod_poly_init(p, mod); fq_nmod_get_nmod_poly(p, op->fq_nmod, ctx->ctx.fq_nmod); fmpz_mod_poly_set_nmod_poly(poly, p); nmod_poly_clear(p); } else { fq_get_fmpz_mod_poly(poly, op->fq, ctx->ctx.fq); } } flint2-2.8.4/fq_default/get_fmpz_poly.c000066400000000000000000000022201414523752600200640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default.h" void fq_default_get_fmpz_poly(fmpz_poly_t poly, const fq_default_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { nmod_poly_t p; ulong mod = fmpz_get_ui(fq_zech_ctx_prime(ctx->ctx.fq_zech)); nmod_poly_init(p, mod); fq_zech_get_nmod_poly(p, op->fq_zech, ctx->ctx.fq_zech); fmpz_poly_set_nmod_poly(poly, p); nmod_poly_clear(p); } else if (ctx->type == 2) { nmod_poly_t p; ulong mod = fmpz_get_ui(fq_nmod_ctx_prime(ctx->ctx.fq_nmod)); nmod_poly_init(p, mod); fq_nmod_get_nmod_poly(p, op->fq_nmod, ctx->ctx.fq_nmod); fmpz_poly_set_nmod_poly(poly, p); nmod_poly_clear(p); } else { fq_get_fmpz_poly(poly, op->fq, ctx->ctx.fq); } } flint2-2.8.4/fq_default/inlines.c000066400000000000000000000011411414523752600166500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_DEFAULT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fq_default.h" flint2-2.8.4/fq_default/set_fmpz_mod_poly.c000066400000000000000000000022371414523752600207470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default.h" void fq_default_set_fmpz_mod_poly(fq_default_t op, const fmpz_mod_poly_t poly, const fq_default_ctx_t ctx) { if (ctx->type == 1) { nmod_poly_t p; ulong mod = fmpz_get_ui(fq_zech_ctx_prime(ctx->ctx.fq_zech)); nmod_poly_init(p, mod); fmpz_mod_poly_get_nmod_poly(p, poly); fq_zech_set_nmod_poly(op->fq_zech, p, ctx->ctx.fq_zech); nmod_poly_clear(p); } else if (ctx->type == 2) { nmod_poly_t p; ulong mod = fmpz_get_ui(fq_nmod_ctx_prime(ctx->ctx.fq_nmod)); nmod_poly_init(p, mod); fmpz_mod_poly_get_nmod_poly(p, poly); fq_nmod_set_nmod_poly(op->fq_nmod, p, ctx->ctx.fq_nmod); nmod_poly_clear(p); } else { fq_set_fmpz_mod_poly(op->fq, poly, ctx->ctx.fq); } } flint2-2.8.4/fq_default/set_fmpz_poly.c000066400000000000000000000022171414523752600201060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default.h" void fq_default_set_fmpz_poly(fq_default_t op, const fmpz_poly_t poly, const fq_default_ctx_t ctx) { if (ctx->type == 1) { nmod_poly_t p; ulong mod = fmpz_get_ui(fq_zech_ctx_prime(ctx->ctx.fq_zech)); nmod_poly_init(p, mod); fmpz_poly_get_nmod_poly(p, poly); fq_zech_set_nmod_poly(op->fq_zech, p, ctx->ctx.fq_zech); nmod_poly_clear(p); } else if (ctx->type == 2) { nmod_poly_t p; ulong mod = fmpz_get_ui(fq_nmod_ctx_prime(ctx->ctx.fq_nmod)); nmod_poly_init(p, mod); fmpz_poly_get_nmod_poly(p, poly); fq_nmod_set_nmod_poly(op->fq_nmod, p, ctx->ctx.fq_nmod); nmod_poly_clear(p); } else { fq_set_fmpz_poly(op->fq, poly, ctx->ctx.fq); } } flint2-2.8.4/fq_default/test/000077500000000000000000000000001414523752600160255ustar00rootroot00000000000000flint2-2.8.4/fq_default/test/t-ctx_init_modulus.c000066400000000000000000000063141414523752600220270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default.h" #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("ctx_init_modulus...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_default/test/t-ctx_init_modulus_nmod.c000066400000000000000000000034241414523752600230430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default.h" #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("ctx_init_modulus_nmod...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_default/test/t-ctx_modulus.c000066400000000000000000000057701414523752600210110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default.h" #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("ctx_modulus...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_mod_poly_clear(mod, mod_ctx); fmpz_mod_ctx_clear(mod_ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_default/test/t-get_set_fmpz_mod_poly.c000066400000000000000000000101751414523752600230260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default.h" #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get/set_fmpz_mod_poly...."); fflush(stdout); /* 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_default/test/t-get_set_fmpz_poly.c000066400000000000000000000072611414523752600221710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default.h" #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get/set_fmpz_poly...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_poly_clear(f); fq_default_clear(fq1, ctx); fq_default_clear(fq2, ctx); fq_default_ctx_clear(ctx); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_default/test/t-init.c000066400000000000000000000031071414523752600173760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default.h" #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_default_mat.h000066400000000000000000000645511414523752600160730ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FQ_DEFAULT_MAT_INLINE static __inline__ #endif #include "ulong_extras.h" #include "fmpz.h" #include "fq.h" #include "fq_nmod.h" #include "fq_zech.h" #include "fq_default.h" #include "fq_mat.h" #include "fq_nmod_mat.h" #include "fq_zech_mat.h" #include "flint.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; } 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 (ctx->type == 1) { fq_zech_mat_init(mat->fq_zech, rows, cols, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_init(mat->fq_nmod, rows, cols, ctx->ctx.fq_nmod); } else { fq_mat_init(mat->fq, rows, cols, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_init_set(mat->fq_zech, src->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_init_set(mat->fq_nmod, src->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_init_set(mat->fq, src->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_swap(mat1->fq_zech, mat2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_swap(mat1->fq_nmod, mat2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_swap(mat1->fq, mat2->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_set(mat1->fq_zech, mat2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_set(mat1->fq_nmod, mat2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_set(mat1->fq, mat2->fq, ctx->ctx.fq); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_clear(fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_mat_clear(mat->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_clear(mat->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_clear(mat->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { return fq_zech_mat_equal(mat1->fq_zech, mat2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_equal(mat1->fq_nmod, mat2->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_equal(mat1->fq, mat2->fq, ctx->ctx.fq); } FQ_DEFAULT_MAT_INLINE int fq_default_mat_is_zero(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_mat_is_zero(mat->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_is_zero(mat->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_is_zero(mat->fq, ctx->ctx.fq); } FQ_DEFAULT_MAT_INLINE int fq_default_mat_is_one(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_mat_is_one(mat->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_is_one(mat->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_is_one(mat->fq, ctx->ctx.fq); } FQ_DEFAULT_MAT_INLINE int fq_default_mat_is_empty(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_mat_is_empty(mat->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_is_empty(mat->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_is_empty(mat->fq, ctx->ctx.fq); } FQ_DEFAULT_MAT_INLINE int fq_default_mat_is_square(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_mat_is_square(mat->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_is_square(mat->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_is_square(mat->fq, ctx->ctx.fq); } 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 (ctx->type == 1) { fq_zech_set(val->fq_zech, fq_zech_mat_entry(mat->fq_zech, i, j), ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_set(val->fq_nmod, fq_nmod_mat_entry(mat->fq_nmod, i, j), ctx->ctx.fq_nmod); } else { fq_set(val->fq, fq_mat_entry(mat->fq, i, j), ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_entry_set(mat->fq_zech, i, j, x->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_entry_set(mat->fq_nmod, i, j, x->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_entry_set(mat->fq, i, j, x->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { return fq_zech_mat_nrows(mat->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_nrows(mat->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_nrows(mat->fq, ctx->ctx.fq); } FQ_DEFAULT_MAT_INLINE slong fq_default_mat_ncols(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_mat_ncols(mat->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_ncols(mat->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_ncols(mat->fq, ctx->ctx.fq); } 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 (ctx->type == 1) { fq_zech_mat_swap_rows(mat->fq_zech, perm, r, s, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_swap_rows(mat->fq_nmod, perm, r, s, ctx->ctx.fq_nmod); } else { fq_mat_swap_rows(mat->fq, perm, r, s, ctx->ctx.fq); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_invert_rows(fq_default_mat_t mat, slong * perm, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_mat_invert_rows(mat->fq_zech, perm, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_invert_rows(mat->fq_nmod, perm, ctx->ctx.fq_nmod); } else { fq_mat_invert_rows(mat->fq, perm, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_swap_cols(mat->fq_zech, perm, r, s, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_swap_cols(mat->fq_nmod, perm, r, s, ctx->ctx.fq_nmod); } else { fq_mat_swap_cols(mat->fq, perm, r, s, ctx->ctx.fq); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_invert_cols(fq_default_mat_t mat, slong * perm, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_mat_invert_cols(mat->fq_zech, perm, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_invert_cols(mat->fq_nmod, perm, ctx->ctx.fq_nmod); } else { fq_mat_invert_cols(mat->fq, perm, ctx->ctx.fq); } } /* Assignment ***************************************************************/ FQ_DEFAULT_MAT_INLINE void fq_default_mat_zero(fq_default_mat_t A, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_mat_zero(A->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_zero(A->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_zero(A->fq, ctx->ctx.fq); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_one(fq_default_mat_t A, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_mat_one(A->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_one(A->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_one(A->fq, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_mat_set_nmod_mat(mat1->fq_zech, mat2, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_set_nmod_mat(mat1->fq_nmod, mat2, ctx->ctx.fq_nmod); } else { fq_mat_set_nmod_mat(mat1->fq, mat2, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_set_fmpz_mod_mat(mat1->fq_zech, mat2, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_set_fmpz_mod_mat(mat1->fq_nmod, mat2, ctx->ctx.fq_nmod); } else { fq_mat_set_fmpz_mod_mat(mat1->fq, mat2, ctx->ctx.fq); } } 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 (ctx->type == 1) { fmpz_mod_mat_init(mod_mat, mat2->r, mat2->c, fq_zech_ctx_prime(ctx->ctx.fq_zech)); fmpz_mod_mat_set_fmpz_mat(mod_mat, mat2); fq_zech_mat_set_fmpz_mod_mat(mat1->fq_zech, mod_mat, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fmpz_mod_mat_init(mod_mat, mat2->r, mat2->c, fq_nmod_ctx_prime(ctx->ctx.fq_nmod)); fmpz_mod_mat_set_fmpz_mat(mod_mat, mat2); fq_nmod_mat_set_fmpz_mod_mat(mat1->fq_nmod, mod_mat, ctx->ctx.fq_nmod); } else { fmpz_mod_mat_init(mod_mat, mat2->r, mat2->c, fq_ctx_prime(ctx->ctx.fq)); fmpz_mod_mat_set_fmpz_mat(mod_mat, mat2); fq_mat_set_fmpz_mod_mat(mat1->fq, mod_mat, ctx->ctx.fq); } fmpz_mod_mat_clear(mod_mat); } /* 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 (ctx->type == 1) { fq_zech_mat_window_init(window->fq_zech, mat->fq_zech, r1, c1, r2, c2, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_window_init(window->fq_nmod, mat->fq_nmod, r1, c1, r2, c2, ctx->ctx.fq_nmod); } else { fq_mat_window_init(window->fq, mat->fq, r1, c1, r2, c2, ctx->ctx.fq); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_window_clear(fq_default_mat_t window, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_mat_window_clear(window->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_window_clear(window->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_window_clear(window->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_concat_horizontal(res->fq_zech, mat1->fq_zech, mat2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_concat_horizontal(res->fq_nmod, mat1->fq_nmod, mat2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_concat_horizontal(res->fq, mat1->fq, mat2->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_concat_vertical(res->fq_zech, mat1->fq_zech, mat2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_concat_vertical(res->fq_nmod, mat1->fq_nmod, mat2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_concat_vertical(res->fq, mat1->fq, mat2->fq, ctx->ctx.fq); } } /* Input and output *********************************************************/ FQ_DEFAULT_MAT_INLINE int fq_default_mat_fprint(FILE * file, const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_mat_fprint(file, mat->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_fprint(file, mat->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_fprint(file, mat->fq, ctx->ctx.fq); } FQ_DEFAULT_MAT_INLINE int fq_default_mat_fprint_pretty(FILE * file, const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_mat_fprint_pretty(file, mat->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_fprint_pretty(file, mat->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_fprint_pretty(file, mat->fq, ctx->ctx.fq); } FQ_DEFAULT_MAT_INLINE int fq_default_mat_print(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_mat_print(mat->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_print(mat->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_print(mat->fq, ctx->ctx.fq); } FQ_DEFAULT_MAT_INLINE int fq_default_mat_print_pretty(const fq_default_mat_t mat, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_mat_print_pretty(mat->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_print_pretty(mat->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_print_pretty(mat->fq, ctx->ctx.fq); } /* 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 (ctx->type == 1) { fq_zech_mat_randtest(mat->fq_zech, state, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_randtest(mat->fq_nmod, state, ctx->ctx.fq_nmod); } else { fq_mat_randtest(mat->fq, state, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_randrank(mat->fq_zech, state, rank, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_randrank(mat->fq_nmod, state, rank, ctx->ctx.fq_nmod); } else { fq_mat_randrank(mat->fq, state, rank, ctx->ctx.fq); } } FQ_DEFAULT_MAT_INLINE void fq_default_mat_randops(fq_default_mat_t mat, slong count, flint_rand_t state, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_mat_randops(mat->fq_zech, count, state, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_randops(mat->fq_nmod, count, state, ctx->ctx.fq_nmod); } else { fq_mat_randops(mat->fq, count, state, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_randtril(mat->fq_zech, state, unit, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_randtril(mat->fq_nmod, state, unit, ctx->ctx.fq_nmod); } else { fq_mat_randtril(mat->fq, state, unit, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_randtriu(mat->fq_zech, state, unit, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_randtriu(mat->fq_nmod, state, unit, ctx->ctx.fq_nmod); } else { fq_mat_randtriu(mat->fq, state, unit, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_mat_add(C->fq_zech, A->fq_zech, B->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_add(C->fq_nmod, A->fq_nmod, B->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_add(C->fq, A->fq, B->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_sub(C->fq_zech, A->fq_zech, B->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_sub(C->fq_nmod, A->fq_nmod, B->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_sub(C->fq, A->fq, B->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_neg(B->fq_zech, A->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_neg(B->fq_nmod, A->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_neg(B->fq, A->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_submul(D->fq_zech, C->fq_zech, A->fq_zech, B->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_submul(D->fq_nmod, C->fq_nmod, A->fq_nmod, B->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_submul(D->fq, C->fq, A->fq, B->fq, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_mat_mul(C->fq_zech, A->fq_zech, B->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_mul(C->fq_nmod, A->fq_nmod, B->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_mul(C->fq, A->fq, B->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { return fq_zech_mat_lu(P, A->fq_zech, rank_check, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_lu(P, A->fq_nmod, rank_check, ctx->ctx.fq_nmod); } return fq_mat_lu(P, A->fq, rank_check, ctx->ctx.fq); } /* 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 (ctx->type == 1) { return fq_zech_mat_inv(B->fq_zech, A->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_inv(B->fq_nmod, A->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_inv(B->fq, A->fq, ctx->ctx.fq); } /* Solving *******************************************************************/ FQ_DEFAULT_MAT_INLINE slong fq_default_mat_rref(fq_default_mat_t A, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_mat_rref(A->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_rref(A->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_rref(A->fq, ctx->ctx.fq); } 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 (ctx->type == 1) { return fq_zech_mat_nullspace(X->fq_zech, A->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_nullspace(X->fq_nmod, A->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_nullspace(X->fq, A->fq, ctx->ctx.fq); } FQ_DEFAULT_MAT_INLINE slong fq_default_mat_rank(const fq_default_mat_t A, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_mat_rank(A->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_rank(A->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_rank(A->fq, ctx->ctx.fq); } 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 (ctx->type == 1) { fq_zech_mat_solve_tril(X->fq_zech, L->fq_zech, B->fq_zech, unit, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_solve_tril(X->fq_nmod, L->fq_nmod, B->fq_nmod, unit, ctx->ctx.fq_nmod); } else { fq_mat_solve_tril(X->fq, L->fq, B->fq, unit, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_mat_solve_triu(X->fq_zech, U->fq_zech, B->fq_zech, unit, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_solve_triu(X->fq_nmod, U->fq_nmod, B->fq_nmod, unit, ctx->ctx.fq_nmod); } else { fq_mat_solve_triu(X->fq, U->fq, B->fq, unit, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { return fq_zech_mat_solve(X->fq_zech, A->fq_zech, C->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_solve(X->fq_nmod, A->fq_nmod, C->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_solve(X->fq, A->fq, C->fq, ctx->ctx.fq); } /* 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 (ctx->type == 1) { return fq_zech_mat_can_solve(X->fq_zech, A->fq_zech, B->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_mat_can_solve(X->fq_nmod, A->fq_nmod, B->fq_nmod, ctx->ctx.fq_nmod); } return fq_mat_can_solve(X->fq, A->fq, B->fq, ctx->ctx.fq); } /* 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 (ctx->type == 1) { fq_zech_mat_similarity(A->fq_zech, r, d->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_similarity(A->fq_nmod, r, d->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_similarity(A->fq, r, d->fq, ctx->ctx.fq); } } /* 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 flint2-2.8.4/fq_default_mat/000077500000000000000000000000001414523752600157075ustar00rootroot00000000000000flint2-2.8.4/fq_default_mat/inlines.c000066400000000000000000000012011414523752600175060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_DEFAULT_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fq_default.h" #include "fq_default_mat.h" flint2-2.8.4/fq_default_mat/test/000077500000000000000000000000001414523752600166665ustar00rootroot00000000000000flint2-2.8.4/fq_default_mat/test/t-init.c000066400000000000000000000033761414523752600202470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default_mat.h" #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_default_mat/test/t-set_fmpz_mat.c000066400000000000000000000072521414523752600217710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default_mat.h" #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_fmpz_mat...."); fflush(stdout); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_default_poly.h000066400000000000000000001235471414523752600162760ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FQ_DEFAULT_POLY_INLINE static __inline__ #endif #include "ulong_extras.h" #include "fmpz.h" #include "fq.h" #include "fq_nmod.h" #include "fq_zech.h" #include "fq_default.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; } 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 (ctx->type == 1) { fq_zech_poly_init(poly->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_init(poly->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_init(poly->fq, ctx->ctx.fq); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_init2(fq_default_poly_t poly, slong alloc, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_poly_init2(poly->fq_zech, alloc, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_init2(poly->fq_nmod, alloc, ctx->ctx.fq_nmod); } else { fq_poly_init2(poly->fq, alloc, ctx->ctx.fq); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_realloc(fq_default_poly_t poly, slong alloc, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_poly_realloc(poly->fq_zech, alloc, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_realloc(poly->fq_nmod, alloc, ctx->ctx.fq_nmod); } else { fq_poly_realloc(poly->fq, alloc, ctx->ctx.fq); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_truncate(fq_default_poly_t poly, slong len, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_poly_truncate(poly->fq_zech, len, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_truncate(poly->fq_nmod, len, ctx->ctx.fq_nmod); } else { fq_poly_truncate(poly->fq, len, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_set_trunc(poly1->fq_zech, poly2->fq_zech, len, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_set_trunc(poly1->fq_nmod, poly2->fq_nmod, len, ctx->ctx.fq_nmod); } else { fq_poly_set_trunc(poly1->fq, poly2->fq, len, ctx->ctx.fq); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_fit_length(fq_default_poly_t poly, slong len, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_poly_fit_length(poly->fq_zech, len, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_fit_length(poly->fq_nmod, len, ctx->ctx.fq_nmod); } else { fq_poly_fit_length(poly->fq, len, ctx->ctx.fq); } } FQ_DEFAULT_POLY_INLINE void _fq_default_poly_set_length(fq_default_poly_t poly, slong len, const fq_default_ctx_t ctx) { if (ctx->type == 1) { _fq_zech_poly_set_length(poly->fq_zech, len, ctx->ctx.fq_zech); } else if (ctx->type == 2) { _fq_nmod_poly_set_length(poly->fq_nmod, len, ctx->ctx.fq_nmod); } else { _fq_poly_set_length(poly->fq, len, ctx->ctx.fq); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_clear(fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_poly_clear(poly->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_clear(poly->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_clear(poly->fq, ctx->ctx.fq); } } /* Polynomial parameters ***************************************************/ FQ_DEFAULT_POLY_INLINE slong fq_default_poly_length(const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_length(poly->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_length(poly->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_length(poly->fq, ctx->ctx.fq); } FQ_DEFAULT_POLY_INLINE slong fq_default_poly_degree(const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_degree(poly->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_degree(poly->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_degree(poly->fq, ctx->ctx.fq); } /* 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 (ctx->type == 1) { fq_zech_poly_randtest(f->fq_zech, state, len, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_randtest(f->fq_nmod, state, len, ctx->ctx.fq_nmod); } else { fq_poly_randtest(f->fq, state, len, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_randtest_not_zero(f->fq_zech, state, len, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_randtest_not_zero(f->fq_nmod, state, len, ctx->ctx.fq_nmod); } else { fq_poly_randtest_not_zero(f->fq, state, len, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_randtest_monic(f->fq_zech, state, len, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_randtest_monic(f->fq_nmod, state, len, ctx->ctx.fq_nmod); } else { fq_poly_randtest_monic(f->fq, state, len, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_randtest_irreducible(f->fq_zech, state, len, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_randtest_irreducible(f->fq_nmod, state, len, ctx->ctx.fq_nmod); } else { fq_poly_randtest_irreducible(f->fq, state, len, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_poly_set(rop->fq_zech, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_set(rop->fq_nmod, op->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_set(rop->fq, op->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_set_fq_zech(poly->fq_zech, c->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_set_fq_nmod(poly->fq_nmod, c->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_set_fq(poly->fq, c->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_swap(op1->fq_zech, op2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_swap(op1->fq_nmod, op2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_swap(op1->fq, op2->fq, ctx->ctx.fq); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_zero(fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_poly_zero(poly->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_zero(poly->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_zero(poly->fq, ctx->ctx.fq); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_one(fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_poly_one(poly->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_one(poly->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_one(poly->fq, ctx->ctx.fq); } } FQ_DEFAULT_POLY_INLINE void fq_default_poly_gen(fq_default_poly_t f, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_poly_gen(f->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_gen(f->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_gen(f->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_make_monic(rop->fq_zech, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_make_monic(rop->fq_nmod, op->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_make_monic(rop->fq, op->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_reverse(res->fq_zech, poly->fq_zech, n, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_reverse(res->fq_nmod, poly->fq_nmod, n, ctx->ctx.fq_nmod); } else { fq_poly_reverse(res->fq, poly->fq, n, ctx->ctx.fq); } } FQ_DEFAULT_POLY_INLINE ulong fq_default_poly_deflation(const fq_default_poly_t input, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_deflation(input->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_deflation(input->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_deflation(input->fq, ctx->ctx.fq); } 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 (ctx->type == 1) { fq_zech_poly_deflate(result->fq_zech, input->fq_zech, deflation, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_deflate(result->fq_nmod, input->fq_nmod, deflation, ctx->ctx.fq_nmod); } else { fq_poly_deflate(result->fq, input->fq, deflation, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_inflate(result->fq_zech, input->fq_zech, inflation, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_inflate(result->fq_nmod, input->fq_nmod, inflation, ctx->ctx.fq_nmod); } else { fq_poly_inflate(result->fq, input->fq, inflation, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_poly_get_coeff(x->fq_zech, poly->fq_zech, n, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_get_coeff(x->fq_nmod, poly->fq_nmod, n, ctx->ctx.fq_nmod); } else { fq_poly_get_coeff(x->fq, poly->fq, n, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_set_coeff(poly->fq_zech, n, x->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_set_coeff(poly->fq_nmod, n, x->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_set_coeff(poly->fq, n, x->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_set_coeff_fmpz(poly->fq_zech, n, x, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_set_coeff_fmpz(poly->fq_nmod, n, x, ctx->ctx.fq_nmod); } else { fq_poly_set_coeff_fmpz(poly->fq, n, x, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_set_nmod_poly(rop->fq_zech, op, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_set_nmod_poly(rop->fq_nmod, op, ctx->ctx.fq_nmod); } else { fq_poly_set_nmod_poly(rop->fq, op, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_set_fmpz_mod_poly(rop->fq_zech, op, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_set_fmpz_mod_poly(rop->fq_nmod, op, ctx->ctx.fq_nmod); } else { fq_poly_set_fmpz_mod_poly(rop->fq, op, ctx->ctx.fq); } } FLINT_DLL 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 (ctx->type == 1) { return fq_zech_poly_equal(poly1->fq_zech, poly2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_equal(poly1->fq_nmod, poly2->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_equal(poly1->fq, poly2->fq, ctx->ctx.fq); } 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 (ctx->type == 1) { return fq_zech_poly_equal_trunc(poly1->fq_zech, poly2->fq_zech, n, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_equal_trunc(poly1->fq_nmod, poly2->fq_nmod, n, ctx->ctx.fq_nmod); } return fq_poly_equal_trunc(poly1->fq, poly2->fq, n, ctx->ctx.fq); } FQ_DEFAULT_POLY_INLINE int fq_default_poly_is_zero(const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_is_zero(poly->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_is_zero(poly->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_is_zero(poly->fq, ctx->ctx.fq); } FQ_DEFAULT_POLY_INLINE int fq_default_poly_is_one(const fq_default_poly_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_is_one(op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_is_one(op->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_is_one(op->fq, ctx->ctx.fq); } FQ_DEFAULT_POLY_INLINE int fq_default_poly_is_unit(const fq_default_poly_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_is_unit(op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_is_unit(op->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_is_unit(op->fq, ctx->ctx.fq); } FQ_DEFAULT_POLY_INLINE int fq_default_poly_is_gen(const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_is_gen(poly->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_is_gen(poly->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_is_gen(poly->fq, ctx->ctx.fq); } 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 (ctx->type == 1) { return fq_zech_poly_equal_fq_zech(poly->fq_zech, c->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_equal_fq_nmod(poly->fq_nmod, c->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_equal_fq(poly->fq, c->fq, ctx->ctx.fq); } /* 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 (ctx->type == 1) { fq_zech_poly_add(rop->fq_zech, op1->fq_zech, op2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_add(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_add(rop->fq, op1->fq, op2->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_add_si(rop->fq_zech, op1->fq_zech, c, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_add_si(rop->fq_nmod, op1->fq_nmod, c, ctx->ctx.fq_nmod); } else { fq_poly_add_si(rop->fq, op1->fq, c, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_add_series(rop->fq_zech, op1->fq_zech, op2->fq_zech, n, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_add_series(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, n, ctx->ctx.fq_nmod); } else { fq_poly_add_series(rop->fq, op1->fq, op2->fq, n, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_sub(rop->fq_zech, op1->fq_zech, op2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_sub(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_sub(rop->fq, op1->fq, op2->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_sub_series(rop->fq_zech, op1->fq_zech, op2->fq_zech, n, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_sub_series(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, n, ctx->ctx.fq_nmod); } else { fq_poly_sub_series(rop->fq, op1->fq, op2->fq, n, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_neg(rop->fq_zech, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_neg(rop->fq_nmod, op->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_neg(rop->fq, op->fq, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_poly_scalar_mul_fq_zech(rop->fq_zech, op->fq_zech, x->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_scalar_mul_fq_nmod(rop->fq_nmod, op->fq_nmod, x->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_scalar_mul_fq(rop->fq, op->fq, x->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_scalar_div_fq_zech(rop->fq_zech, op->fq_zech, x->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_scalar_div_fq_nmod(rop->fq_nmod, op->fq_nmod, x->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_scalar_div_fq(rop->fq, op->fq, x->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_scalar_addmul_fq_zech(rop->fq_zech, op->fq_zech, x->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_scalar_addmul_fq_nmod(rop->fq_nmod, op->fq_nmod, x->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_scalar_addmul_fq(rop->fq, op->fq, x->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_scalar_submul_fq_zech(rop->fq_zech, op->fq_zech, x->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_scalar_submul_fq_nmod(rop->fq_nmod, op->fq_nmod, x->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_scalar_submul_fq(rop->fq, op->fq, x->fq, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_poly_mul(rop->fq_zech, op1->fq_zech, op2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_mul(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_mul(rop->fq, op1->fq, op2->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_mullow(rop->fq_zech, op1->fq_zech, op2->fq_zech, n, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_mullow(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, n, ctx->ctx.fq_nmod); } else { fq_poly_mullow(rop->fq, op1->fq, op2->fq, n, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_mulhigh(rop->fq_zech, op1->fq_zech, op2->fq_zech, start, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_mulhigh(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, start, ctx->ctx.fq_nmod); } else { fq_poly_mulhigh(rop->fq, op1->fq, op2->fq, start, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_mulmod(res->fq_zech, poly1->fq_zech, poly2->fq_zech, f->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_mulmod(res->fq_nmod, poly1->fq_nmod, poly2->fq_nmod, f->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_mulmod(res->fq, poly1->fq, poly2->fq, f->fq, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_poly_sqr(rop->fq_zech, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_sqr(rop->fq_nmod, op->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_sqr(rop->fq, op->fq, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_poly_pow(rop->fq_zech, op->fq_zech, e, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_pow(rop->fq_nmod, op->fq_nmod, e, ctx->ctx.fq_nmod); } else { fq_poly_pow(rop->fq, op->fq, e, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_pow_trunc(res->fq_zech, poly->fq_zech, e, trunc, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_pow_trunc(res->fq_nmod, poly->fq_nmod, e, trunc, ctx->ctx.fq_nmod); } else { fq_poly_pow_trunc(res->fq, poly->fq, e, trunc, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_powmod_fmpz_binexp(res->fq_zech, poly->fq_zech, e, f->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_powmod_fmpz_binexp(res->fq_nmod, poly->fq_nmod, e, f->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_powmod_fmpz_binexp(res->fq, poly->fq, e, f->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_powmod_ui_binexp(res->fq_zech, poly->fq_zech, e, f->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_powmod_ui_binexp(res->fq_nmod, poly->fq_nmod, e, f->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_powmod_ui_binexp(res->fq, poly->fq, e, f->fq, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_poly_shift_left(rop->fq_zech, op->fq_zech, n, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_shift_left(rop->fq_nmod, op->fq_nmod, n, ctx->ctx.fq_nmod); } else { fq_poly_shift_left(rop->fq, op->fq, n, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_shift_right(rop->fq_zech, op->fq_zech, n, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_shift_right(rop->fq_nmod, op->fq_nmod, n, ctx->ctx.fq_nmod); } else { fq_poly_shift_right(rop->fq, op->fq, n, ctx->ctx.fq); } } /* Norms *******************************************************************/ FQ_DEFAULT_POLY_INLINE slong fq_default_poly_hamming_weight(const fq_default_poly_t op, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_hamming_weight(op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_hamming_weight(op->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_hamming_weight(op->fq, ctx->ctx.fq); } /* 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 (ctx->type == 1) { fq_zech_poly_gcd(rop->fq_zech, op1->fq_zech, op2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_gcd(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_gcd(rop->fq, op1->fq, op2->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_xgcd(G->fq_zech, S->fq_zech, T->fq_zech, A->fq_zech, B->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_xgcd(G->fq_nmod, S->fq_nmod, T->fq_nmod, A->fq_nmod, B->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_xgcd(G->fq, S->fq, T->fq, A->fq, B->fq, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { return fq_zech_poly_remove(f->fq_zech, g->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_remove(f->fq_nmod, g->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_remove(f->fq, g->fq, ctx->ctx.fq); } 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 (ctx->type == 1) { fq_zech_poly_divrem(Q->fq_zech, R->fq_zech, A->fq_zech, B->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_divrem(Q->fq_nmod, R->fq_nmod, A->fq_nmod, B->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_divrem(Q->fq, R->fq, A->fq, B->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_rem(R->fq_zech, A->fq_zech, B->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_rem(R->fq_nmod, A->fq_nmod, B->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_rem(R->fq, A->fq, B->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_inv_series(Qinv->fq_zech, Q->fq_zech, n, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_inv_series(Qinv->fq_nmod, Q->fq_nmod, n, ctx->ctx.fq_nmod); } else { fq_poly_inv_series(Qinv->fq, Q->fq, n, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_div_series(Q->fq_zech, A->fq_zech, B->fq_zech, n, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_div_series(Q->fq_nmod, A->fq_nmod, B->fq_nmod, n, ctx->ctx.fq_nmod); } else { fq_poly_div_series(Q->fq, A->fq, B->fq, n, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { return fq_zech_poly_divides(Q->fq_zech, A->fq_zech, B->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_divides(Q->fq_nmod, A->fq_nmod, B->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_divides(Q->fq, A->fq, B->fq, ctx->ctx.fq); } /* 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 (ctx->type == 1) { fq_zech_poly_derivative(rop->fq_zech, op->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_derivative(rop->fq_nmod, op->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_derivative(rop->fq, op->fq, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_poly_evaluate_fq_zech(res->fq_zech, f->fq_zech, a->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_evaluate_fq_nmod(res->fq_nmod, f->fq_nmod, a->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_evaluate_fq(res->fq, f->fq, a->fq, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_poly_compose(rop->fq_zech, op1->fq_zech, op2->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_compose(rop->fq_nmod, op1->fq_nmod, op2->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_compose(rop->fq, op1->fq, op2->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_compose_mod(res->fq_zech, poly1->fq_zech, poly2->fq_zech, poly3->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_compose_mod(res->fq_nmod, poly1->fq_nmod, poly2->fq_nmod, poly3->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_compose_mod(res->fq, poly1->fq, poly2->fq, poly3->fq, ctx->ctx.fq); } } /* Input and output ********************************************************/ FQ_DEFAULT_POLY_INLINE int fq_default_poly_fprint_pretty(FILE * file, const fq_default_poly_t poly, const char *x, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_fprint_pretty(file, poly->fq_zech, x, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_fprint_pretty(file, poly->fq_nmod, x, ctx->ctx.fq_nmod); } return fq_poly_fprint_pretty(file, poly->fq, x, ctx->ctx.fq); } FQ_DEFAULT_POLY_INLINE int fq_default_poly_fprint(FILE * file, const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_fprint(file, poly->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_fprint(file, poly->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_fprint(file, poly->fq, ctx->ctx.fq); } FQ_DEFAULT_POLY_INLINE int fq_default_poly_print(const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_print(poly->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_print(poly->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_print(poly->fq, ctx->ctx.fq); } FQ_DEFAULT_POLY_INLINE int fq_default_poly_print_pretty(const fq_default_poly_t poly, const char *x, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_print_pretty(poly->fq_zech, x, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_print_pretty(poly->fq_nmod, x, ctx->ctx.fq_nmod); } return fq_poly_print_pretty(poly->fq, x, ctx->ctx.fq); } 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 (ctx->type == 1) { return fq_zech_poly_get_str_pretty(poly->fq_zech, x, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_get_str_pretty(poly->fq_nmod, x, ctx->ctx.fq_nmod); } return fq_poly_get_str_pretty(poly->fq, x, ctx->ctx.fq); } FQ_DEFAULT_POLY_INLINE char * fq_default_poly_get_str(const fq_default_poly_t poly, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_get_str(poly->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_get_str(poly->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_get_str(poly->fq, ctx->ctx.fq); } #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 (ctx->type == 1) { fq_zech_mat_charpoly(p->fq_zech, M->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_charpoly(p->fq_nmod, M->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_charpoly(p->fq, M->fq, ctx->ctx.fq); } } /* 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 (ctx->type == 1) { fq_zech_mat_minpoly(p->fq_zech, X->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_mat_minpoly(p->fq_nmod, X->fq_nmod, ctx->ctx.fq_nmod); } else { fq_mat_minpoly(p->fq, X->fq, ctx->ctx.fq); } } #ifdef __cplusplus } #endif #endif flint2-2.8.4/fq_default_poly/000077500000000000000000000000001414523752600161115ustar00rootroot00000000000000flint2-2.8.4/fq_default_poly/inlines.c000066400000000000000000000012031414523752600177120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_DEFAULT_POLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fq_default.h" #include "fq_default_poly.h" flint2-2.8.4/fq_default_poly/set_fmpz_poly.c000066400000000000000000000020721414523752600211500ustar00rootroot00000000000000/* 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 2.1 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 const * p; fmpz_mod_ctx_t mod; fmpz_mod_poly_t mod_poly; if (ctx->type == 1) { p = fq_zech_ctx_prime(ctx->ctx.fq_zech); } else if (ctx->type == 2) { p = fq_nmod_ctx_prime(ctx->ctx.fq_nmod); } else { p = fq_ctx_prime(ctx->ctx.fq); } fmpz_mod_ctx_init(mod, p); 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); } flint2-2.8.4/fq_default_poly/test/000077500000000000000000000000001414523752600170705ustar00rootroot00000000000000flint2-2.8.4/fq_default_poly/test/t-init.c000066400000000000000000000033621414523752600204440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default_poly.h" #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_default_poly/test/t-set_fmpz_poly.c000066400000000000000000000066341414523752600224000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default_poly.h" #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_fmpz_poly...."); fflush(stdout); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_default_poly_factor.h000066400000000000000000000271661414523752600176340ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FQ_DEFAULT_POLY_FACTOR_INLINE static __inline__ #endif #include "ulong_extras.h" #include "fmpz.h" #include "fq.h" #include "fq_nmod.h" #include "fq_zech.h" #include "fq_default.h" #include "fq_poly.h" #include "fq_nmod_poly.h" #include "fq_zech_poly.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; } 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 (ctx->type == 1) { fq_zech_poly_factor_init(fac->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_init(fac->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_factor_init(fac->fq, ctx->ctx.fq); } } FQ_DEFAULT_POLY_FACTOR_INLINE void fq_default_poly_factor_clear(fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) { if (ctx->type == 1) { fq_zech_poly_factor_clear(fac->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_clear(fac->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_factor_clear(fac->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_factor_realloc(fac->fq_zech, alloc, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_realloc(fac->fq_nmod, alloc, ctx->ctx.fq_nmod); } else { fq_poly_factor_realloc(fac->fq, alloc, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_factor_fit_length(fac->fq_zech, len, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_fit_length(fac->fq_nmod, len, ctx->ctx.fq_nmod); } else { fq_poly_factor_fit_length(fac->fq, len, ctx->ctx.fq); } } FQ_DEFAULT_POLY_FACTOR_INLINE slong fq_default_poly_factor_length(fq_default_poly_factor_t fac, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fac->fq_zech->num; } else if (ctx->type == 2) { return fac->fq_nmod->num; } 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 (ctx->type == 1) { return fac->fq_zech->exp[i]; } else if (ctx->type == 2) { return fac->fq_nmod->exp[i]; } 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 (ctx->type == 1) { fq_zech_poly_factor_set(res->fq_zech, fac->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_set(res->fq_nmod, fac->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_factor_set(res->fq, fac->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_factor_insert(fac->fq_zech, poly->fq_zech, exp, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_insert(fac->fq_nmod, poly->fq_nmod, exp, ctx->ctx.fq_nmod); } else { fq_poly_factor_insert(fac->fq, poly->fq, exp, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_factor_get_poly(poly->fq_zech, fac->fq_zech, i, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_get_poly(poly->fq_nmod, fac->fq_nmod, i, ctx->ctx.fq_nmod); } else { fq_poly_factor_get_poly(poly->fq, fac->fq, i, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_factor_print(fac->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_print(fac->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_factor_print(fac->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_factor_print_pretty(fac->fq_zech, var, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_print_pretty(fac->fq_nmod, var, ctx->ctx.fq_nmod); } else { fq_poly_factor_print_pretty(fac->fq, var, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_factor_concat(res->fq_zech, fac->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_concat(res->fq_nmod, fac->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_factor_concat(res->fq, fac->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_factor_pow(fac->fq_zech, exp, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_pow(fac->fq_nmod, exp, ctx->ctx.fq_nmod); } else { fq_poly_factor_pow(fac->fq, exp, ctx->ctx.fq); } } FQ_DEFAULT_POLY_FACTOR_INLINE int fq_default_poly_is_squarefree(const fq_default_poly_t f, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_is_squarefree(f->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_is_squarefree(f->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_is_squarefree(f->fq, ctx->ctx.fq); } 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 (ctx->type == 1) { fq_zech_poly_factor_squarefree(res->fq_zech, f->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_squarefree(res->fq_nmod, f->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_factor_squarefree(res->fq, f->fq, ctx->ctx.fq); } } FQ_DEFAULT_POLY_FACTOR_INLINE int fq_default_poly_is_irreducible(const fq_default_poly_t f, const fq_default_ctx_t ctx) { if (ctx->type == 1) { return fq_zech_poly_is_irreducible(f->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { return fq_nmod_poly_is_irreducible(f->fq_nmod, ctx->ctx.fq_nmod); } return fq_poly_is_irreducible(f->fq, ctx->ctx.fq); } 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 (ctx->type == 1) { fq_zech_poly_factor_distinct_deg(res->fq_zech, poly->fq_zech, degs, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_distinct_deg(res->fq_nmod, poly->fq_nmod, degs, ctx->ctx.fq_nmod); } else { fq_poly_factor_distinct_deg(res->fq, poly->fq, degs, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_factor_equal_deg(factors->fq_zech, pol->fq_zech, d, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_equal_deg(factors->fq_nmod, pol->fq_nmod, d, ctx->ctx.fq_nmod); } else { fq_poly_factor_equal_deg(factors->fq, pol->fq, d, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_factor(result->fq_zech, leading_coeff->fq_zech, input->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor(result->fq_nmod, leading_coeff->fq_nmod, input->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_factor(result->fq, leading_coeff->fq, input->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_factor_split_single(linfactor->fq_zech, input->fq_zech, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_factor_split_single(linfactor->fq_nmod, input->fq_nmod, ctx->ctx.fq_nmod); } else { fq_poly_factor_split_single(linfactor->fq, input->fq, ctx->ctx.fq); } } 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 (ctx->type == 1) { fq_zech_poly_roots(r->fq_zech, f->fq_zech, with_multiplicity, ctx->ctx.fq_zech); } else if (ctx->type == 2) { fq_nmod_poly_roots(r->fq_nmod, f->fq_nmod, with_multiplicity, ctx->ctx.fq_nmod); } else { fq_poly_roots(r->fq, f->fq, with_multiplicity, ctx->ctx.fq); } } #ifdef __cplusplus } #endif #endif flint2-2.8.4/fq_default_poly_factor/000077500000000000000000000000001414523752600174475ustar00rootroot00000000000000flint2-2.8.4/fq_default_poly_factor/inlines.c000066400000000000000000000012551414523752600212570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_DEFAULT_POLY_FACTOR_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fq_default.h" #include "fq_default_poly.h" #include "fq_default_poly_factor.h" flint2-2.8.4/fq_default_poly_factor/test/000077500000000000000000000000001414523752600204265ustar00rootroot00000000000000flint2-2.8.4/fq_default_poly_factor/test/t-init.c000066400000000000000000000050141414523752600217760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_default_poly_factor.h" #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_embed.h000066400000000000000000000033011414523752600146440ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #define FQ_EMBED_TEMPLATES_INLINE FLINT_DLL #else #define FQ_EMBED_INLINE static __inline__ #define FQ_EMBED_TEMPLATES_INLINE static __inline__ #endif #include "fq.h" #include "fmpz_mod_mat.h" #define T fq #define B fmpz_mod #include "fq_embed_templates.h" #undef B #undef T FQ_EMBED_INLINE 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); } FQ_EMBED_INLINE 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); } #endif flint2-2.8.4/fq_embed/000077500000000000000000000000001414523752600144765ustar00rootroot00000000000000flint2-2.8.4/fq_embed/composition_matrix.c000066400000000000000000000011351414523752600205710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_embed.h" #include "fq_poly.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 flint2-2.8.4/fq_embed/embed.c000066400000000000000000000040161414523752600157170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_embed.h" #include "fq_poly.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" 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); } #endif #endif #undef B #undef CAP_T #undef T flint2-2.8.4/fq_embed/matrices.c000066400000000000000000000157711414523752600164640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_embed.h" #include "fq_poly.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); 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); 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, fq_ctx_prime(ctx)); fmpz_mod_mat_init(tmp, n, n, fq_ctx_prime(ctx)); fmpz_mod_mat_zero(tmp); 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); 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); fq_clear(d_ctx, ctx); fq_clear(d_ctx_inv, ctx); fmpz_mod_mat_clear(mul_mat); fmpz_mod_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 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); slong n = fmpz_mod_mat_nrows(basis); fmpz_mod_mat_t m2d, d2m, tmp; fmpz_mod_mat_init(m2d, n, n, fmpz_mod_ctx_modulus(sub_ctx->ctxp)); fmpz_mod_mat_init(d2m, m, m, fmpz_mod_ctx_modulus(sub_ctx->ctxp)); fmpz_mod_mat_init(tmp, m, n, fmpz_mod_ctx_modulus(sub_ctx->ctxp)); fq_embed_mono_to_dual_matrix(m2d, sup_ctx); fmpz_mod_mat_transpose(res, basis); fq_embed_dual_to_mono_matrix(d2m, sub_ctx); fmpz_mod_mat_mul(tmp, res, m2d); fmpz_mod_mat_mul(res, d2m, tmp); fmpz_mod_mat_clear(m2d); fmpz_mod_mat_clear(d2m); fmpz_mod_mat_clear(tmp); } 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, fmpz_mod_ctx_modulus(ctxp)); fmpz_mod_mat_init(sub2gen, m, m, fmpz_mod_ctx_modulus(ctxp)); fmpz_mod_mat_init(gen2sup, n, m, fmpz_mod_ctx_modulus(ctxp)); fmpz_mod_mat_init(sup2gen, m, n, fmpz_mod_ctx_modulus(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); } /* 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, fmpz_mod_ctx_modulus(ctxp)); fmpz_mod_mat_init(mat_mul, n, n, fmpz_mod_ctx_modulus(ctxp)); fmpz_mod_mat_init(tmp, m, n, fmpz_mod_ctx_modulus(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); fmpz_mod_mat_mul(tvec, gen2sup, column); 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); fmpz_mod_mat_swap(tmp, sup2gen); fmpz_mod_mat_clear(tmp); fmpz_mod_mat_clear(mat_mul); fmpz_mod_mat_clear(tvec); fmpz_mod_mat_window_clear(column); fq_clear(mul, sup_ctx); fq_clear(trace, sup_ctx); } fmpz_mod_mat_mul(embed, gen2sup, sub2gen); fmpz_mod_mat_mul(project, gen2sub, sup2gen); fmpz_mod_mat_clear(gen2sub); fmpz_mod_mat_clear(sub2gen); fmpz_mod_mat_clear(gen2sup); fmpz_mod_mat_clear(sup2gen); fq_ctx_clear(gen_ctx); fmpz_clear(invd); fmpz_mod_poly_clear(gen_minpoly_cp, ctxp); } flint2-2.8.4/fq_embed/mul_matrix.c000066400000000000000000000034231414523752600170250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); fmpz_clear(lead); } flint2-2.8.4/fq_embed/test/000077500000000000000000000000001414523752600154555ustar00rootroot00000000000000flint2-2.8.4/fq_embed/test/t-composition_matrix.c000066400000000000000000000051241414523752600220130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_embed.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("composition_matrix... "); fflush(stdout); /* 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_randtest(ctx, state), 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, fq_ctx_prime(ctx)); fmpz_mod_mat_init(mat_a, d, d, fq_ctx_prime(ctx)); fmpz_mod_mat_init(mat_aq, d, d, fq_ctx_prime(ctx)); fmpz_mod_mat_init(res, d, d, fq_ctx_prime(ctx)); 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); 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)) { 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), flint_printf("\n"), fmpz_mod_mat_print_pretty(mat_a), flint_printf("\n"), fmpz_mod_mat_print_pretty(mat_aq), flint_printf("\n"), fmpz_mod_mat_print_pretty(res), flint_printf("\n"); abort(); } fmpz_mod_mat_clear(mat_frob); fmpz_mod_mat_clear(mat_a); fmpz_mod_mat_clear(mat_aq); fmpz_mod_mat_clear(res); fq_clear(frob, ctx); fq_clear(a, ctx); fq_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_embed/test/t-embed.c000066400000000000000000000050031414523752600171340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_embed.h" #include "fq_poly.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" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("embed... "); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif #endif #undef B #undef CAP_T #undef T flint2-2.8.4/fq_embed/test/t-embed_matrices.c000066400000000000000000000105771414523752600210370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_embed.h" #include #include int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("embed matrices... "); fflush(stdout); /* Check that isomorphism to self gives identity matrices */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { fq_ctx_t ctx; fq_t gen; const fmpz_mod_poly_struct *modulus; fmpz_mod_mat_t embed, project, one; slong d; fq_ctx_randtest(ctx, state); 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, fq_ctx_prime(ctx)); fmpz_mod_mat_init(project, d, d, fq_ctx_prime(ctx)); fmpz_mod_mat_init(one, d, d, fq_ctx_prime(ctx)); fq_embed_matrices(embed, project, gen, ctx, gen, ctx, modulus); fmpz_mod_mat_one(one); if (!fmpz_mod_mat_equal(embed, one) || !fmpz_mod_mat_equal(project, one)) { 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), flint_printf("\nProject\n"), fmpz_mod_mat_print_pretty(project), flint_printf("\n"); abort(); } fmpz_mod_mat_clear(embed); fmpz_mod_mat_clear(project); fmpz_mod_mat_clear(one); fq_clear(gen, ctx); fq_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++) { 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_randtest(ctx1, state), m = fq_ctx_degree(ctx1), m == 1) { fq_ctx_clear(ctx1); } n = m*j; 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, fq_ctx_prime(ctx1)); fmpz_mod_mat_init(project, m, n, fq_ctx_prime(ctx1)); fmpz_mod_mat_init(comp, m, m, fq_ctx_prime(ctx1)); fmpz_mod_mat_init(one, m, m, fq_ctx_prime(ctx1)); fq_embed_matrices(embed, project, gen1, ctx1, gen2, ctx2, minpoly); fmpz_mod_mat_mul(comp, project, embed); fmpz_mod_mat_one(one); if (!fmpz_mod_mat_equal(comp, one)) { 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), flint_printf("\nProject\n"), fmpz_mod_mat_print_pretty(project), flint_printf("\nComposition\n"), fmpz_mod_mat_print_pretty(comp), flint_printf("\n"); abort(); } fmpz_mod_mat_clear(embed); fmpz_mod_mat_clear(project); fmpz_mod_mat_clear(comp); fmpz_mod_mat_clear(one); 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); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_embed/test/t-mono_dual_matrix.c000066400000000000000000000036601414523752600214300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_embed.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("mono_to/from_dual_matrix... "); fflush(stdout); /* 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_randtest(ctx, state); d = fq_ctx_degree(ctx); fmpz_mod_mat_init(m2d, d, d, fq_ctx_prime(ctx)); fmpz_mod_mat_init(d2m, d, d, fq_ctx_prime(ctx)); fmpz_mod_mat_init(one, d, d, fq_ctx_prime(ctx)); fmpz_mod_mat_init(two, d, d, fq_ctx_prime(ctx)); fq_embed_mono_to_dual_matrix(m2d, ctx); fq_embed_dual_to_mono_matrix(d2m, ctx); fmpz_mod_mat_mul(one, m2d, d2m); fmpz_mod_mat_one(two); if (!fmpz_mod_mat_equal(one, two)) { 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), flint_printf("\nDual -> Mono\n"), fmpz_mod_mat_print_pretty(d2m), flint_printf("\n"); abort(); } fmpz_mod_mat_clear(m2d); fmpz_mod_mat_clear(d2m); fmpz_mod_mat_clear(one); fmpz_mod_mat_clear(two); fq_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_embed/test/t-mul_matrix.c000066400000000000000000000041671414523752600202530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_embed.h" #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("mul_matrix... "); fflush(stdout); /* 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_randtest(ctx, state); d = fq_ctx_degree(ctx); fq_init(a, ctx); fmpz_mod_mat_init(mat_a, d, d, fq_ctx_prime(ctx)); fmpz_mod_mat_init(mat_a_sq, d, d, fq_ctx_prime(ctx)); fmpz_mod_mat_init(mat_a_a, d, d, fq_ctx_prime(ctx)); 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); if (!fmpz_mod_mat_equal(mat_a_a, mat_a_sq)) { 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), flint_printf("^2\n=\n"), fmpz_mod_mat_print_pretty(mat_a_a), flint_printf("\n=\n"), fmpz_mod_mat_print_pretty(mat_a_sq), flint_printf("\n"); abort(); } fmpz_mod_mat_clear(mat_a); fmpz_mod_mat_clear(mat_a_sq); fmpz_mod_mat_clear(mat_a_a); fq_clear(a, ctx); fq_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_embed_templates.h000066400000000000000000000076731414523752600167420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "templates.h" #ifdef __cplusplus extern "C" { #endif FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 */ FLINT_DLL 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. */ FLINT_DLL 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)) */ FLINT_DLL 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); FQ_EMBED_TEMPLATES_INLINE 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))); } FLINT_DLL void TEMPLATE(T, embed_mul_matrix)(TEMPLATE(B, mat_t) matrix, const TEMPLATE(T, t) gen, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, embed_mono_to_dual_matrix)(TEMPLATE(B, mat_t) res, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, embed_dual_to_mono_matrix)(TEMPLATE(B, mat_t) res, const TEMPLATE(T, ctx_t) ctx); #ifdef __cplusplus } #endif #endif #endif flint2-2.8.4/fq_embed_templates/000077500000000000000000000000001414523752600165545ustar00rootroot00000000000000flint2-2.8.4/fq_embed_templates/composition_matrix.c000066400000000000000000000025371414523752600226560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "templates.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)) 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)(matrix); for (j = 0; j < trunc; j++) { for (i = 0; i < tmp->length; i++) TEMPLATE(B, mat_set_entry)(matrix, i, j, __TEMPLATE(B, poly_get_coeff)(tmp, i)); if (j < len - 1) TEMPLATE(T, mul)(tmp, tmp, gen, ctx); } TEMPLATE(T, clear)(tmp, ctx); } #endif #endif flint2-2.8.4/fq_embed_templates/embed.c000066400000000000000000000043141414523752600177760ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_embed_templates/matrices.c000066400000000000000000000212521414523752600205310ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_embed_templates/test/000077500000000000000000000000001414523752600175335ustar00rootroot00000000000000flint2-2.8.4/fq_embed_templates/test/t-composition_matrix.c000066400000000000000000000060011414523752600240640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("composition_matrix... "); fflush(stdout); /* 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_randtest)(ctx, state), 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); TEMPLATE(T, pow)(frob, frob, TEMPLATE(T, ctx_prime)(ctx), ctx); 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); TEMPLATE(T, pow)(a, a, TEMPLATE(T, ctx_prime)(ctx), ctx); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_embed_templates/test/t-embed.c000066400000000000000000000046131414523752600212200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("embed... "); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif #endif flint2-2.8.4/fq_embed_templates/test/t-embed_matrices.c000066400000000000000000000120711414523752600231040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "templates.h" #include #include int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("embed matrices... "); fflush(stdout); /* 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_randtest)(ctx, state); d = TEMPLATE(T, ctx_degree)(ctx); modulus = TEMPLATE(T, ctx_modulus)(ctx); TEMPLATE(T, init)(gen, ctx); TEMPLATE(T, gen)(gen, ctx); TEMPLATE(T, pow)(gen, gen, TEMPLATE(T, ctx_prime)(ctx), ctx); 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"); 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_randtest)(ctx1, state), 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"); 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); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif #endif flint2-2.8.4/fq_embed_templates/test/t-mono_dual_matrix.c000066400000000000000000000043571414523752600235120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("mono_to/from_dual_matrix... "); fflush(stdout); /* 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_randtest)(ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif #endif flint2-2.8.4/fq_embed_templates/test/t-mul_matrix.c000066400000000000000000000047011414523752600223230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef B #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("mul_matrix... "); fflush(stdout); /* 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_randtest)(ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif #endif flint2-2.8.4/fq_mat.h000066400000000000000000000022271414523752600143570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #define FQ_MAT_INLINE FLINT_DLL #else #define FQ_MAT_TEMPLATES_INLINE static __inline__ #define FQ_MAT_INLINE static __inline__ #endif #include "fq.h" #include "fq_vec.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 FQ_MAT_INLINE 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; } #define T fq #define CAP_T FQ #include "fq_mat_templates.h" #undef CAP_T #undef T #endif flint2-2.8.4/fq_mat/000077500000000000000000000000001414523752600142035ustar00rootroot00000000000000flint2-2.8.4/fq_mat/add.c000066400000000000000000000010001414523752600150660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/add.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/can_solve.c000066400000000000000000000010071414523752600163160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/can_solve.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/charpoly_danilevsky.c000066400000000000000000000010711414523752600204200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #include "fq_poly.h" #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/charpoly_danilevsky.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/clear.c000066400000000000000000000010021414523752600154260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/concat_horizontal.c000066400000000000000000000010241414523752600200640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/concat_horizontal.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/concat_vertical.c000066400000000000000000000010221414523752600175020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/concat_vertical.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/equal.c000066400000000000000000000010021414523752600154470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/equal.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/fprint.c000066400000000000000000000010031414523752600156430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/fprint.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/init.c000066400000000000000000000010011414523752600153020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/init.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/init_set.c000066400000000000000000000010051414523752600161610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/init_set.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/inlines.c000066400000000000000000000010541414523752600160100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "fq_mat.h" flint2-2.8.4/fq_mat/inv.c000066400000000000000000000010021414523752600151340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/inv.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/is_one.c000066400000000000000000000010041414523752600156160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/is_one.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/is_zero.c000066400000000000000000000010041414523752600160140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/is_zero.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/lu.c000066400000000000000000000007771414523752600150020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/lu.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/lu_classical.c000066400000000000000000000010111414523752600167760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/lu_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/lu_recursive.c000066400000000000000000000010111414523752600170470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/lu_recursive.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/minpoly.c000066400000000000000000000010551414523752600160370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #include "fq_poly.h" #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/minpoly.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/mul.c000066400000000000000000000010001414523752600151330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/mul.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/mul_KS.c000066400000000000000000000010031414523752600155330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/mul_KS.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/mul_classical.c000066400000000000000000000010121414523752600171540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/mul_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/mul_vec.c000066400000000000000000000010601414523752600157760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #include "fq_poly.h" #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/mul_vec.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/neg.c000066400000000000000000000010001414523752600151070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/neg.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/nullspace.c000066400000000000000000000010061414523752600163320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/nullspace.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/one.c000066400000000000000000000010011414523752600151200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/one.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/profile/000077500000000000000000000000001414523752600156435ustar00rootroot00000000000000flint2-2.8.4/fq_mat/profile/p-mul.c000066400000000000000000000010121414523752600170330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/randops.c000066400000000000000000000010041414523752600160100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/randops.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/randpermdiag.c000066400000000000000000000010111414523752600167750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/randpermdiag.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/randrank.c000066400000000000000000000010051414523752600161430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/randrank.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/randtest.c000066400000000000000000000010051414523752600161670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/randtest.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/randtril.c000066400000000000000000000010051414523752600161620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/randtril.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/randtriu.c000066400000000000000000000010051414523752600161730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/randtriu.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/rank.c000066400000000000000000000010011414523752600152720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/rank.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/reduce_row.c000066400000000000000000000031141414523752600165040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_mat/rref.c000066400000000000000000000010011414523752600152750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/rref.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/set.c000066400000000000000000000010001414523752600151310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/set.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/set_fmpz_mod_mat.c000066400000000000000000000010161414523752600176740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/set_fmpz_mod_mat.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/set_nmod_mat.c000066400000000000000000000010121414523752600170120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/set_nmod_mat.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/similarity.c000066400000000000000000000010601414523752600165320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #include "fq_poly.h" #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/similarity.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/solve.c000066400000000000000000000010041414523752600154720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/solve.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/solve_tril.c000066400000000000000000000010071414523752600165270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/solve_tril.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/solve_tril_classical.c000066400000000000000000000010211414523752600205410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/solve_tril_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/solve_tril_recursive.c000066400000000000000000000010211414523752600206120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/solve_tril_recursive.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/solve_triu.c000066400000000000000000000010071414523752600165400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/solve_triu.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/solve_triu_classical.c000066400000000000000000000010211414523752600205520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/solve_triu_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/solve_triu_recursive.c000066400000000000000000000010211414523752600206230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/solve_triu_recursive.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/sub.c000066400000000000000000000010001414523752600151270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/sub.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/submul.c000066400000000000000000000010031414523752600156500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/submul.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/swap.c000066400000000000000000000010011414523752600153110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/swap.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/test/000077500000000000000000000000001414523752600151625ustar00rootroot00000000000000flint2-2.8.4/fq_mat/test/t-add_sub.c000066400000000000000000000010131414523752600171630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-can_solve.c000066400000000000000000000010161414523752600175360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-charpoly.c000066400000000000000000000010411414523752600174040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-concat_horizontal.c000066400000000000000000000010331414523752600213040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-concat_vertical.c000066400000000000000000000010311414523752600207220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-equal.c000066400000000000000000000010111414523752600166670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-inv.c000066400000000000000000000010111414523752600163540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-invert_rows_cols.c000066400000000000000000000010261414523752600211670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-is_zero.c000066400000000000000000000010131414523752600172340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-lu_classical.c000066400000000000000000000010201414523752600202160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-lu_recursive.c000066400000000000000000000010201414523752600202670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-minpoly.c000066400000000000000000000010401414523752600172510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-mul.c000066400000000000000000000010071414523752600163620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-mul_KS.c000066400000000000000000000010121414523752600167530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-mul_vec.c000066400000000000000000000010161414523752600172170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-nullspace.c000066400000000000000000000010151414523752600175520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-one.c000066400000000000000000000010101414523752600163400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-rank.c000066400000000000000000000010101414523752600165120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-rref.c000066400000000000000000000010101414523752600165150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-set_fmpz_mod_mat.c000066400000000000000000000010251414523752600211140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-set_nmod_mat.c000066400000000000000000000010211414523752600202320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-solve.c000066400000000000000000000010131414523752600167120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-solve_tril.c000066400000000000000000000010161414523752600177470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-solve_tril_classical.c000066400000000000000000000010301414523752600217610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-solve_tril_recursive.c000066400000000000000000000010301414523752600220320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-solve_triu.c000066400000000000000000000010161414523752600177600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-solve_triu_classical.c000066400000000000000000000010301414523752600217720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-solve_triu_recursive.c000066400000000000000000000010301414523752600220430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-submul.c000066400000000000000000000010121414523752600170700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-vec_mul.c000066400000000000000000000010161414523752600172170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-window_init_clear.c000066400000000000000000000010331414523752600212640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/test/t-zero.c000066400000000000000000000010101414523752600165360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_mat/vec_mul.c000066400000000000000000000010601414523752600157760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #include "fq_poly.h" #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/vec_mul.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/window_clear.c000066400000000000000000000010111414523752600170150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/window_clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/window_init.c000066400000000000000000000010101414523752600166710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/window_init.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat/zero.c000066400000000000000000000010011414523752600153160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_mat_templates/zero.c" #undef CAP_T #undef T flint2-2.8.4/fq_mat_templates.h000066400000000000000000000376041414523752600164440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "flint.h" #include "templates.h" #include "ulong_extras.h" #include "fmpz_mod_mat.h" #ifdef __cplusplus extern "C" { #endif typedef struct { TEMPLATE(T, struct) * entries; slong r; slong c; TEMPLATE(T, struct) ** rows; } TEMPLATE(T, mat_struct); typedef TEMPLATE(T, mat_struct) TEMPLATE(T, mat_t)[1]; /* Memory management ********************************************************/ FLINT_DLL void TEMPLATE(T, mat_init)(TEMPLATE(T, mat_t) mat, slong rows, slong cols, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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; } FQ_MAT_TEMPLATES_INLINE 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); } FLINT_DLL void TEMPLATE(T, mat_swap)(TEMPLATE(T, mat_t) mat1, TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx); FQ_MAT_TEMPLATES_INLINE 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); } FLINT_DLL void TEMPLATE(T, mat_set)(TEMPLATE(T, mat_t) mat1, const TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, mat_clear)(TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int TEMPLATE(T, mat_equal)(const TEMPLATE(T, mat_t) mat1, const TEMPLATE(T, mat_t) mat2, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int TEMPLATE(T, mat_is_zero)(const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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)) { TEMPLATE(T, 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; } } 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); } FQ_MAT_TEMPLATES_INLINE 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) { t = perm[s]; perm[s] = perm[r]; perm[r] = t; } 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); } } } FQ_MAT_TEMPLATES_INLINE 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; slong i; slong c = mat->c; slong k = mat->c/2; if (perm) { for (i =0; i < k; i++) { t = perm[i]; perm[i] = perm[c - i]; perm[c - i] = t; } } 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); } } } } /* Assignment ***************************************************************/ FLINT_DLL void TEMPLATE(T, mat_zero)(TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, mat_one)(TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); /* Conversions ***************************************************************/ FLINT_DLL void TEMPLATE(T, mat_set_nmod_mat) (TEMPLATE(T, mat_t) mat1, const nmod_mat_t mat2, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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 */ FLINT_DLL 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); FLINT_DLL void TEMPLATE(T, mat_window_clear)(TEMPLATE(T, mat_t) window, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL 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 *********************************************************/ FLINT_DLL int TEMPLATE(T, mat_fprint)(FILE * file, const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int TEMPLATE(T, mat_fprint_pretty)(FILE * file, const TEMPLATE(T, mat_t) mat, const TEMPLATE(T, ctx_t) ctx); FQ_MAT_TEMPLATES_INLINE 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); } FQ_MAT_TEMPLATES_INLINE 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); } /* TODO: Read functions */ /* Random matrix generation *************************************************/ FLINT_DLL void TEMPLATE(T, mat_randtest)(TEMPLATE(T, mat_t) mat, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, mat_randrank)(TEMPLATE(T, mat_t) mat, flint_rand_t state, slong rank, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL void TEMPLATE(T, mat_randops)(TEMPLATE(T, mat_t) mat, slong count, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, mat_randtril)(TEMPLATE(T, mat_t) mat, flint_rand_t state, int unit, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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 */ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void TEMPLATE(T, mat_neg)(TEMPLATE(T, mat_t) B, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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 */ FLINT_DLL 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_DLL 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); FLINT_DLL 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); FLINT_DLL slong TEMPLATE(T, mat_lu)(slong * P, TEMPLATE(T, mat_t) A, int rank_check, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL slong TEMPLATE(T, mat_lu_recursive)(slong * P, TEMPLATE(T, mat_t) A, int rank_check, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL slong TEMPLATE(T, mat_lu_classical)(slong * P, TEMPLATE(T, mat_t) A, int rank_check, const TEMPLATE(T, ctx_t) ctx); /* Inverse *******************************************************************/ FLINT_DLL int TEMPLATE(T, mat_inv)(TEMPLATE(T, mat_t) B, TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); /* Solving *******************************************************************/ FLINT_DLL slong TEMPLATE(T, mat_rref)(TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL slong TEMPLATE(T, mat_reduce_row)(TEMPLATE(T, mat_t) A, slong * P, slong * L, slong m, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL slong TEMPLATE(T, mat_nullspace)(TEMPLATE(T, mat_t) X, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL slong TEMPLATE(T, mat_rank)(const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 *******************************************************/ FLINT_DLL 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 *******************************************************************/ FLINT_DLL 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 ****************************************************************/ FLINT_DLL 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 * FLINT_DLL * 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 flint2-2.8.4/fq_mat_templates/000077500000000000000000000000001414523752600162615ustar00rootroot00000000000000flint2-2.8.4/fq_mat_templates/add.c000066400000000000000000000015601414523752600171570ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/can_solve.c000066400000000000000000000060011414523752600203730ustar00rootroot00000000000000/* 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 2.1 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 (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; 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) { 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); TEMPLATE(T, mat_clear)(LU, ctx); flint_free(perm); flint_free(pivots); return result; } #endif flint2-2.8.4/fq_mat_templates/charpoly_danilevsky.c000066400000000000000000000153761414523752600225130ustar00rootroot00000000000000/* 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 2.1 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); } #endif flint2-2.8.4/fq_mat_templates/clear.c000066400000000000000000000016621414523752600175200ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/concat_horizontal.c000066400000000000000000000017331414523752600221510ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/concat_vertical.c000066400000000000000000000017651414523752600215760ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/equal.c000066400000000000000000000017411414523752600175370ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/fprint.c000066400000000000000000000057161414523752600177400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" /* 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 #endif flint2-2.8.4/fq_mat_templates/init.c000066400000000000000000000027041414523752600173730ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/init_set.c000066400000000000000000000014011414523752600202370ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/inv.c000066400000000000000000000025401414523752600172220ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/is_one.c000066400000000000000000000016201414523752600177000ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/is_zero.c000066400000000000000000000014421414523752600201000ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/lu.c000066400000000000000000000012241414523752600170440ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/lu_classical.c000066400000000000000000000054311414523752600210660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #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 flint2-2.8.4/fq_mat_templates/lu_recursive.c000066400000000000000000000070131414523752600211350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include 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 flint2-2.8.4/fq_mat_templates/minpoly.c000066400000000000000000000116641414523752600201240ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (fq_mat_charpoly). Non-square matrix.\n"); flint_abort(); } 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 flint2-2.8.4/fq_mat_templates/mul.c000066400000000000000000000020441414523752600172220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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) { 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 flint2-2.8.4/fq_mat_templates/mul_KS.c000066400000000000000000000044061414523752600176230ustar00rootroot00000000000000/* 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 2.1 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); fmpz_set(beta, TEMPLATE(T, ctx_prime) (ctx)); 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 flint2-2.8.4/fq_mat_templates/mul_classical.c000066400000000000000000000032761414523752600212500ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/mul_vec.c000066400000000000000000000033651414523752600200660ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/neg.c000066400000000000000000000014131414523752600171750ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/nullspace.c000066400000000000000000000042461414523752600204210ustar00rootroot00000000000000/* 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 2.1 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, 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 flint2-2.8.4/fq_mat_templates/one.c000066400000000000000000000012631414523752600172100ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/profile/000077500000000000000000000000001414523752600177215ustar00rootroot00000000000000flint2-2.8.4/fq_mat_templates/profile/p-mul.c000066400000000000000000000050071414523752600211210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "flint.h" #include "templates.h" #include #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 flint2-2.8.4/fq_mat_templates/randops.c000066400000000000000000000035161414523752600201000ustar00rootroot00000000000000/* 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 2.1 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, slong count, flint_rand_t state, 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 flint2-2.8.4/fq_mat_templates/randpermdiag.c000066400000000000000000000022351414523752600210640ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/randrank.c000066400000000000000000000020561414523752600202300ustar00rootroot00000000000000/* 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 2.1 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) { printf("Exception (nmod_mat_randrank). Impossible rank.\n"); flint_abort(); } 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 flint2-2.8.4/fq_mat_templates/randtest.c000066400000000000000000000014111414523752600202460ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/randtril.c000066400000000000000000000023071414523752600202460ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/randtriu.c000066400000000000000000000023061414523752600202560ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/rank.c000066400000000000000000000016541414523752600173660ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/reduce_row.c000066400000000000000000000032771414523752600205740ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/rref.c000066400000000000000000000077621414523752600173770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "flint.h" #include "perm.h" slong TEMPLATE(T, mat_rref) (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; if (TEMPLATE(T, mat_is_zero)(A, ctx)) return 0; if (A->r == 1) { TEMPLATE(T, struct) * c; slong i, j; slong r = 0; for (i = 0; i < A->c; i++) { c = TEMPLATE(T, mat_entry)(A, 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 < A->c; j++) { TEMPLATE(T, mul)(TEMPLATE(T, mat_entry)(A, 0, j), TEMPLATE(T, mat_entry)(A, 0, j), c, ctx); } TEMPLATE(T, one)(c, ctx); break; } } return r; } n = A->c; P = _perm_init(TEMPLATE(T, mat_nrows) (A, ctx)); rank = TEMPLATE(T, mat_lu) (P, A, 0, ctx); _perm_clear(P); if (rank == 0) return rank; /* Clear L */ for (i = 0; i < A->r; i++) for (j = 0; j < FLINT_MIN(i, rank); j++) TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (A, 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) (A, 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) (A, 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) (A, 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) (A, j, pivots[i]), ctx); } else { TEMPLATE(T, zero) (TEMPLATE(T, mat_entry) (A, 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) (A, 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 flint2-2.8.4/fq_mat_templates/set.c000066400000000000000000000015741414523752600172270ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/set_fmpz_mod_mat.c000066400000000000000000000016041414523752600217550ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/set_nmod_mat.c000066400000000000000000000015721414523752600211030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.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 flint2-2.8.4/fq_mat_templates/similarity.c000066400000000000000000000032031414523752600206110ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/solve.c000066400000000000000000000026111414523752600175550ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/solve_tril.c000066400000000000000000000017131414523752600206110ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/solve_tril_classical.c000066400000000000000000000035331414523752600226310ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/solve_tril_recursive.c000066400000000000000000000036771414523752600227130ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/solve_triu.c000066400000000000000000000017131414523752600206220ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/solve_triu_classical.c000066400000000000000000000036331414523752600226430ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/solve_triu_recursive.c000066400000000000000000000036261414523752600227160ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/sub.c000066400000000000000000000015601414523752600172200ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/submul.c000066400000000000000000000016501414523752600177360ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/swap.c000066400000000000000000000013371414523752600174030ustar00rootroot00000000000000/* 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 2.1 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) { if (mat1 != mat2) { TEMPLATE(T, mat_struct) tmp; tmp = *mat1; *mat1 = *mat2; *mat2 = tmp; } } #endif flint2-2.8.4/fq_mat_templates/test/000077500000000000000000000000001414523752600172405ustar00rootroot00000000000000flint2-2.8.4/fq_mat_templates/test/t-add_sub.c000066400000000000000000000033061414523752600212500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" int main(void) { slong m, n, rep; FLINT_TEST_INIT(state); printf("add/sub/neg...."); fflush(stdout); 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_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-can_solve.c000066400000000000000000000076611414523752600216300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include int main(void) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, X, X2, B, AX; slong i, k, m, n; int solved; FLINT_TEST_INIT(state); printf("solve...."); fflush(stdout); /* test random systems */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_randtest) (ctx, state); 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, 1+n_randint(state, 1+m*m), state, 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-charpoly.c000066400000000000000000000036621414523752600214750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, B, C; TEMPLATE(T, poly_t) p1, p2; slong i, m, n; FLINT_TEST_INIT(state); flint_printf("charpoly...."); fflush(stdout); /* charpoly(AB) == charpoly(BA) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = n_randint(state, 10); n = m; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-concat_horizontal.c000066400000000000000000000040511414523752600233650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("concat_horizontal...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-concat_vertical.c000066400000000000000000000040501414523752600230040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("concat_vertical...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-equal.c000066400000000000000000000046201414523752600207560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); printf("equal...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-inv.c000066400000000000000000000071401414523752600204430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "templates.h" #include #include #include int main(void) { TEMPLATE(T, mat_t) A, B, C, I; TEMPLATE(T, ctx_t) ctx; slong i, j, m, r; int result; FLINT_TEST_INIT(state); flint_printf("inv...."); fflush(stdout); for (i = 0; i < 5 * flint_test_multiplier(); i++) { m = n_randint(state, 20); TEMPLATE(T, ctx_randtest) (ctx, state); 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, 1+n_randint(state, 1+m*m), state, 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"); 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); 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_randtest) (ctx, state); 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, 1+n_randint(state, 1+m*m), state, ctx); result = TEMPLATE(T, mat_inv)(B, A, ctx); if (result) { flint_printf("FAIL:\n"); flint_printf("singular matrix reported as invertible\n"); abort(); } /* Aliasing */ result = TEMPLATE(T, mat_inv)(A, A, ctx); if (result) { flint_printf("FAIL:\n"); flint_printf("singular matrix reported as invertible\n"); abort(); } TEMPLATE(T, mat_clear)(A, ctx); TEMPLATE(T, mat_clear)(B, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_mat_templates/test/t-invert_rows_cols.c000066400000000000000000000036761414523752600232620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" int main(void) { slong m, n, rep, i, j; FLINT_TEST_INIT(state); printf("invert_cols/rows...."); fflush(stdout); 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_randtest) (ctx, state); 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); abort(); } } } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-is_zero.c000066400000000000000000000032211414523752600213150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); printf("is_zero...."); fflush(stdout); 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_randtest) (ctx, state); TEMPLATE(T, mat_init) (A, rows, cols, ctx); if (!TEMPLATE(T, mat_is_zero) (A, ctx)) { printf("FAIL!\n"); 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"); abort(); } } TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-lu_classical.c000066400000000000000000000100261414523752600223020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" 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); } 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"); 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); abort(); } TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (L, ctx); TEMPLATE(T, mat_clear) (U, ctx); } int main(void) { slong i; FLINT_TEST_INIT(state); printf("lu_classical...."); fflush(stdout); 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_randtest) (ctx, state); 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, d, state, 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-lu_recursive.c000066400000000000000000000100251414523752600223520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" 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); } 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"); 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); abort(); } TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (L, ctx); TEMPLATE(T, mat_clear) (U, ctx); } int main(void) { slong i; FLINT_TEST_INIT(state); printf("lu_recursive...."); fflush(stdout); 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_randtest) (ctx, state); 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, d, state, 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-minpoly.c000066400000000000000000000070351414523752600213410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { 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; FLINT_TEST_INIT(state); flint_printf("minpoly...."); fflush(stdout); /* minpoly(A) divides charpoly(A) */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { m = n_randint(state, 10); n = m; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-mul.c000066400000000000000000000107021414523752600204420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include int main(void) { slong i; FLINT_TEST_INIT(state); printf("mul...."); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-mul_KS.c000066400000000000000000000061261414523752600210440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include int main(void) { slong i; FLINT_TEST_INIT(state); printf("mul_KS...."); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, mat_clear) (C, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-mul_vec.c000066400000000000000000000062701414523752600213040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include int main(void) { slong i; FLINT_TEST_INIT(state); printf("mul_vec...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-nullspace.c000066400000000000000000000050621414523752600216360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("nullspace...."); fflush(stdout); 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_randtest) (ctx, state); 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, d, state, 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"); 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"); 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"); abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, mat_clear) (ker, ctx); TEMPLATE(T, mat_clear) (B, ctx); TEMPLATE(T, ctx_clear) (ctx); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-one.c000066400000000000000000000024731414523752600204340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include int main(void) { int iter; FLINT_TEST_INIT(state); printf("one/is_one...."); fflush(stdout); 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_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-rank.c000066400000000000000000000041621414523752600206030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A; slong i, m, n, d, r; FLINT_TEST_INIT(state); flint_printf("rank...."); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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, d, state, ctx); if (r != TEMPLATE(T, mat_rank) (A, ctx)) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); abort(); } TEMPLATE(T, mat_clear) (A, ctx); } TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-rref.c000066400000000000000000000125461414523752600206130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "perm.h" #include "flint.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; } int main(void) { slong i; FLINT_TEST_INIT(state); printf("rref...."); fflush(stdout); 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_randtest) (ctx, state); 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, 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"); 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, 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-set_fmpz_mod_mat.c000066400000000000000000000033401414523752600231740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_fmpz_mod_mat... "); fflush(stdout); /* 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; TEMPLATE(T, ctx_randtest)(ctx, state); 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); fmpz_mod_mat_init(m, r, c, TEMPLATE(T, ctx_prime)(ctx)); fmpz_mod_mat_one(m); 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"); abort(); } fmpz_mod_mat_clear(m); TEMPLATE(T, mat_clear)(a, ctx); TEMPLATE(T, ctx_clear)(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_mat_templates/test/t-set_nmod_mat.c000066400000000000000000000033251414523752600223210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_nmod_mat... "); fflush(stdout); /* 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_randtest)(ctx, state); 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); nmod_mat_init(m, r, c, fmpz_get_ui(TEMPLATE(T, ctx_prime)(ctx))); 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"); abort(); } nmod_mat_clear(m); TEMPLATE(T, mat_clear)(a, ctx); TEMPLATE(T, ctx_clear)(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_mat_templates/test/t-solve.c000066400000000000000000000066651414523752600210120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include int main(void) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, mat_t) A, X, B, AX; slong i, m, n, r; int solved; FLINT_TEST_INIT(state); printf("solve...."); fflush(stdout); for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_randtest) (ctx, state); 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, 1+n_randint(state, 1+m*m), state, 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"); 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_randtest) (ctx, state); 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, 1+n_randint(state, 1+m*m), state, 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-solve_tril.c000066400000000000000000000050171414523752600220320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include int main(void) { slong i; FLINT_TEST_INIT(state); printf("solve_tril...."); fflush(stdout); 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_randtest) (ctx, state); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-solve_tril_classical.c000066400000000000000000000050541414523752600240510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include int main(void) { slong i; FLINT_TEST_INIT(state); printf("solve_tril_classical...."); fflush(stdout); 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_randtest) (ctx, state); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-solve_tril_recursive.c000066400000000000000000000050541414523752600241220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include int main(void) { slong i; FLINT_TEST_INIT(state); printf("solve_tril_recursive...."); fflush(stdout); 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_randtest) (ctx, state); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-solve_triu.c000066400000000000000000000050161414523752600220420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include int main(void) { slong i; FLINT_TEST_INIT(state); printf("solve_triu...."); fflush(stdout); 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_randtest) (ctx, state); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-solve_triu_classical.c000066400000000000000000000050541414523752600240620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include int main(void) { slong i; FLINT_TEST_INIT(state); printf("solve_triu_classical...."); fflush(stdout); 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_randtest) (ctx, state); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-solve_triu_recursive.c000066400000000000000000000050541414523752600241330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include int main(void) { slong i; FLINT_TEST_INIT(state); printf("solve_triu_recursive...."); fflush(stdout); 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_randtest) (ctx, state); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-submul.c000066400000000000000000000053221414523752600211560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include int main(void) { slong i; FLINT_TEST_INIT(state); printf("submul...."); fflush(stdout); 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_randtest) (ctx, state); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-vec_mul.c000066400000000000000000000062621414523752600213050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include int main(void) { slong i; FLINT_TEST_INIT(state); printf("vec_mul...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-window_init_clear.c000066400000000000000000000032261414523752600233500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("window_init/clear...."); fflush(stdout); 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_randtest) (ctx, state); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/test/t-zero.c000066400000000000000000000033111414523752600206220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include int main(void) { int iter; FLINT_TEST_INIT(state); printf("zero/is_zero...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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"); abort(); } } TEMPLATE(T, mat_clear) (A, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_mat_templates/vec_mul.c000066400000000000000000000033651414523752600200660ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/window_clear.c000066400000000000000000000014111414523752600210770ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/window_init.c000066400000000000000000000025221414523752600207600ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_mat_templates/zero.c000066400000000000000000000012751414523752600174110ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_nmod.h000066400000000000000000000331231414523752600145320ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #define FQ_TEMPLATES_INLINE FLINT_DLL #else #define FQ_NMOD_INLINE static __inline__ #define FQ_TEMPLATES_INLINE static __inline__ #endif #include "nmod_poly.h" #include "nmod_mat.h" #include "ulong_extras.h" /* Data types and context ****************************************************/ #ifdef __cplusplus extern "C" { #endif typedef nmod_poly_t fq_nmod_t; typedef nmod_poly_struct fq_nmod_struct; typedef struct { fmpz p; 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]; FLINT_DLL void fq_nmod_ctx_init(fq_nmod_ctx_t ctx, const fmpz_t p, slong d, const char *var); FLINT_DLL int _fq_nmod_ctx_init_conway(fq_nmod_ctx_t ctx, const fmpz_t p, slong d, const char *var); FLINT_DLL void fq_nmod_ctx_init_conway(fq_nmod_ctx_t ctx, const fmpz_t p, slong d, const char *var); FLINT_DLL void fq_nmod_ctx_init_modulus(fq_nmod_ctx_t ctx, const nmod_poly_t modulus, const char *var); FLINT_DLL void fq_nmod_ctx_randtest(fq_nmod_ctx_t ctx, flint_rand_t state); FLINT_DLL void fq_nmod_ctx_randtest_reducible(fq_nmod_ctx_t ctx, flint_rand_t state); FLINT_DLL 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; } #define fq_nmod_ctx_prime(ctx) (&((ctx)->p)) FQ_NMOD_INLINE void fq_nmod_ctx_order(fmpz_t f, const fq_nmod_ctx_t ctx) { fmpz_set(f, fq_nmod_ctx_prime(ctx)); fmpz_pow_ui(f, f, fq_nmod_ctx_degree(ctx)); } /* TODO */ FQ_NMOD_INLINE int fq_nmod_ctx_fprint(FILE * file, const fq_nmod_ctx_t ctx) { int r; slong i, k; r = flint_fprintf(file, "p = "); if (r <= 0) return r; r = fmpz_fprint(file, 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; } FQ_NMOD_INLINE void fq_nmod_ctx_print(const fq_nmod_ctx_t ctx) { fq_nmod_ctx_fprint(stdout, ctx); } /* Memory managment *********************************************************/ FQ_NMOD_INLINE 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)); } FQ_NMOD_INLINE 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)); } FQ_NMOD_INLINE void fq_nmod_clear(fq_nmod_t rop, const fq_nmod_ctx_t ctx) { nmod_poly_clear(rop); } FQ_NMOD_INLINE 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); } } FQ_NMOD_INLINE 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); } FQ_NMOD_INLINE 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); } FQ_NMOD_INLINE 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); } /* Basic arithmetic **********************************************************/ FLINT_DLL void fq_nmod_add(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_sub(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_sub_one(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_neg(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_mul(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_t op2, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_mul_fmpz(fq_nmod_t rop, const fq_nmod_t op, const fmpz_t x, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_mul_si(fq_nmod_t rop, const fq_nmod_t op, slong x, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_mul_ui(fq_nmod_t rop, const fq_nmod_t op, ulong x, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_sqr(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_inv(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fq_nmod_pow(fq_nmod_t rop, const fq_nmod_t op1, const fmpz_t e, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_pow_ui(fq_nmod_t rop, const fq_nmod_t op1, const ulong e, const fq_nmod_ctx_t ctx); /* Roots ********************************************************************/ FLINT_DLL int fq_nmod_sqrt(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_pth_root(fq_nmod_t rop, const fq_nmod_t op1, const fq_nmod_ctx_t ctx); FLINT_DLL int fq_nmod_is_square(const fq_nmod_t op, const fq_nmod_ctx_t ctx); /* Randomisation *************************************************************/ FLINT_DLL void fq_nmod_randtest(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_randtest_dense(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_randtest_not_zero(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_rand(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_rand_not_zero(fq_nmod_t rop, flint_rand_t state, const fq_nmod_ctx_t ctx); /* Comparison ****************************************************************/ FQ_NMOD_INLINE 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); } FQ_NMOD_INLINE int fq_nmod_is_zero(const fq_nmod_t op, const fq_nmod_ctx_t ctx) { return nmod_poly_is_zero(op); } FQ_NMOD_INLINE int fq_nmod_is_one(const fq_nmod_t op, const fq_nmod_ctx_t ctx) { return nmod_poly_is_one(op); } FLINT_DLL int fq_nmod_cmp(const fq_nmod_t a, const fq_nmod_t b, const fq_nmod_ctx_t ctx); /* Assignments and conversions ***********************************************/ FQ_NMOD_INLINE void fq_nmod_set(fq_nmod_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx) { nmod_poly_set(rop, op); } FQ_NMOD_INLINE void fq_nmod_set_fmpz(fq_nmod_t rop, const fmpz_t x, const fq_nmod_ctx_t ctx) { fmpz_t rx; fmpz_init(rx); fmpz_mod(rx, x, fq_nmod_ctx_prime(ctx)); nmod_poly_zero(rop); nmod_poly_set_coeff_ui(rop, 0, fmpz_get_ui(rx)); fmpz_clear(rx); } FQ_NMOD_INLINE 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); } FQ_NMOD_INLINE 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)); } FQ_NMOD_INLINE void fq_nmod_swap(fq_nmod_t op1, fq_nmod_t op2, const fq_nmod_ctx_t ctx) { nmod_poly_swap(op1, op2); } FQ_NMOD_INLINE void fq_nmod_zero(fq_nmod_t rop, const fq_nmod_ctx_t ctx) { nmod_poly_zero(rop); } FQ_NMOD_INLINE void fq_nmod_one(fq_nmod_t rop, const fq_nmod_ctx_t ctx) { nmod_poly_one(rop); } FQ_NMOD_INLINE 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_DLL void fq_nmod_get_nmod_poly(nmod_poly_t a, const fq_nmod_t b, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_set_nmod_poly(fq_nmod_t a, const nmod_poly_t b, const fq_nmod_ctx_t ctx); /* Output ********************************************************************/ FQ_NMOD_INLINE int fq_nmod_fprint(FILE * file, const fq_nmod_t op, const fq_nmod_ctx_t ctx) { return nmod_poly_fprint(file, op); } FQ_NMOD_INLINE void fq_nmod_print(const fq_nmod_t op, const fq_nmod_ctx_t ctx) { nmod_poly_print(op); } FQ_NMOD_INLINE 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); } FQ_NMOD_INLINE void fq_nmod_print_pretty(const fq_nmod_t op, const fq_nmod_ctx_t ctx) { nmod_poly_print_pretty(op, ctx->var); } FLINT_DLL char * fq_nmod_get_str(const fq_nmod_t op, const fq_nmod_ctx_t ctx); FLINT_DLL char * fq_nmod_get_str_pretty(const fq_nmod_t op, const fq_nmod_ctx_t ctx); /* Special functions *********************************************************/ FLINT_DLL void _fq_nmod_trace(fmpz_t rop, const mp_limb_t *op, slong len, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_trace(fmpz_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx); FLINT_DLL void _fq_nmod_frobenius(mp_limb_t *rop, const mp_limb_t *op, slong len, slong e, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_frobenius(fq_nmod_t rop, const fq_nmod_t op, slong e, const fq_nmod_ctx_t ctx); FLINT_DLL void _fq_nmod_norm(fmpz_t rop, const mp_limb_t *op, slong len, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_norm(fmpz_t rop, const fq_nmod_t op, const fq_nmod_ctx_t ctx); /* Bit packing ******************************************************/ FLINT_DLL void fq_nmod_bit_pack(fmpz_t f, const fq_nmod_t op, flint_bitcnt_t bit_size, const fq_nmod_ctx_t ctx); FLINT_DLL void fq_nmod_bit_unpack(fq_nmod_t rop, const fmpz_t f, flint_bitcnt_t bit_size, const fq_nmod_ctx_t ctx); /* Inlines *******************************************************************/ FLINT_DLL void __fq_nmod_ctx_prime(fmpz_t p, fq_nmod_ctx_t ctx); #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 flint2-2.8.4/fq_nmod/000077500000000000000000000000001414523752600143575ustar00rootroot00000000000000flint2-2.8.4/fq_nmod/add.c000066400000000000000000000015641414523752600152610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/bit_pack.c000066400000000000000000000010661414523752600163020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/bit_unpack.c000066400000000000000000000011331414523752600166400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/cmp.c000066400000000000000000000013471414523752600153070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" 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; } flint2-2.8.4/fq_nmod/ctx_clear.c000066400000000000000000000013061414523752600164670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" void fq_nmod_ctx_clear(fq_nmod_ctx_t ctx) { nmod_poly_clear(ctx->modulus); nmod_poly_clear(ctx->inv); fmpz_clear(fq_nmod_ctx_prime(ctx)); _nmod_vec_clear(ctx->a); flint_free(ctx->j); flint_free(ctx->var); } flint2-2.8.4/fq_nmod/ctx_init.c000066400000000000000000000017271414523752600163530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod.h" #include "nmod_poly.h" void fq_nmod_ctx_init(fq_nmod_ctx_t ctx, const fmpz_t p, slong d, const char *var) { flint_rand_t state; nmod_poly_t poly; if (_fq_nmod_ctx_init_conway(ctx, p, d, var)) { ctx->is_conway = 1; return; } else ctx->is_conway = 0; flint_randinit(state); nmod_poly_init2(poly, fmpz_get_ui(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); } flint2-2.8.4/fq_nmod/ctx_init_conway.c000066400000000000000000000044011414523752600177230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod.h" /* from qadic/ctx_init_conway.c */ extern int flint_conway_polynomials []; int _fq_nmod_ctx_init_conway(fq_nmod_ctx_t ctx, const fmpz_t p, slong d, const char *var) { unsigned int position; if (fmpz_cmp_ui(p, 109987) > 0) { return 0; } for (position = 0; flint_conway_polynomials[position] != 0; position += 3+flint_conway_polynomials[position+1]) { /* Different prime? */ if (fmpz_cmp_ui(p, flint_conway_polynomials[position])) continue; /* Same degree? */ if (d == flint_conway_polynomials[position+1]) { nmod_poly_t mod; slong i; nmod_poly_init(mod, fmpz_get_ui(p)); /* Copy the polynomial */ for (i = 0; i < d; i++) { int coeff = flint_conway_polynomials[position+2+i]; nmod_poly_set_coeff_ui(mod, i, coeff); } nmod_poly_set_coeff_ui(mod, d, 1); fq_nmod_ctx_init_modulus(ctx, mod, var); nmod_poly_clear(mod); return 1; } } return 0; } void fq_nmod_ctx_init_conway(fq_nmod_ctx_t ctx, const fmpz_t p, slong d, const char *var) { int result; if (fmpz_cmp_ui(p, 109987) > 0) { flint_printf("Exception (fq_nmod_ctx_init_conway). Conway polynomials \n"); flint_printf("are only available for primes up to 109987.\n"); flint_abort(); } result = _fq_nmod_ctx_init_conway(ctx, p, d, var); if (!result) { flint_printf("Exception (fq_nmod_ctx_init_conway). The polynomial for \n(p,d) = ("); fmpz_print(p), flint_printf(",%wd) is not present in the database.\n", d); flint_abort(); } ctx->is_conway = 1; } flint2-2.8.4/fq_nmod/ctx_init_modulus.c000066400000000000000000000040421414523752600201140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; fmpz_init(fq_nmod_ctx_prime(ctx)); fmpz_set_ui(fq_nmod_ctx_prime(ctx), modulus->mod.n); 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; } flint2-2.8.4/fq_nmod/ctx_randtest.c000066400000000000000000000022511414523752600172250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" void fq_nmod_ctx_randtest(fq_nmod_ctx_t ctx, flint_rand_t state) { nmod_poly_t modulus; mp_limb_t x; fmpz_t p; slong d; fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, 6), 1)); d = n_randint(state, 10) + 1; fq_nmod_ctx_init_conway(ctx, p, d, "a"); fmpz_clear(p); /* Test non-monic modulus */ if (n_randint(state, 2)) { 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); } } flint2-2.8.4/fq_nmod/ctx_randtest_reducible.c000066400000000000000000000014751414523752600212520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" void fq_nmod_ctx_randtest_reducible(fq_nmod_ctx_t ctx, flint_rand_t state) { fmpz_t p; slong d; nmod_poly_t mod; fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, 6), 1)); d = n_randint(state, 10) + 1; nmod_poly_init(mod, fmpz_get_ui(p)); nmod_poly_randtest_monic(mod, state, d + 1); fq_nmod_ctx_init_modulus(ctx, mod, "a"); nmod_poly_clear(mod); fmpz_clear(p); } flint2-2.8.4/fq_nmod/div.c000066400000000000000000000010071414523752600153030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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/div.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod/frobenius.c000066400000000000000000000040261414523752600165210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.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_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); } } flint2-2.8.4/fq_nmod/gcdinv.c000066400000000000000000000010651414523752600157770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/get_nmod_poly.c000066400000000000000000000012211414523752600173560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/get_set_fmpz_mod_mat.c000066400000000000000000000020701414523752600207100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/get_str.c000066400000000000000000000007731414523752600162010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/get_str_pretty.c000066400000000000000000000010231414523752600175750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/inlines.c000066400000000000000000000013461414523752600161700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fq_nmod.h" void __fq_nmod_ctx_prime(fmpz_t p, fq_nmod_ctx_t ctx) { fmpz_set(p, fq_nmod_ctx_prime(ctx)); } flint2-2.8.4/fq_nmod/inv.c000066400000000000000000000032471414523752600153250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fq_nmod_inv). Zero is not invertible.\n"); flint_abort(); } 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); } } flint2-2.8.4/fq_nmod/is_invertible.c000066400000000000000000000010211414523752600173530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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/is_invertible.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod/is_invertible_f.c000066400000000000000000000010231414523752600176620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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/is_invertible_f.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod/is_square.c000066400000000000000000000010161414523752600165140ustar00rootroot00000000000000/* 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 2.1 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/is_square.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod/mul.c000066400000000000000000000012161414523752600153200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/mul_fmpz.c000066400000000000000000000013001414523752600163460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { fmpz_t rx; fmpz_init(rx); fmpz_mod(rx, x, fq_nmod_ctx_prime(ctx)); nmod_poly_scalar_mul_nmod(rop, op, fmpz_get_ui(rx)); fmpz_clear(rx); } flint2-2.8.4/fq_nmod/mul_si.c000066400000000000000000000011671414523752600160200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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) { mp_limb_t rx = x < 0 ? -x : x; nmod_poly_scalar_mul_nmod(rop, op, rx); if (x < 0) nmod_poly_neg(rop, rop); } flint2-2.8.4/fq_nmod/mul_ui.c000066400000000000000000000011021414523752600160070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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, n_mod2_preinv(x, ctx->mod.n, ctx->mod.ninv)); } flint2-2.8.4/fq_nmod/multiplicative_order.c000066400000000000000000000010301414523752600207430ustar00rootroot00000000000000/* 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 2.1 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/multiplicative_order.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod/neg.c000066400000000000000000000011451414523752600152750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/norm.c000066400000000000000000000035671414523752600155110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod.h" #include "nmod_mat.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); } } flint2-2.8.4/fq_nmod/pow.c000066400000000000000000000110361414523752600153310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fq_nmod_pow). e < 0.\n"); flint_abort(); } 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_cmpabs(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); } flint2-2.8.4/fq_nmod/pth_root.c000066400000000000000000000015111414523752600163570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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(rop, rop, fq_nmod_ctx_prime(ctx), ctx); } } flint2-2.8.4/fq_nmod/rand.c000066400000000000000000000017611414523752600154540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/randtest.c000066400000000000000000000034551414523752600163560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/set_nmod_poly.c000066400000000000000000000014751414523752600174050ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_nmod/sqr.c000066400000000000000000000010411414523752600153240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/sqrt.c000066400000000000000000000010111414523752600155050ustar00rootroot00000000000000/* 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 2.1 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/sqrt.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod/sub.c000066400000000000000000000015641414523752600153220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod/sub_one.c000066400000000000000000000011641414523752600161570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fq_nmod/test/000077500000000000000000000000001414523752600153365ustar00rootroot00000000000000flint2-2.8.4/fq_nmod/test/t-add.c000066400000000000000000000010161414523752600164710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-assign.c000066400000000000000000000010221414523752600172220ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_nmod/test/t-ctx_init.c000066400000000000000000000010231414523752600175600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-div.c000066400000000000000000000010161414523752600165230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-frobenius.c000066400000000000000000000010241414523752600177340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-get_set_nmod_poly.c000066400000000000000000000040101414523752600214500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { slong i, j; fq_nmod_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("get/set_nmod_poly... "); fflush(stdout); for (j = 0; j < 10*flint_test_multiplier(); j++) { fq_nmod_ctx_randtest(ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_nmod/test/t-inv.c000066400000000000000000000010161414523752600165350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-is_invertible.c000066400000000000000000000010301414523752600205730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-is_invertible_f.c000066400000000000000000000010321414523752600211020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-is_primitive.c000066400000000000000000000010271414523752600204460ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_nmod/test/t-is_square.c000066400000000000000000000010251414523752600177340ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_nmod/test/t-mul.c000066400000000000000000000010161414523752600165360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-mul_fmpz.c000066400000000000000000000064511414523752600176020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fq_nmod.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_fmpz...."); fflush(stdout); /* 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(ctx, 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,fq_nmod_ctx_prime(ctx)); 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"); 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(ctx, 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, fq_nmod_ctx_prime(ctx)); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod/test/t-mul_si.c000066400000000000000000000051321414523752600172340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fq_nmod.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_si...."); fflush(stdout); /* 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_randtest(ctx, state); 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:\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 = %wd\n",x); 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_randtest(ctx, state); 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, -x); nmod_poly_neg(b, b); } else { nmod_poly_scalar_mul_nmod(b, a, 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("x = %wd\n",x); abort(); } fq_nmod_clear(a, ctx); fq_nmod_clear(c, ctx); nmod_poly_clear(b); fq_nmod_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod/test/t-mul_ui.c000066400000000000000000000050541414523752600172410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fq_nmod.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_ui...."); fflush(stdout); /* 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_randtest(ctx, state); 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); 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_randtest(ctx, state); 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); abort(); } fq_nmod_clear(a, ctx); fq_nmod_clear(c, ctx); nmod_poly_clear(b); fq_nmod_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod/test/t-multiplicative_order.c000066400000000000000000000010371414523752600221720ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_nmod/test/t-neg.c000066400000000000000000000010161414523752600165120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-norm.c000066400000000000000000000010171414523752600167150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-pow.c000066400000000000000000000010161414523752600165460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-pth_root.c000066400000000000000000000010231414523752600175750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-sqr.c000066400000000000000000000010161414523752600165460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-sqrt.c000066400000000000000000000010201414523752600167250ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_nmod/test/t-sub.c000066400000000000000000000010161414523752600165320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/test/t-trace.c000066400000000000000000000010201414523752600170320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_nmod/trace.c000066400000000000000000000034431414523752600156250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_embed.h000066400000000000000000000030211414523752600156600ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #define FQ_EMBED_TEMPLATES_INLINE FLINT_DLL #else #define FQ_NMOD_EMBED_INLINE static __inline__ #define FQ_EMBED_TEMPLATES_INLINE static __inline__ #endif #include "fq_nmod.h" #define T fq_nmod #define B nmod #include "fq_embed_templates.h" FQ_EMBED_TEMPLATES_INLINE 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 FQ_NMOD_EMBED_INLINE 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); } #endif flint2-2.8.4/fq_nmod_embed/000077500000000000000000000000001414523752600155135ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_embed/composition_matrix.c000066400000000000000000000011551414523752600216100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_embed.h" #include "fq_nmod_poly.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" #undef B #undef CAP_T #undef T flint2-2.8.4/fq_nmod_embed/embed.c000066400000000000000000000011401414523752600167270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_embed.h" #include "fq_nmod_poly.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/embed.c" #undef B #undef CAP_T #undef T flint2-2.8.4/fq_nmod_embed/matrices.c000066400000000000000000000011431414523752600174650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_embed.h" #include "fq_nmod_poly.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/matrices.c" #undef B #undef CAP_T #undef T flint2-2.8.4/fq_nmod_embed/mul_matrix.c000066400000000000000000000033641414523752600200460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } } flint2-2.8.4/fq_nmod_embed/test/000077500000000000000000000000001414523752600164725ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_embed/test/t-composition_matrix.c000066400000000000000000000011341414523752600230250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_embed/test/t-embed.c000066400000000000000000000011501414523752600201500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_embed.h" #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_embed/test/t-embed_matrices.c000066400000000000000000000011301414523752600220350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_embed/test/t-mono_dual_matrix.c000066400000000000000000000011321414523752600224350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_embed/test/t-mul_matrix.c000066400000000000000000000011241414523752600212560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat.h000066400000000000000000000023771414523752600154020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #define FQ_NMOD_MAT_INLINE FLINT_DLL #else #define FQ_MAT_TEMPLATES_INLINE static __inline__ #define FQ_NMOD_MAT_INLINE static __inline__ #endif #include "fq_nmod.h" #include "fq_nmod_vec.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 FQ_NMOD_MAT_INLINE 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; } #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates.h" #undef CAP_T #undef T #endif flint2-2.8.4/fq_nmod_mat/000077500000000000000000000000001414523752600152205ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_mat/add.c000066400000000000000000000010171414523752600161130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/add.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/can_solve.c000066400000000000000000000010261414523752600173340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/can_solve.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/charpoly_danilevsky.c000066400000000000000000000011221414523752600214320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #include "fq_nmod_poly.h" #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/charpoly_danilevsky.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/clear.c000066400000000000000000000010211414523752600164440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/concat_horizontal.c000066400000000000000000000010431414523752600211020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/concat_horizontal.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/concat_vertical.c000066400000000000000000000010411414523752600205200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/concat_vertical.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/equal.c000066400000000000000000000010211414523752600164650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/equal.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/fprint.c000066400000000000000000000010221414523752600166610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/fprint.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/init.c000066400000000000000000000010201414523752600163200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/init.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/init_set.c000066400000000000000000000010241414523752600171770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/init_set.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/inlines.c000066400000000000000000000010661414523752600170300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "fq_nmod_mat.h" flint2-2.8.4/fq_nmod_mat/inv.c000066400000000000000000000010211414523752600161520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/inv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/is_one.c000066400000000000000000000010231414523752600166340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/is_one.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/is_zero.c000066400000000000000000000010231414523752600170320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/is_zero.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/lu.c000066400000000000000000000010161414523752600160020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/lu.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/lu_classical.c000066400000000000000000000010301414523752600200140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/lu_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/lu_recursive.c000066400000000000000000000010301414523752600200650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/lu_recursive.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/minpoly.c000066400000000000000000000011061414523752600170510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #include "fq_nmod_poly.h" #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/minpoly.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/mul.c000066400000000000000000000010171414523752600161600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/mul.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/mul_KS.c000066400000000000000000000010221414523752600165510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/mul_KS.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/mul_classical.c000066400000000000000000000010311414523752600201720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/mul_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/mul_vec.c000066400000000000000000000010571414523752600170210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/mul_vec.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/neg.c000066400000000000000000000010171414523752600161340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/neg.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/nullspace.c000066400000000000000000000010251414523752600173500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/nullspace.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/one.c000066400000000000000000000010201414523752600161360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/one.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/randops.c000066400000000000000000000010231414523752600170260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/randops.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/randpermdiag.c000066400000000000000000000010301414523752600200130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/randpermdiag.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/randrank.c000066400000000000000000000010241414523752600171610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/randrank.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/randtest.c000066400000000000000000000010241414523752600172050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/randtest.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/randtril.c000066400000000000000000000010241414523752600172000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/randtril.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/randtriu.c000066400000000000000000000010241414523752600172110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/randtriu.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/rank.c000066400000000000000000000010201414523752600163100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/rank.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/reduce_row.c000066400000000000000000000074741414523752600175360ustar00rootroot00000000000000/* 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 2.1 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_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 = FLINT_BIT_COUNT(ctx->p)*2 + 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, ctx->p); 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); } flint2-2.8.4/fq_nmod_mat/rref.c000066400000000000000000000010201414523752600163130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/rref.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/set.c000066400000000000000000000010171414523752600161560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/set.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/set_fmpz_mod_mat.c000066400000000000000000000010341414523752600207110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/set_fmpz_mod_mat.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/set_nmod_mat.c000066400000000000000000000010311414523752600200300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/set_nmod_mat.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/similarity.c000066400000000000000000000011111414523752600175440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #include "fq_nmod_poly.h" #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/similarity.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/solve.c000066400000000000000000000010231414523752600165100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/solve.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/solve_tril.c000066400000000000000000000010261414523752600175450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/solve_tril.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/solve_tril_classical.c000066400000000000000000000010401414523752600215570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/solve_tril_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/solve_tril_recursive.c000066400000000000000000000010401414523752600216300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/solve_tril_recursive.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/solve_triu.c000066400000000000000000000010261414523752600175560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/solve_triu.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/solve_triu_classical.c000066400000000000000000000010401414523752600215700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/solve_triu_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/solve_triu_recursive.c000066400000000000000000000010401414523752600216410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/solve_triu_recursive.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/sub.c000066400000000000000000000010171414523752600161540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/sub.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/submul.c000066400000000000000000000010221414523752600166660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/submul.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/swap.c000066400000000000000000000010201414523752600163270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/swap.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/test/000077500000000000000000000000001414523752600161775ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_mat/test/t-add_sub.c000066400000000000000000000010321414523752600202010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-can_solve.c000066400000000000000000000010351414523752600205540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-charpoly.c000066400000000000000000000010651414523752600204270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-concat_horizontal.c000066400000000000000000000010521414523752600223220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-concat_vertical.c000066400000000000000000000010501414523752600217400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-equal.c000066400000000000000000000010301414523752600177050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-inv.c000066400000000000000000000010301414523752600173720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-invert_rows_cols.c000066400000000000000000000010451414523752600222050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-is_zero.c000066400000000000000000000010321414523752600202520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-lu_classical.c000066400000000000000000000010371414523752600212430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-lu_recursive.c000066400000000000000000000010371414523752600213140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-minpoly.c000066400000000000000000000010641414523752600202740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-mul.c000066400000000000000000000010261414523752600174000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-mul_KS.c000066400000000000000000000010311414523752600177710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-mul_vec.c000066400000000000000000000010351414523752600202350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-nullspace.c000066400000000000000000000010341414523752600205700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-one.c000066400000000000000000000010271414523752600173650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-rank.c000066400000000000000000000010271414523752600175370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-rref.c000066400000000000000000000010271414523752600175420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-set_fmpz_mod_mat.c000066400000000000000000000010441414523752600221320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-set_nmod_mat.c000066400000000000000000000010401414523752600212500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-solve.c000066400000000000000000000010321414523752600177300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-solve_tril.c000066400000000000000000000010351414523752600207650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-solve_tril_classical.c000066400000000000000000000010471414523752600230060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-solve_tril_recursive.c000066400000000000000000000010471414523752600230570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-solve_triu.c000066400000000000000000000010351414523752600207760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-solve_triu_classical.c000066400000000000000000000010471414523752600230170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-solve_triu_recursive.c000066400000000000000000000010471414523752600230700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-submul.c000066400000000000000000000010311414523752600201060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-vec_mul.c000066400000000000000000000010351414523752600202350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-window_init_clear.c000066400000000000000000000010521414523752600223020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/test/t-zero.c000066400000000000000000000010271414523752600175630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_mat/vec_mul.c000066400000000000000000000010571414523752600170210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/vec_mul.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/window_clear.c000066400000000000000000000010301414523752600200330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/window_clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/window_init.c000066400000000000000000000010271414523752600177160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/window_init.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mat/zero.c000066400000000000000000000010201414523752600163340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mat.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_mat_templates/zero.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_mpoly.h000066400000000000000000002130361414523752600157550ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define FQ_NMOD_MPOLY_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "nmod_mpoly.h" #include "n_poly.h" #ifdef __cplusplus extern "C" { #endif /* Type definitions *********************************************************/ /* context object for fq_nmod_mpoly */ 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]; /* fq_nmod_mpoly_t sparse multivariates with fq_nmod coefficients */ 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]; /* 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]; FLINT_DLL void bad_fq_nmod_embed_clear(bad_fq_nmod_embed_t emb); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void bad_n_fq_embed_sm_to_lg(mp_limb_t * out_, const n_poly_t in_, const bad_fq_nmod_embed_t emb); FLINT_DLL 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); FLINT_DLL void bad_n_fq_embed_lg_to_sm(n_poly_t out_, const mp_limb_t * in_, const bad_fq_nmod_embed_t emb); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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]; FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ************************************************************/ FLINT_DLL 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); FLINT_DLL void fq_nmod_mpoly_ctx_init(fq_nmod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, const fq_nmod_ctx_t fqctx); FLINT_DLL 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); FLINT_DLL 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); } FLINT_DLL void fq_nmod_mpoly_init2(fq_nmod_mpoly_t A, slong alloc, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_init3(fq_nmod_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_realloc(fq_nmod_mpoly_t A, slong alloc, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_fit_length(fq_nmod_mpoly_t A, slong length, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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 **************************************************************/ FLINT_DLL 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); FLINT_DLL char * fq_nmod_mpoly_get_str_pretty(const fq_nmod_mpoly_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL int fq_nmod_mpoly_fprint_pretty(FILE * file, const fq_nmod_mpoly_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx); FQ_NMOD_MPOLY_INLINE 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); } /* Basic manipulation *******************************************************/ FLINT_DLL void fq_nmod_mpoly_gen(fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL int fq_nmod_mpoly_is_gen(const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_set(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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) { fq_nmod_mpoly_struct t = *A; *A = *B; *B = t; } /* 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; } FLINT_DLL int fq_nmod_mpoly_is_fq_nmod(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_get_fq_nmod(fq_nmod_t c, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_set_fq_nmod(fq_nmod_mpoly_t A, const fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_set_n_fq(fq_nmod_mpoly_t A, const mp_limb_t * c, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_set_ui(fq_nmod_mpoly_t A, ulong c, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_set_fmpz(fq_nmod_mpoly_t A, const fmpz_t c, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_set_fq_nmod_gen(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL 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; } FLINT_DLL int fq_nmod_mpoly_is_one(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); /* Degrees *******************************************************************/ FQ_NMOD_MPOLY_INLINE 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); } FQ_NMOD_MPOLY_INLINE 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); } FQ_NMOD_MPOLY_INLINE 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); } FQ_NMOD_MPOLY_INLINE void fq_nmod_mpoly_degree_fmpz(fmpz_t deg, const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) { mpoly_degree_fmpz(deg, A->exps, A->length, A->bits, var, ctx->minfo); } FQ_NMOD_MPOLY_INLINE slong fq_nmod_mpoly_degree_si(const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx) { return mpoly_degree_si(A->exps, A->length, A->bits, var, ctx->minfo); } FQ_NMOD_MPOLY_INLINE 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); } FQ_NMOD_MPOLY_INLINE 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); } FQ_NMOD_MPOLY_INLINE 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); } FQ_NMOD_MPOLY_INLINE 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); } /* Coefficients **************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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; } FQ_NMOD_MPOLY_INLINE 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)); } /* conversion ****************************************************************/ FLINT_DLL int fq_nmod_mpoly_is_fq_nmod_poly(const fq_nmod_mpoly_t A, slong var, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ****************************************************************/ FLINT_DLL 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 ******************************************************/ FLINT_DLL 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; } FLINT_DLL void fq_nmod_mpoly_resize(fq_nmod_mpoly_t A, slong new_length, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FQ_NMOD_MPOLY_INLINE 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); } FQ_NMOD_MPOLY_INLINE 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fq_nmod_mpoly_sort_terms(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_combine_like_terms(fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_reverse(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_assert_canonical(const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _fq_nmod_mpoly_push_exp_ffmpz(fq_nmod_mpoly_t A, const fmpz * exp, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void _fq_nmod_mpoly_push_exp_pfmpz(fq_nmod_mpoly_t A, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void _fq_nmod_mpoly_push_exp_ui(fq_nmod_mpoly_t A, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx); /* Random generation *********************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ******************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 *********************************************************/ FLINT_DLL void fq_nmod_mpoly_neg(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fq_nmod_mpoly_make_monic(fq_nmod_mpoly_t A, const fq_nmod_mpoly_t B, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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 **********************************************************/ FLINT_DLL 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 ****************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ******************************************************************/ FLINT_DLL 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); FLINT_DLL 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 ******************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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"); } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ***************************************************************/ FLINT_DLL 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; } FLINT_DLL 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 ***********************************************************************/ FLINT_DLL void fq_nmod_mpoly_term_content(fq_nmod_mpoly_t M, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fq_nmod_mpoly_deflation(fmpz * shift, fmpz * stride, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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) ******************************************************************************/ FLINT_DLL void mpoly_void_ring_init_fq_nmod_mpoly_ctx(mpoly_void_ring_t R, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int fq_nmod_mpoly_repack_bits_inplace(fq_nmod_mpoly_t A, flint_bitcnt_t Abits, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_ctx_change_modulus(fq_nmod_mpoly_ctx_t ctx, slong deg); /* Univariates ***************************************************************/ FLINT_DLL void fq_nmod_mpoly_univar_init(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_univar_clear(fq_nmod_mpoly_univar_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_univar_fit_length(fq_nmod_mpoly_univar_t A, slong length, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_univar_print_pretty(const fq_nmod_mpoly_univar_t A, const char ** x, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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) { fq_nmod_mpoly_univar_struct t = *A; *A = *B; *B = t; } FQ_NMOD_MPOLY_INLINE 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); } 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; } FQ_NMOD_MPOLY_INLINE 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); } 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); } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ********************************************************************/ FLINT_DLL int fq_nmod_mpolyu_is_canonical(const fq_nmod_mpolyu_t poly, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyu_init(fq_nmod_mpolyu_t A, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL void fq_nmod_mpolyu_zero(fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx); FLINT_DLL int fq_nmod_mpolyu_is_one(fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx); FLINT_DLL void fq_nmod_mpolyu_print_pretty(const fq_nmod_mpolyu_t poly, const char ** x, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyu_fit_length(fq_nmod_mpolyu_t A, slong length, const fq_nmod_mpoly_ctx_t uctx); FLINT_DLL void fq_nmod_mpolyu_one(fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t uctx); FLINT_DLL void fq_nmod_mpolyu_degrees_si( slong * degs, const fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyu_repack_bits_inplace( fq_nmod_mpolyu_t A, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyu_shift_right(fq_nmod_mpolyu_t A, ulong s); FLINT_DLL void fq_nmod_mpolyu_shift_left(fq_nmod_mpolyu_t A, ulong s); FLINT_DLL int fq_nmod_mpolyu_content_mpoly(fq_nmod_mpoly_t g, const fq_nmod_mpolyu_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyu_scalar_mul_fq_nmod(fq_nmod_mpolyu_t A, fq_nmod_t c, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyu_set(fq_nmod_mpolyu_t A, const fq_nmod_mpolyu_t B, const fq_nmod_mpoly_ctx_t uctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_DLL void fq_nmod_mpolyu_divexact_mpoly_inplace(fq_nmod_mpolyu_t A, fq_nmod_mpoly_t c, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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_DLL 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 ********************************************************************/ FLINT_DLL void fq_nmod_mpolyn_init(fq_nmod_mpolyn_t A, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyn_clear(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyn_swap(fq_nmod_mpolyn_t A, fq_nmod_mpolyn_t B); FLINT_DLL int fq_nmod_mpolyn_is_canonical(const fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyn_zero(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyn_one(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL int fq_nmod_mpolyn_is_zero(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyn_print_pretty(const fq_nmod_mpolyn_t A, const char ** x_in, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyn_fit_length(fq_nmod_mpolyn_t A, slong length, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyn_fit_bits(fq_nmod_mpolyn_t A, slong bits, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); 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 *******************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fq_nmod_mpolyun_init(fq_nmod_mpolyun_t A, flint_bitcnt_t bits, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyun_clear(fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL int fq_nmod_mpolyun_is_canonical(const fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyun_print_pretty(const fq_nmod_mpolyun_t poly, const char ** x, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyun_swap(fq_nmod_mpolyun_t A, fq_nmod_mpolyun_t B); FLINT_DLL void fq_nmod_mpolyun_zero(fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyun_fit_length(fq_nmod_mpolyun_t A, slong length, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyun_one(fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL int fq_nmod_mpolyn_is_nonzero_fq_nmod(const fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL int fq_nmod_mpolyun_is_nonzero_fq_nmod(const fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fq_nmod_mpolyun_shift_right(fq_nmod_mpolyun_t A, ulong s); FLINT_DLL void fq_nmod_mpolyun_shift_left(fq_nmod_mpolyun_t A, ulong s); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fq_nmod_mpolyn_content_poly(fq_nmod_poly_t g, fq_nmod_mpolyn_t B, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyun_content_poly(fq_nmod_poly_t g, fq_nmod_mpolyun_t B, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL slong fq_nmod_mpolyn_lastdeg(fq_nmod_mpolyn_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL slong fq_nmod_mpolyun_lastdeg(fq_nmod_mpolyun_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyun_set( fq_nmod_mpolyun_t A, const fq_nmod_mpolyun_t B, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 *********************************************************************/ FLINT_DLL int fq_nmod_next(fq_nmod_t alpha, const fq_nmod_ctx_t fqctx); FLINT_DLL void fq_nmod_next_not_zero(fq_nmod_t alpha, const fq_nmod_ctx_t fqctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ****************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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]; FLINT_DLL void fq_nmod_mpoly_geobucket_init(fq_nmod_mpoly_geobucket_t B, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_geobucket_clear(fq_nmod_mpoly_geobucket_t B, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_geobucket_empty(fq_nmod_mpoly_t p, fq_nmod_mpoly_geobucket_t B, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_geobucket_fit_length(fq_nmod_mpoly_geobucket_t B, slong i, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_geobucket_set(fq_nmod_mpoly_geobucket_t B, fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_geobucket_add(fq_nmod_mpoly_geobucket_t B, fq_nmod_mpoly_t p, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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 ******************************************************************************/ /* test that r is a valid remainder upon division by g this means that no monomial of r is divisible by lm(g) */ FQ_NMOD_MPOLY_INLINE 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); /* mask with high bit set in each field of exponent vector */ for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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_printf("fq_nmod_mpoly_remainder_strongtest FAILED i = %wd\n", i); flint_printf("rem ");fq_nmod_mpoly_print_pretty(r, NULL, ctx); printf("\n\n"); flint_printf("den ");fq_nmod_mpoly_print_pretty(g, NULL, ctx); printf("\n\n"); flint_abort(); } } flint_free(rexp); flint_free(gexp); } #ifdef __cplusplus } #endif #endif flint2-2.8.4/fq_nmod_mpoly/000077500000000000000000000000001414523752600155775ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_mpoly/add.c000066400000000000000000000101451414523752600164740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/add_fq_nmod.c000066400000000000000000000066541414523752600202110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_nmod_mpoly/cmp.c000066400000000000000000000022301414523752600165170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/combine_like_terms.c000066400000000000000000000030641414523752600216000ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/compose_fq_nmod_mpoly.c000066400000000000000000000036111414523752600223340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/compose_fq_nmod_mpoly_gen.c000066400000000000000000000024101414523752600231610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/compose_fq_nmod_mpoly_geobucket.c000066400000000000000000000036241414523752600243700ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/compose_fq_nmod_mpoly_horner.c000066400000000000000000000251711414523752600237160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 == 0) { fq_nmod_mpoly_zero(A, 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; } flint2-2.8.4/fq_nmod_mpoly/compose_fq_nmod_poly.c000066400000000000000000000153451414523752600221660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_nmod_mpoly/compose_mat.c000066400000000000000000000042151414523752600202530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_vec(v, M, u); 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; } flint2-2.8.4/fq_nmod_mpoly/content_vars.c000066400000000000000000000127401414523752600204540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/ctx_change_modulus.c000066400000000000000000000012071414523752600216160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" void fq_nmod_mpoly_ctx_change_modulus(fq_nmod_mpoly_ctx_t ctx, slong deg) { fmpz_t P; fmpz_init_set_ui(P, ctx->fqctx->mod.n); fq_nmod_ctx_clear(ctx->fqctx); fq_nmod_ctx_init(ctx->fqctx, P, deg, "#"); fmpz_clear(P); } flint2-2.8.4/fq_nmod_mpoly/ctx_clear.c000066400000000000000000000010301414523752600177010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/ctx_init.c000066400000000000000000000017251414523752600175710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) { fmpz_t P; mpoly_ctx_init(ctx->minfo, nvars, ord); fmpz_init_set_ui(P, p); fq_nmod_ctx_init(ctx->fqctx, P, deg, "#"); fmpz_clear(P); } 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); } flint2-2.8.4/fq_nmod_mpoly/ctx_init_rand.c000066400000000000000000000023211414523752600205660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) << (FLINT_BITS - 2)); } 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); } flint2-2.8.4/fq_nmod_mpoly/deflate.c000066400000000000000000000031551414523752600173530ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/deflation.c000066400000000000000000000013031414523752600177050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/derivative.c000066400000000000000000000065141414523752600201130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/discriminant.c000066400000000000000000000014761414523752600204370ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fq_nmod_mpoly/div.c000066400000000000000000000011751414523752600165310ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fq_nmod_mpoly/div_monagan_pearce.c000066400000000000000000000241131414523752600215450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 cofficient 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 neccesary */ 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); } flint2-2.8.4/fq_nmod_mpoly/divides.c000066400000000000000000000013011414523752600173650ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fq_nmod_mpoly/divides_monagan_pearce.c000066400000000000000000000542351414523752600224220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 indicies */ 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 cofficient 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 neccesary */ 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 cofficient 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; } flint2-2.8.4/fq_nmod_mpoly/divrem.c000066400000000000000000000013131414523752600172270ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fq_nmod_mpoly/divrem_ideal.c000066400000000000000000000013501414523752600203660ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fq_nmod_mpoly/divrem_ideal_monagan_pearce.c000066400000000000000000000320021414523752600234030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; 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 * acc, * pp, * lc_minus_inv; TMP_INIT; TMP_START; 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)); 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; } flint2-2.8.4/fq_nmod_mpoly/divrem_monagan_pearce.c000066400000000000000000000604171414523752600222600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 indicies */ hind = (slong *) TMP_ALLOC(Blen*sizeof(slong)); for (i = 0; i < Blen; i++) hind[i] = 1; /* mask with high bit set in each field of exponent vector */ mask = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); /* 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 cofficient 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 neccesary */ 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 cofficient 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 neccesary */ 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); } flint2-2.8.4/fq_nmod_mpoly/equal.c000066400000000000000000000016701414523752600170560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/equal_fq_nmod.c000066400000000000000000000015171414523752600205610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/evaluate_all.c000066400000000000000000000063511414523752600204060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/evaluate_one.c000066400000000000000000000136351414523752600204220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/fit_length.c000066400000000000000000000013561414523752600200730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/fit_length_fit_bits.c000066400000000000000000000031471414523752600217560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } } } flint2-2.8.4/fq_nmod_mpoly/fit_length_reset_bits.c000066400000000000000000000014431414523752600223130ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/fprint_pretty.c000066400000000000000000000046161414523752600206630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" 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; } flint2-2.8.4/fq_nmod_mpoly/fq_nmod_embed.c000066400000000000000000000503261414523752600205300ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/gcd.c000066400000000000000000001656231414523752600165150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/gcd_brown.c000066400000000000000000000013741414523752600177140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/gcd_cofactors.c000066400000000000000000000032161414523752600205450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/gcd_hensel.c000066400000000000000000000321031414523752600200350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/gcd_zippel.c000066400000000000000000000360751414523752600200760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/gcd_zippel2.c000066400000000000000000002562131414523752600201560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" #include "fq_nmod_mpoly_factor.h" 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); } flint2-2.8.4/fq_nmod_mpoly/gen.c000066400000000000000000000017051414523752600165170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/geobuckets.c000066400000000000000000000103261414523752600201000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/get_coeff_fq_nmod_fmpz.c000066400000000000000000000017111414523752600224230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_nmod_mpoly/get_coeff_fq_nmod_monomial.c000066400000000000000000000034241414523752600232650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/get_coeff_fq_nmod_ui.c000066400000000000000000000017201414523752600220640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_nmod_mpoly/get_coeff_vars_ui.c000066400000000000000000000103161414523752600214150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/get_fq_nmod.c000066400000000000000000000017221414523752600202270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/get_set_is_fq_nmod_poly.c000066400000000000000000000100261414523752600226350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/get_str_pretty.c000066400000000000000000000073601414523752600210270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); } flint2-2.8.4/fq_nmod_mpoly/get_term.c000066400000000000000000000017651414523752600175620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/get_term_coeff_fq_nmod.c000066400000000000000000000014211414523752600224140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/get_term_exp_fmpz.c000066400000000000000000000015471414523752600214700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/get_term_exp_si.c000066400000000000000000000015421414523752600211220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/get_term_exp_ui.c000066400000000000000000000015421414523752600211240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/get_term_monomial.c000066400000000000000000000017661414523752600214560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/get_term_var_exp_si.c000066400000000000000000000015611414523752600217730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/get_term_var_exp_ui.c000066400000000000000000000015611414523752600217750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/inflate.c000066400000000000000000000047661414523752600174020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/init.c000066400000000000000000000023461414523752600167130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/inlines.c000066400000000000000000000011511414523752600174020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_MPOLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fq_nmod_mpoly.h" flint2-2.8.4/fq_nmod_mpoly/interp.c000066400000000000000000003233401414523752600172510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/is_canonical.c000066400000000000000000000046271414523752600203760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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"); } } flint2-2.8.4/fq_nmod_mpoly/is_fq_nmod.c000066400000000000000000000013721414523752600200640ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/is_gen.c000066400000000000000000000013641414523752600172130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/is_one.c000066400000000000000000000013741414523752600172240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/lead_coeff_vars.c000066400000000000000000000036431414523752600210530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/fq_nmod_mpoly/make_monic.c000066400000000000000000000016441414523752600200520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/mpolyn.c000066400000000000000000000130641414523752600172650ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_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; } 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; } flint2-2.8.4/fq_nmod_mpoly/mpolyn_gcd_brown.c000066400000000000000000001051161414523752600213110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/mpolyu.c000066400000000000000000000566411414523752600173040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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++) SLONG_SWAP(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; } flint2-2.8.4/fq_nmod_mpoly/mpolyu_divides.c000066400000000000000000000367031414523752600210100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 indicies */ 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 neccesary */ 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; } flint2-2.8.4/fq_nmod_mpoly/mpolyu_gcdp_zippel.c000066400000000000000000001353211414523752600216550ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_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, 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, 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; } flint2-2.8.4/fq_nmod_mpoly/mpolyun.c000066400000000000000000000453401414523752600174540ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_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; } flint2-2.8.4/fq_nmod_mpoly/mul.c000066400000000000000000000011761414523752600165450ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fq_nmod_mpoly/mul_johnson.c000066400000000000000000000353771414523752600203150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/neg.c000066400000000000000000000016341414523752600165200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/one.c000066400000000000000000000013511414523752600165240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/pow_fmpz.c000066400000000000000000000036101414523752600176040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/pow_rmul.c000066400000000000000000000017161414523752600176140ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/fq_nmod_mpoly/pow_ui.c000066400000000000000000000035041414523752600172470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/profile/000077500000000000000000000000001414523752600172375ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_mpoly/profile/p-gcd.c000066400000000000000000000213771414523752600204070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" #include "profiler.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() { 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; } flint2-2.8.4/fq_nmod_mpoly/push_term_fq_nmod_fmpz.c000066400000000000000000000035151414523752600225140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/push_term_fq_nmod_ui.c000066400000000000000000000024251414523752600221540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/quadratic_root.c000066400000000000000000000372351414523752600207750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/randtest_bits.c000066400000000000000000000025631414523752600206160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/randtest_bound.c000066400000000000000000000022751414523752600207640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/randtest_bounds.c000066400000000000000000000023031414523752600211370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/realloc.c000066400000000000000000000017601414523752600173700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/fq_nmod_mpoly/repack_bits.c000066400000000000000000000041121414523752600202270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/resize.c000066400000000000000000000020551414523752600172460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/resultant.c000066400000000000000000000016761414523752600177760ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fq_nmod_mpoly/reverse.c000066400000000000000000000021001414523752600174070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/scalar_addmul_fq_nmod.c000066400000000000000000000111011414523752600222330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/scalar_mul_fq_nmod.c000066400000000000000000000047361414523752600216020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/set.c000066400000000000000000000015751414523752600165460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/set_coeff_fq_nmod_fmpz.c000066400000000000000000000057331414523752600224470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/set_coeff_fq_nmod_monomial.c000066400000000000000000000022771414523752600233060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/set_coeff_fq_nmod_ui.c000066400000000000000000000016311414523752600221010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/set_fmpz.c000066400000000000000000000021541414523752600175740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/set_fq_nmod.c000066400000000000000000000024001414523752600202350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/set_fq_nmod_gen.c000066400000000000000000000014431414523752600210740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/set_str_pretty.c000066400000000000000000000026351414523752600210430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/fq_nmod_mpoly/set_term_coeff_fq_nmod.c000066400000000000000000000014361414523752600224360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/set_term_exp_fmpz.c000066400000000000000000000020161414523752600214740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/set_term_exp_ui.c000066400000000000000000000020031414523752600211310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly/setform.c000066400000000000000000000024761414523752600174330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/sort_terms.c000066400000000000000000000110311414523752600201400ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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) { count_leading_zeros(msb, 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; } flint2-2.8.4/fq_nmod_mpoly/sqrt_heap.c000066400000000000000000000334011414523752600177320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" /* 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 cofficient 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; } flint2-2.8.4/fq_nmod_mpoly/sub.c000066400000000000000000000101571414523752600165400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/sub_fq_nmod.c000066400000000000000000000041251414523752600202410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_nmod_mpoly/term_content.c000066400000000000000000000033371414523752600204520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/test/000077500000000000000000000000001414523752600165565ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_mpoly/test/t-add_sub.c000066400000000000000000000303621414523752600205700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("add/sub...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-add_sub_fq_nmod.c000066400000000000000000000100351414523752600222660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("add/sub_fq_nmod...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-cmp.c000066400000000000000000000134351414523752600177500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int result; slong i, j1, j2; FLINT_TEST_INIT(state); flint_printf("cmp...."); fflush(stdout); /* 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-compose_fq_nmod_mpoly.c000066400000000000000000000377551414523752600235740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j, v; FLINT_TEST_INIT(state); flint_printf("compose_fq_nmod_mpoly...."); fflush(stdout); { 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); 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); 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); 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); 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); 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); 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); 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/nvars1 + 1); len2 = n_randint(state, 10/nvars2 + 1); exp_bound1 = n_randint(state, 10/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); 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); 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-compose_fq_nmod_poly.c000066400000000000000000000132061414523752600234000ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, v; FLINT_TEST_INIT(state); flint_printf("compose_fq_nmod_poly...."); fflush(stdout); { 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); 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); flint_abort(); } if (!fq_nmod_poly_is_zero(A, ctxB->fqctx)) { printf("FAIL\n"); flint_printf("Check example 2 equality\n", i); 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/nvars1 + 1); len2 = n_randint(state, 20); exp_bound1 = n_randint(state, 100/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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-degree.c000066400000000000000000000141431414523752600204210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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"); 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"); flint_abort(); } if (degs_si[i] != fq_nmod_mpoly_degree_si(A, i, ctx)) { printf("FAIL\n"); flint_printf("Check individual degree_si\n"); 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"); flint_abort(); } fmpz_clear(degi); } for (i = 0; i < nvars; i++) { fmpz_clear(degs[i]); flint_free(degs[i]); } flint_free(degs); } int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("degree...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-derivative.c000066400000000000000000000141441414523752600213310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int i, j, result; slong tmul = 5; FLINT_TEST_INIT(state); flint_printf("derivative...."); fflush(stdout); /* 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-div_monagan_pearce.c000066400000000000000000000150431414523752600227670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("div_monagan_pearce...."); fflush(stdout); /* 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); 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); 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); 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; 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; exp_bound = n_randint(state, 100/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 100/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 100/ctx->minfo->nvars) + 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-divrem_ideal_monagan_pearce.c000066400000000000000000000217661414523752600246420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int result; slong i, j, w; FLINT_TEST_INIT(state); flint_printf("divrem_ideal_monagan_pearce...."); fflush(stdout); /* 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); 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]; 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; exp_bound = n_randint(state, 10/ctx->minfo->nvars + 1) + 2; exp_bound1 = n_randint(state, 25/ctx->minfo->nvars + 1) + 2; exp_bound2 = n_randint(state, 20/ctx->minfo->nvars + 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); 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]; 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; exp_bound = n_randint(state, 10/ctx->minfo->nvars + 1) + 2; exp_bound1 = n_randint(state, 25/ctx->minfo->nvars + 1) + 2; exp_bound2 = n_randint(state, 20/ctx->minfo->nvars + 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-divrem_monagan_pearce.c000066400000000000000000000337521414523752600235020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int result; slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("divrem_monagan_pearce...."); fflush(stdout); /* 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); 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; 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; exp_bound = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 50/ctx->minfo->nvars) + 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); 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; 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; exp_bound = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 50/ctx->minfo->nvars) + 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); 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; 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; exp_bound = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 50/ctx->minfo->nvars) + 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); 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; 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; exp_bound = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 50/ctx->minfo->nvars) + 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); 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; 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; exp_bound = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 50/ctx->minfo->nvars) + 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-evaluate.c000066400000000000000000000176701414523752600210040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j, v; slong tmul = 5; FLINT_TEST_INIT(state); flint_printf("evaluate...."); fflush(stdout); /* 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); 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); 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-gcd.c000066400000000000000000000532701414523752600177270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); } int main(void) { slong i, j, k, tmul = 7; FLINT_TEST_INIT(state); flint_printf("gcd...."); fflush(stdout); /* 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"); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-gcd_brown.c000066400000000000000000000102461414523752600211320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_brown...."); fflush(stdout); 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 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); degbound = 1 + 50/ctx->minfo->nvars/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(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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-gcd_cofactors.c000066400000000000000000000677271414523752600220060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); } int main(void) { slong i, j, k, tmul = 2; FLINT_TEST_INIT(state); flint_printf("gcd_cofactors...."); fflush(stdout); /* 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"); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-gcd_hensel.c000066400000000000000000000123751414523752600212660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_hensel...."); fflush(stdout); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-gcd_zippel.c000066400000000000000000000120211414523752600212770ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_zippel...."); fflush(stdout); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-gcd_zippel2.c000066400000000000000000000120531414523752600213660ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_zippel2...."); fflush(stdout); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-gen.c000066400000000000000000000047151414523752600177430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "ulong_extras.h" #include "fq_nmod_mpoly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gen/is_gen...."); fflush(stdout); 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); 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); 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); flint_abort(); } fq_nmod_mpoly_clear(f1, ctx); fq_nmod_mpoly_clear(f2, ctx); fq_nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-get_coeff_vars_ui.c000066400000000000000000000134721414523752600226430ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j1, j2; FLINT_TEST_INIT(state); flint_printf("get_coeff_vars_ui...."); fflush(stdout); /* 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"); 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; 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); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-get_set_coeff.c000066400000000000000000000076541414523752600217730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int i, j, k, result; FLINT_TEST_INIT(state); flint_printf("get_set_coeff...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-get_set_coeff_fq_nmod_monomial.c000066400000000000000000000076531414523752600253700ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("get/set_coeff_fq_nmod_monomial...."); fflush(stdout); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-get_set_is_fq_nmod.c000066400000000000000000000055311414523752600230170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "ulong_extras.h" #include "fq_nmod_mpoly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("get_set_is_fq_nmod...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-get_set_str_pretty.c000066400000000000000000000034331414523752600231170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("get_set_str_pretty...."); fflush(stdout); { 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"); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(f1, ctx); fq_nmod_mpoly_ctx_clear(ctx); } } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-get_set_term_coeff_fq_nmod.c000066400000000000000000000037261414523752600245210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("get/set_term_coeff_fq_nmod...."); fflush(stdout); /* 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-get_set_term_exp_fmpz.c000066400000000000000000000055761414523752600235710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get/set_term_exp_fmpz...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-get_set_term_exp_si.c000066400000000000000000000053021414523752600232130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get/set_term_exp_si...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-get_set_term_exp_ui.c000066400000000000000000000052651414523752600232250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get/set_term_exp_ui...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-get_term.c000066400000000000000000000041021414523752600207660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("get_term...."); fflush(stdout); /* 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-get_term_monomial.c000066400000000000000000000050661414523752600226730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("get_term_monomial...."); fflush(stdout); /* 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-mpolyuu_divides.c000066400000000000000000000133111414523752600224030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); 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); 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); } int main(void) { slong i, j, tmul = 50; FLINT_TEST_INIT(state); flint_printf("mpolyuu_divides...."); fflush(stdout); /* 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-mul_johnson.c000066400000000000000000000143251414523752600215230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int i, j, result; slong tmul = 5; FLINT_TEST_INIT(state); flint_printf("mul_johnson...."); fflush(stdout); /* 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-push_term_fq_nmod_fmpz.c000066400000000000000000000077331414523752600237420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("push_term_fq_nmod_fmpz...."); fflush(stdout); /* 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, m; flint_bitcnt_t exp_bits; fmpz ** 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 = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); exp2 = (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]); } 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); /* 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 */ fq_nmod_mpoly_push_term_fq_nmod_fmpz(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_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); 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); 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 pushed polynomial matches add\ni=%wd\n",i,j); 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); for (k = 0; k < nvars; k++) { fmpz_clear(exp2[k]); flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); } flint_free(exp2); flint_free(exp); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-push_term_fq_nmod_ui.c000066400000000000000000000067651414523752600234070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("push_term_fq_nmod_ui...."); fflush(stdout); /* 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-quadratic_root.c000066400000000000000000000067241414523752600222140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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"); 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"); 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"); 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"); flint_abort(); } fq_nmod_mpoly_clear(s, ctx); fq_nmod_mpoly_clear(t, ctx); } int main(void) { slong i, j, tmul = 20; FLINT_TEST_INIT(state); flint_printf("quadratic_root...."); fflush(stdout); /* 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-repack_bits.c000066400000000000000000000151001414523752600214460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j; int success; FLINT_TEST_INIT(state); flint_printf("repack_bits...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-resize.c000066400000000000000000000063151414523752600204710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("push_term_fq_nmod_ui...."); fflush(stdout); /* 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); flint_abort(); } if (!fq_nmod_mpoly_equal(f1, f3, ctx)) { printf("FAIL\n"); flint_printf("Check resize+setterm matches add\ni=%wd\n",i); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-resultant_discriminant.c000066400000000000000000000204761414523752600237610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("resultant_discriminant...."); fflush(stdout); /* 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"); flint_abort(); } if (!fq_nmod_mpoly_equal(d, d1, ctx)) { flint_printf("FAIL: Check quadratic polynomial\n"); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-reverse.c000066400000000000000000000047251414523752600206460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("reverse...."); fflush(stdout); /* 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); 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); flint_abort(); } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-scalar_addmul_fq_nmod.c000066400000000000000000000060531414523752600234650ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("scalar_addmul_fq_nmod...."); fflush(stdout); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-scalar_mul_fq_nmod.c000066400000000000000000000141171414523752600230140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_ui...."); fflush(stdout); /* 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-sort_terms.c000066400000000000000000000041541414523752600213700ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("sort_terms...."); fflush(stdout); /* 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); flint_abort(); } } fq_nmod_mpoly_clear(f, ctx); fq_nmod_mpoly_clear(g, ctx); fq_nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-sqrt.c000066400000000000000000000125441414523752600201620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("sqrt...."); fflush(stdout); /* 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"); 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); 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); flint_abort(); } } else if (!fq_nmod_mpoly_is_zero(g, ctx)) { flint_printf("FAIL: Check nonsquare returns 0 sqrt\n"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-total_degree.c000066400000000000000000000116501414523752600216240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); } int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("total_degree...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-univar.c000066400000000000000000000066631414523752600205020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("univar...."); fflush(stdout); /* 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-univar_resultant.c000066400000000000000000000136121414523752600225730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); 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 int main(void) { FLINT_TEST_INIT(state); flint_printf("univar_resultant...."); fflush(stdout); { 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"); 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"); 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"); 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 FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/test/t-used_vars.c000066400000000000000000000045161414523752600211640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("used_vars...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly/to_from_fq_nmod_poly.c000066400000000000000000000070261414523752600221630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly/univar.c000066400000000000000000000444141414523752600172560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } 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); } SLONG_SWAP(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; } flint2-2.8.4/fq_nmod_mpoly/void_ring.c000066400000000000000000000077201414523752600177310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly_factor.h000066400000000000000000000414231414523752600173120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define FQ_NMOD_MPOLY_FACTOR_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "fq_nmod_mpoly.h" #include "nmod_mpoly_factor.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]; FLINT_DLL void fq_nmod_mpoly_factor_init(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_factor_realloc(fq_nmod_mpoly_factor_t f, slong alloc, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_factor_fit_length(fq_nmod_mpoly_factor_t f, slong len, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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; } FQ_NMOD_MPOLY_FACTOR_INLINE 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); } 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); } FQ_NMOD_MPOLY_FACTOR_INLINE 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_DLL 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); FLINT_DLL void fq_nmod_mpoly_factor_print_pretty(const fq_nmod_mpoly_factor_t f, const char ** vars, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int fq_nmod_mpoly_factor(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpoly_factor_sort(fq_nmod_mpoly_factor_t f, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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; } FQ_NMOD_MPOLY_FACTOR_INLINE 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_DLL 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; } FLINT_DLL void _fq_nmod_mpoly_get_lead0( fq_nmod_mpoly_t c, const fq_nmod_mpoly_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void n_fq_bpoly_make_primitive( n_poly_t g, n_bpoly_t A, const fq_nmod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL int n_polyu_fq_is_canonical( const n_polyu_t A, const fq_nmod_ctx_t ctx); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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; } FLINT_DLL void fq_nmod_mpolyv_clear(fq_nmod_mpolyv_t A, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyv_print_pretty(const fq_nmod_mpolyv_t poly, const char ** x, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL void fq_nmod_mpolyv_fit_length(fq_nmod_mpolyv_t A, slong length, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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]; FLINT_DLL 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); FLINT_DLL void fq_nmod_mpoly_pfrac_clear( fq_nmod_mpoly_pfrac_t I, const fq_nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 flint2-2.8.4/fq_nmod_mpoly_factor/000077500000000000000000000000001414523752600171355ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_mpoly_factor/append.c000066400000000000000000000020451414523752600205510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly_factor/clear.c000066400000000000000000000014541414523752600203730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly_factor/cmp.c000066400000000000000000000017731414523752600200700ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly_factor/compression.c000066400000000000000000000063551414523752600216530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly_factor/eval.c000066400000000000000000000140571414523752600202370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly_factor/expand.c000066400000000000000000000021671414523752600205660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly_factor/factor.c000066400000000000000000000674601414523752600205740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly_factor.h" #include "long_extras.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) { SLONG_SWAP(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; } /* Assum 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); } flint2-2.8.4/fq_nmod_mpoly_factor/factor_content.c000066400000000000000000000121131414523752600223070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 primitve 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--) SLONG_SWAP(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; } flint2-2.8.4/fq_nmod_mpoly_factor/factor_squarefree.c000066400000000000000000000303461414523752600230070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly_factor/fit_length.c000066400000000000000000000013531414523752600214260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fq_nmod_mpoly_factor/get_set_lead0.c000066400000000000000000000022761414523752600220070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fq_nmod_mpoly_factor/init.c000066400000000000000000000012471414523752600202500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly_factor/inlines.c000066400000000000000000000011671414523752600207470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_MPOLY_FACTOR_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fq_nmod_mpoly_factor.h" flint2-2.8.4/fq_nmod_mpoly_factor/irred_lgprime.c000066400000000000000000000227621414523752600221360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.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_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_printf("fatal error in _frob_combine"); flint_abort(); } _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; } flint2-2.8.4/fq_nmod_mpoly_factor/irred_smprime_wang.c000066400000000000000000000212331414523752600231570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly_factor/irred_smprime_zassenhaus.c000066400000000000000000000267771414523752600244310ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_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 evalutaion */ 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; } flint2-2.8.4/fq_nmod_mpoly_factor/irred_smprime_zippel.c000066400000000000000000001312661414523752600235360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.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 comming 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); ULONG_SWAP(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; } flint2-2.8.4/fq_nmod_mpoly_factor/lcc_wang.c000066400000000000000000000102121414523752600210520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "n_poly.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; } flint2-2.8.4/fq_nmod_mpoly_factor/mpoly_hlift.c000066400000000000000000000277001414523752600216350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fq_nmod_mpoly_factor/mpoly_pfrac.c000066400000000000000000000232671414523752600216260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly_factor/mpolyv.c000066400000000000000000000103561414523752600206340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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 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); } flint2-2.8.4/fq_nmod_mpoly_factor/n_bpoly_fq.c000066400000000000000000000245011414523752600214330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_mpoly_factor/n_bpoly_fq_factor_lgprime.c000066400000000000000000000601751414523752600245170ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.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); SLONG_SWAP(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); SLONG_SWAP(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; local_fac->num = 0; /* stupid */ 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; } flint2-2.8.4/fq_nmod_mpoly_factor/n_bpoly_fq_factor_smprime.c000066400000000000000000001125641414523752600245340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); SLONG_SWAP(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); SLONG_SWAP(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 */ local_fac->num = 0; 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 attemp 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; } flint2-2.8.4/fq_nmod_mpoly_factor/n_bpoly_hlift.c000066400000000000000000000404601414523752600221350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly_factor/polyu.c000066400000000000000000000027761414523752600204650ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly_factor.h" 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"); } 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; } flint2-2.8.4/fq_nmod_mpoly_factor/polyu3_hlift.c000066400000000000000000000344331414523752600217310ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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--) { ULONG_SWAP(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; } flint2-2.8.4/fq_nmod_mpoly_factor/polyun.c000066400000000000000000000040331414523752600206270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly_factor.h" 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"); } 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; } flint2-2.8.4/fq_nmod_mpoly_factor/print_pretty.c000066400000000000000000000015331414523752600220460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_nmod_mpoly_factor/profile/000077500000000000000000000000001414523752600205755ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_mpoly_factor/profile/p-factor.c000066400000000000000000000064311414523752600224600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_nmod_mpoly_factor.h" #include "profiler.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; } flint2-2.8.4/fq_nmod_mpoly_factor/realloc.c000066400000000000000000000037101414523752600207230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly_factor/set.c000066400000000000000000000015521414523752600200770ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_nmod_mpoly_factor/sort.c000066400000000000000000000035131414523752600202720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/fq_nmod_mpoly_factor/test/000077500000000000000000000000001414523752600201145ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_mpoly_factor/test/t-factor.c000066400000000000000000000070151414523752600220020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly_factor.h" /* 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) { 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 (!fq_nmod_mpoly_factor(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization could be computed\n"); 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"); 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"); 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(); } 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"); 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); } int main(void) { slong i, j, tmul = 20; FLINT_TEST_INIT(state); flint_printf("factor...."); fflush(stdout); for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; 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, 7, FLINT_BITS, 4); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(t, ctx); nfacs = 2 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 2 + 50/nfacs/ctx->minfo->nvars; 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_clear(t, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly_factor/test/t-factor_content.c000066400000000000000000000072351414523752600235400ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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"); 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"); 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(); } 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"); 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"); 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"); flint_abort(); } } } } fq_nmod_mpoly_clear(q, ctx); fq_nmod_mpoly_factor_clear(g, ctx); fmpz_clear(deg); } int main(void) { slong i, j, k, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_content...."); fflush(stdout); 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 * 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); nfacs = 5 + (8 + n_randint(state, 8))/ctx->minfo->nvars; 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly_factor/test/t-factor_squarefree.c000066400000000000000000000065501414523752600242270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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"); 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"); 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(); } 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"); 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); } int main(void) { slong i, j, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_squarefree...."); fflush(stdout); 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/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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly_factor/test/t-factor_wang.c000066400000000000000000000076361414523752600230270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly_factor.h" /* 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) { 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 (!fq_nmod_mpoly_factor_wang(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization 1 could be computed\n"); flint_abort(); } if (!fq_nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\ncheck factorization 2 could be computed\n"); 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"); 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"); 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_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"); 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"); 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); } int main(void) { slong i, j, tmul = 15; FLINT_TEST_INIT(state); flint_printf("factor_wang...."); fflush(stdout); for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; 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 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 2 + 40/nfacs/ctx->minfo->nvars; 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_clear(t, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly_factor/test/t-factor_zassenhaus.c000066400000000000000000000076501414523752600242530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly_factor.h" /* 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) { 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 (!fq_nmod_mpoly_factor_zassenhaus(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization 1 could be computed\n"); flint_abort(); } if (!fq_nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\ncheck factorization 2 could be computed\n"); 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"); 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"); 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_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"); 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"); 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); } int main(void) { slong i, j, tmul = 15; FLINT_TEST_INIT(state); flint_printf("factor_zassenhaus...."); fflush(stdout); for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; 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, 5); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(t, ctx); nfacs = 2 + (5 + n_randint(state, 5))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 2 + 30/nfacs/ctx->minfo->nvars; 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_clear(t, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly_factor/test/t-factor_zippel.c000066400000000000000000000076401414523752600233710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly_factor.h" /* 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) { 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 (!fq_nmod_mpoly_factor_zippel(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization 1 could be computed\n"); flint_abort(); } if (!fq_nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\ncheck factorization 2 could be computed\n"); 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"); 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"); 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_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"); 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"); 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); } int main(void) { slong i, j, tmul = 15; FLINT_TEST_INIT(state); flint_printf("factor_zippel...."); fflush(stdout); for (i = 0; i < tmul * flint_test_multiplier(); i++) { slong lower; 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, 6, FLINT_BITS, 5); fq_nmod_mpoly_init(a, ctx); fq_nmod_mpoly_init(t, ctx); nfacs = 2 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 2 + 50/nfacs/ctx->minfo->nvars; 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_clear(t, ctx); fq_nmod_mpoly_clear(a, ctx); fq_nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_nmod_mpoly_factor/test/t-gcd_subresultant.c000066400000000000000000000156751414523752600241070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: fq_nmod_mpoly_clear(ca, ctx); fq_nmod_mpoly_clear(cb, ctx); fq_nmod_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 15; FLINT_TEST_INIT(state); flint_printf("gcd_subresultant...."); fflush(stdout); 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); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_poly.h000066400000000000000000000024731414523752600156010ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #define FQ_NMOD_POLY_INLINE FLINT_DLL #else #define FQ_POLY_TEMPLATES_INLINE static __inline__ #define FQ_NMOD_POLY_INLINE static __inline__ #endif #include "fq_nmod.h" #include "fq_nmod_mat.h" #include "fmpz_mod_poly.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 #include "fq_nmod_poly_factor.h" #endif flint2-2.8.4/fq_nmod_poly/000077500000000000000000000000001414523752600154225ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_poly/add.c000066400000000000000000000010211414523752600163100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/add_series.c000066400000000000000000000010301414523752600176620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/add_series.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/add_si.c000066400000000000000000000010271414523752600170110ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/add_si.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/clear.c000066400000000000000000000010231414523752600166500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/compose.c000066400000000000000000000010251414523752600172310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/compose.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/compose_divconquer.c000066400000000000000000000010401414523752600214650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/compose_divconquer.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/compose_horner.c000066400000000000000000000010341414523752600206060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/compose_horner.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/compose_mod.c000066400000000000000000000010311414523752600200650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/compose_mod.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/compose_mod_brent_kung.c000066400000000000000000000010441414523752600223070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/compose_mod_brent_kung.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000010631414523752600254200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/compose_mod_brent_kung_precomp_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/compose_mod_brent_kung_preinv.c000066400000000000000000000010531414523752600236720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/compose_mod_brent_kung_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/compose_mod_horner.c000066400000000000000000000010401414523752600214420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/compose_mod_horner.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/compose_mod_horner_preinv.c000066400000000000000000000010471414523752600230340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/compose_mod_horner_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/compose_mod_preinv.c000066400000000000000000000010401414523752600214500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/compose_mod_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/deflate.c000066400000000000000000000010251414523752600171700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/deflate.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/deflation.c000066400000000000000000000010271414523752600175330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/deflation.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/derivative.c000066400000000000000000000010301414523752600177220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/derivative.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/div_basecase.c000066400000000000000000000010321414523752600201720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/div_basecase.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/div_newton_n_preinv.c000066400000000000000000000010411414523752600216360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/div_newton_n_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/div_series.c000066400000000000000000000010301414523752600177140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/div_series.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/divides.c000066400000000000000000000010251414523752600172130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/divides.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/divrem_basecase.c000066400000000000000000000010351414523752600207010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/divrem_basecase.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/divrem_divconquer.c000066400000000000000000000010371414523752600213140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/divrem_divconquer.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/divrem_divconquer_recursive.c000066400000000000000000000010511414523752600233770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/divrem_divconquer_recursive.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/divrem_f.c000066400000000000000000000010261414523752600173600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/divrem_f.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/divrem_newton_n_preinv.c000066400000000000000000000010441414523752600223450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/divrem_newton_n_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/equal.c000066400000000000000000000010231414523752600166710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/equal.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/equal_trunc.c000066400000000000000000000010311414523752600201030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/equal_trunc.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/evaluate_fq.c000066400000000000000000000010311414523752600200550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/evaluate_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/evaluate_fq_vec.c000066400000000000000000000011521414523752600207160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/evaluate_fq_vec.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/evaluate_fq_vec_fast.c000066400000000000000000000011571414523752600217400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/evaluate_fq_vec_fast.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/evaluate_fq_vec_iter.c000066400000000000000000000011571414523752600217460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/evaluate_fq_vec_iter.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/fit_length.c000066400000000000000000000010301414523752600177030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/fit_length.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/fprint.c000066400000000000000000000010241414523752600170650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/fprint.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/fprint_pretty.c000066400000000000000000000010331414523752600204740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/fprint_pretty.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/gcd.c000066400000000000000000000010211414523752600163150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/gcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/gcd_euclidean.c000066400000000000000000000010331414523752600203310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/gcd_euclidean.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/gcd_euclidean_f.c000066400000000000000000000010351414523752600206400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/gcd_euclidean_f.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/gcd_hgcd.c000066400000000000000000000010261414523752600173070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/gcd_hgcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/gen.c000066400000000000000000000010211414523752600163310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/gen.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/get_coeff.c000066400000000000000000000010271414523752600175070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/get_coeff.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/get_str.c000066400000000000000000000010251414523752600172330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/get_str.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/get_str_pretty.c000066400000000000000000000010341414523752600206420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/get_str_pretty.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/hamming_weight.c000066400000000000000000000010341414523752600205530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/hamming_weight.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/hgcd.c000066400000000000000000000010221414523752600164660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/hgcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/inflate.c000066400000000000000000000010251414523752600172060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/inflate.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/init.c000066400000000000000000000010221414523752600165240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/init.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/inlines.c000066400000000000000000000011441414523752600172270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_POLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fq_nmod_poly.h" flint2-2.8.4/fq_nmod_poly/inv_series_newton.c000066400000000000000000000010371414523752600213270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/inv_series_newton.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/make_monic.c000066400000000000000000000010301414523752600176620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/make_monic.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/mul.c000066400000000000000000000030631414523752600163650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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(fmpz_get_ui(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(fmpz_get_ui(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); } flint2-2.8.4/fq_nmod_poly/mul_KS.c000066400000000000000000000010241414523752600167550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/mul_KS.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/mul_classical.c000066400000000000000000000046641414523752600204130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_nmod_poly/mul_univariate.c000066400000000000000000000106241414523752600206150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_nmod_poly/mulhigh.c000066400000000000000000000010251414523752600172210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/mulhigh.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/mulhigh_classical.c000066400000000000000000000010371414523752600212420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/mulhigh_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/mullow.c000066400000000000000000000010241414523752600171020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/mullow.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/mullow_KS.c000066400000000000000000000010271414523752600175020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/mullow_KS.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/mullow_classical.c000066400000000000000000000010361414523752600211230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/mullow_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/mullow_univariate.c000066400000000000000000000063441414523752600213430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_nmod_poly/mulmod.c000066400000000000000000000010241414523752600170600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/mulmod.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/mulmod_preinv.c000066400000000000000000000010331414523752600204430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/mulmod_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/neg.c000066400000000000000000000010211414523752600163310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/neg.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/normalise.c000066400000000000000000000010271414523752600175570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/normalise.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/one.c000066400000000000000000000010211414523752600163410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/one.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/pow.c000066400000000000000000000010211414523752600163650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/pow.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/pow_trunc.c000066400000000000000000000010271414523752600176060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/pow_trunc.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/pow_trunc_binexp.c000066400000000000000000000010361414523752600211530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/pow_trunc_binexp.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/powmod_fmpz_binexp.c000066400000000000000000000010401414523752600214670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/powmod_fmpz_binexp.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/powmod_fmpz_binexp_preinv.c000066400000000000000000000010471414523752600230610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/powmod_fmpz_binexp_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/powmod_fmpz_sliding_preinv.c000066400000000000000000000010501414523752600232170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/powmod_fmpz_sliding_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/powmod_ui_binexp.c000066400000000000000000000010361414523752600211350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/powmod_ui_binexp.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/powmod_ui_binexp_preinv.c000066400000000000000000000010451414523752600225200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/powmod_ui_binexp_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/powmod_x_fmpz_preinv.c000066400000000000000000000010421414523752600220360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/powmod_x_fmpz_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/profile/000077500000000000000000000000001414523752600170625ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_poly/profile/p-factor_kaltofen_shoup_vs_fq_poly.c000066400000000000000000000067611414523752600263150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" #include "profiler.h" #include "fq_poly.h" #include "fq_nmod_poly.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_mod_poly_get_fmpz_poly(fpoly, ctx->modulus); 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; } flint2-2.8.4/fq_nmod_poly/profile/p-factor_xnpxp1.c000066400000000000000000000010451414523752600222570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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-factor_xnpxp1.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/profile/p-gcd.c000066400000000000000000000010331414523752600202150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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-gcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/profile/p-is_irreducible.c000066400000000000000000000010461414523752600224500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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-is_irreducible.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/profile/p-iterated_frobenius.c000066400000000000000000000010521414523752600233360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/profile/p-iterated_frobenius_table.c000066400000000000000000000010601414523752600245040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/profile/p-mul_univariate.c000066400000000000000000000041511414523752600225100ustar00rootroot00000000000000#include "flint.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; fmpz_t p, temp; fq_nmod_poly_t f, g, h; fq_nmod_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_nmod_ctx_init(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(p); fmpz_clear(temp); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_nmod_poly/profile/p-mullow.c000066400000000000000000000010361414523752600210020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/randtest.c000066400000000000000000000010261414523752600174110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/randtest.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/randtest_irreducible.c000066400000000000000000000010421414523752600217600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/randtest_irreducible.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/randtest_monic.c000066400000000000000000000010341414523752600205750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/randtest_monic.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/realloc.c000066400000000000000000000010251414523752600172050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/realloc.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/remove.c000066400000000000000000000010241414523752600170600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/remove.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/reverse.c000066400000000000000000000010251414523752600172370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/reverse.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/scalar_addmul_fq.c000066400000000000000000000010361414523752600210470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/scalar_addmul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/scalar_div_fq.c000066400000000000000000000010331414523752600203600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/scalar_div_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/scalar_mul_fq.c000066400000000000000000000010331414523752600203730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/scalar_mul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/scalar_submul_fq.c000066400000000000000000000010361414523752600211100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/scalar_submul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/set.c000066400000000000000000000010211414523752600163530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/set.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/set_coeff.c000066400000000000000000000010271414523752600175230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/set_coeff.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/set_fmpz_mod_poly.c000066400000000000000000000010411414523752600213130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/set_fmpz_mod_poly.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/set_fq.c000066400000000000000000000010241414523752600170440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/set_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/set_nmod_poly.c000066400000000000000000000010351414523752600204400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/set_nmod_poly.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/set_trunc.c000066400000000000000000000010271414523752600175740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/set_trunc.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/shift_left.c000066400000000000000000000010301414523752600177070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/shift_left.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/shift_right.c000066400000000000000000000010311414523752600200730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/shift_right.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/sqr.c000066400000000000000000000010211414523752600163650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/sqr.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/sqr_KS.c000066400000000000000000000010241414523752600167650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/sqr_KS.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/sqr_classical.c000066400000000000000000000010331414523752600204060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/sqr_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/sub.c000066400000000000000000000010211414523752600163510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/sub.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/sub_series.c000066400000000000000000000010301414523752600177230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/sub_series.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/swap.c000066400000000000000000000010221414523752600165330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/swap.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/test/000077500000000000000000000000001414523752600164015ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_poly/test/t-add.c000066400000000000000000000010301414523752600175300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-add_series.c000066400000000000000000000010371414523752600211110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-compose.c000066400000000000000000000010341414523752600204510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-compose_divconquer.c000066400000000000000000000010471414523752600227140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_divconquer.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/test/t-compose_horner.c000066400000000000000000000010431414523752600220260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_horner.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/test/t-compose_mod.c000066400000000000000000000010401414523752600213050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-compose_mod_brent_kung.c000066400000000000000000000010531414523752600235270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-compose_mod_brent_kung_preinv.c000066400000000000000000000010621414523752600251120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-compose_mod_horner.c000066400000000000000000000010471414523752600226710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-compose_mod_horner_preinv.c000066400000000000000000000010561414523752600242540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-compose_mod_preinv.c000066400000000000000000000010471414523752600226770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-deflate.c000066400000000000000000000010341414523752600204100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-derivative.c000066400000000000000000000010371414523752600211510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-div_basecase.c000066400000000000000000000010411414523752600214120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_basecase.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/test/t-div_newton_n_preinv.c000066400000000000000000000010501414523752600230560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-div_series.c000066400000000000000000000010371414523752600211430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-divides.c000066400000000000000000000010341414523752600204330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-divrem_basecase.c000066400000000000000000000010441414523752600221210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_basecase.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/test/t-divrem_divconquer.c000066400000000000000000000010461414523752600225340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_divconquer.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/test/t-divrem_newton_n_preinv.c000066400000000000000000000010531414523752600235650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-equal_trunc.c000066400000000000000000000010401414523752600213230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-evaluate_fq.c000066400000000000000000000010401414523752600212750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-evaluate_fq_vec_fast.c000066400000000000000000000012021414523752600231470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-gcd.c000066400000000000000000000010301414523752600175350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-gcd_euclidean.c000066400000000000000000000010421414523752600215510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/test/t-gcd_euclidean_f.c000066400000000000000000000010441414523752600220600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-gcd_hgcd.c000066400000000000000000000010351414523752600205270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_hgcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/test/t-get_str.c000066400000000000000000000010341414523752600204530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-get_str_pretty.c000066400000000000000000000010431414523752600220620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-hamming_weight.c000066400000000000000000000010431414523752600217730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-hgcd.c000066400000000000000000000010311414523752600177060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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-hgcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/test/t-inflate.c000066400000000000000000000010341414523752600204260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-inv_series_newton.c000066400000000000000000000010461414523752600225470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-make_monic.c000066400000000000000000000010371414523752600211110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-mul.c000066400000000000000000000010301414523752600175750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-mul_KS.c000066400000000000000000000010331414523752600201750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-mul_classical.c000066400000000000000000000010421414523752600216160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-mul_univariate.c000066400000000000000000000010431414523752600220300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-mulhigh.c000066400000000000000000000010341414523752600204410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-mulhigh_classical.c000066400000000000000000000010461414523752600224620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-mullow.c000066400000000000000000000010331414523752600203220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-mullow_KS.c000066400000000000000000000010361414523752600207220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-mullow_classical.c000066400000000000000000000010451414523752600223430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-mullow_univariate.c000066400000000000000000000010461414523752600225550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-mulmod.c000066400000000000000000000010331414523752600203000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-mulmod_preinv.c000066400000000000000000000010421414523752600216630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-neg.c000066400000000000000000000010301414523752600175510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-pow.c000066400000000000000000000010301414523752600176050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-pow_trunc.c000066400000000000000000000010361414523752600210260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-pow_trunc_binexp.c000066400000000000000000000010451414523752600223730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-powmod_fmpz_binexp.c000066400000000000000000000010471414523752600227160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-powmod_fmpz_binexp_preinv.c000066400000000000000000000010561414523752600243010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-powmod_fmpz_sliding_preinv.c000066400000000000000000000010571414523752600244460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-powmod_ui_binexp.c000066400000000000000000000010451414523752600223550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-powmod_ui_binexp_preinv.c000066400000000000000000000010541414523752600237400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-powmod_x_fmpz_preinv.c000066400000000000000000000010511414523752600232560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-randtest_irreducible.c000066400000000000000000000010511414523752600232000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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-randtest_irreducible.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/test/t-scalar_addmul_fq.c000066400000000000000000000010451414523752600222670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-scalar_div_fq.c000066400000000000000000000010421414523752600216000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-scalar_mul_fq.c000066400000000000000000000010421414523752600216130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-scalar_submul_fq.c000066400000000000000000000010451414523752600223300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-set_fmpz_mod_poly.c000066400000000000000000000043131414523752600225400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #include "fmpz_mod_poly.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_fmpz_poly... "); fflush(stdout); /* 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_randtest(ctx, state); fq_nmod_init(r, ctx); fq_nmod_init(s, ctx); fq_nmod_poly_init(a, ctx); fmpz_mod_ctx_init(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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_nmod_poly/test/t-set_nmod_poly.c000066400000000000000000000010441414523752600216600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-set_trunc.c000066400000000000000000000010361414523752600210140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-shift_left_right.c000066400000000000000000000010451414523752600223320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-sqr.c000066400000000000000000000010301414523752600176050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-sqr_KS.c000066400000000000000000000010331414523752600202050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-sqr_classical.c000066400000000000000000000010421414523752600216260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-sub.c000066400000000000000000000010301414523752600175710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-sub_series.c000066400000000000000000000010371414523752600211520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/test/t-xgcd_euclidean.c000066400000000000000000000010431414523752600217420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/test/t-xgcd_euclidean_f.c000066400000000000000000000010451414523752600222510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_poly/tree.c000066400000000000000000000010221414523752600165200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/tree.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/truncate.c000066400000000000000000000010261414523752600174120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/truncate.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/xgcd_euclidean.c000066400000000000000000000010341414523752600205220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/xgcd_euclidean.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly/xgcd_euclidean_f.c000066400000000000000000000010361414523752600210310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_templates/xgcd_euclidean_f.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor.h000066400000000000000000000025661414523752600171420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #define FQ_NMOD_POLY_FACTOR_INLINE FLINT_DLL #else #define FQ_POLY_FACTOR_TEMPLATES_INLINE static __inline__ #define FQ_NMOD_POLY_FACTOR_INLINE static __inline__ #endif FQ_NMOD_POLY_FACTOR_INLINE 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; } #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 *******************************************************************/ FLINT_DLL 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 flint2-2.8.4/fq_nmod_poly_factor/000077500000000000000000000000001414523752600167605ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_poly_factor/clear.c000066400000000000000000000010321414523752600202060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/concat.c000066400000000000000000000010331414523752600203700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/concat.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/factor.c000066400000000000000000000010331414523752600203770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/factor.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/factor_berlekamp.c000066400000000000000000000010451414523752600224240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/factor_berlekamp.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/factor_cantor_zassenhaus.c000066400000000000000000000010551414523752600242150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/factor_cantor_zassenhaus.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/factor_distinct_deg.c000066400000000000000000000010501414523752600231160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/factor_distinct_deg.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/factor_equal_deg.c000066400000000000000000000010451414523752600224100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/factor_equal_deg.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/factor_equal_deg_prob.c000066400000000000000000000010521414523752600234300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/factor_equal_deg_prob.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/factor_kaltofen_shoup.c000066400000000000000000000010521414523752600235010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/factor_kaltofen_shoup.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/factor_split_single.c000066400000000000000000000010551414523752600231570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/factor_split_single.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/factor_squarefree.c000066400000000000000000000010461414523752600226250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/factor_squarefree.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/fit_length.c000066400000000000000000000010371414523752600212500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/fit_length.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/init.c000066400000000000000000000010311414523752600200620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/init.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/inlines.c000066400000000000000000000014671414523752600205750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_POLY_FACTOR_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #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); } flint2-2.8.4/fq_nmod_poly_factor/insert.c000066400000000000000000000010331414523752600204250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/insert.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/is_irreducible.c000066400000000000000000000010431414523752600221060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/is_irreducible.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/is_irreducible_ben_or.c000066400000000000000000000010521414523752600234320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/is_irreducible_ben_or.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/is_irreducible_ddf.c000066400000000000000000000010471414523752600227270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/is_irreducible_ddf.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/is_squarefree.c000066400000000000000000000010421414523752600217560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/is_squarefree.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/iterated_frobenius_preinv.c000066400000000000000000000010561414523752600243660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/iterated_frobenius_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/pow.c000066400000000000000000000010301414523752600177230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/pow.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/print.c000066400000000000000000000010321414523752600202540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/print.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/print_pretty.c000066400000000000000000000010411414523752600216630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/print_pretty.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/profile/000077500000000000000000000000001414523752600204205ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_poly_factor/profile/p-roots.c000066400000000000000000000041361414523752600221730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz.h" #include "fq_nmod_poly.h" #include "profiler.h" int main(int argc, char *argv[]) { slong i; { fmpz_t 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); fmpz_init_set_ui(p, UWORD(1) << (FLINT_BITS - 2)); fmpz_nextprime(p, p, 1); fq_nmod_ctx_init(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); fmpz_clear(p); flint_randclear(randstate); } flint_cleanup_master(); return 0; } flint2-2.8.4/fq_nmod_poly_factor/realloc.c000066400000000000000000000010341414523752600205430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/realloc.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/roots.c000066400000000000000000000010351414523752600202710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/roots.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/set.c000066400000000000000000000010301414523752600177110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_poly_factor_templates/set.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_poly_factor/test/000077500000000000000000000000001414523752600177375ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_poly_factor/test/t-factor.c000066400000000000000000000010421414523752600216170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-factor_berlekamp.c000066400000000000000000000010541414523752600236440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-factor_cantor_zassenhaus.c000066400000000000000000000010641414523752600254350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-factor_distinct_deg.c000066400000000000000000000010571414523752600243450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-factor_equal_deg_prob.c000066400000000000000000000010611414523752600246500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-factor_kaltofen_shoup.c000066400000000000000000000010611414523752600247210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-factor_split_single.c000066400000000000000000000010641414523752600243770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-factor_squarefree.c000066400000000000000000000010551414523752600240450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-is_irreducible.c000066400000000000000000000010521414523752600233260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-is_irreducible_ben_or.c000066400000000000000000000010611414523752600246520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-is_irreducible_ddf.c000066400000000000000000000010561414523752600241470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-is_squarefree.c000066400000000000000000000010511414523752600231760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-iterated_frobenius_preinv.c000066400000000000000000000010651414523752600256060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_poly_factor/test/t-roots.c000066400000000000000000000010441414523752600215110ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_poly.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 flint2-2.8.4/fq_nmod_vec.h000066400000000000000000000027441414523752600153740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #define FQ_NMOD_VEC_INLINE FLINT_DLL #else #define FQ_VEC_TEMPLATES_INLINE static __inline__ #define FQ_NMOD_VEC_INLINE static __inline__ #endif #include "fq_nmod.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 flint2-2.8.4/fq_nmod_vec/000077500000000000000000000000001414523752600152145ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_vec/add.c000066400000000000000000000010171414523752600161070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/clear.c000066400000000000000000000010211414523752600164400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/dot.c000066400000000000000000000016111414523752600161450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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, ctx->p); 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); } flint2-2.8.4/fq_nmod_vec/equal.c000066400000000000000000000010211414523752600164610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/equal.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/fprint.c000066400000000000000000000010221414523752600166550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/fprint.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/init.c000066400000000000000000000010201414523752600163140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/init.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/inlines.c000066400000000000000000000010661414523752600170240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_NMOD_VEC_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "fq_nmod_vec.h" flint2-2.8.4/fq_nmod_vec/is_zero.c000066400000000000000000000010231414523752600170260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/is_zero.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/neg.c000066400000000000000000000010171414523752600161300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/neg.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/randtest.c000066400000000000000000000010241414523752600172010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/randtest.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/scalar_addmul_fq.c000066400000000000000000000010341414523752600206370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/scalar_addmul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/scalar_mul_fq.c000066400000000000000000000010311414523752600201630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/scalar_mul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/scalar_submul_fq.c000066400000000000000000000010341414523752600207000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/scalar_submul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/set.c000066400000000000000000000010171414523752600161520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/set.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/sub.c000066400000000000000000000010171414523752600161500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/sub.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/swap.c000066400000000000000000000010201414523752600163230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/swap.c" #undef CAP_T #undef T flint2-2.8.4/fq_nmod_vec/test/000077500000000000000000000000001414523752600161735ustar00rootroot00000000000000flint2-2.8.4/fq_nmod_vec/test/t-add.c000066400000000000000000000010261414523752600173270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_vec/test/t-is_zero.c000066400000000000000000000010321414523752600202460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_vec/test/t-neg.c000066400000000000000000000010261414523752600173500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_vec/test/t-sub.c000066400000000000000000000010261414523752600173700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_vec/test/t-swap.c000066400000000000000000000010271414523752600175520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_vec/test/t-zero.c000066400000000000000000000010271414523752600175570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_nmod_vec/zero.c000066400000000000000000000010201414523752600163300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_vec.h" #ifdef T #undef T #endif #define T fq_nmod #define CAP_T FQ_NMOD #include "fq_vec_templates/zero.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly.h000066400000000000000000000022761414523752600145650ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #define FQ_POLY_TEMPLATES_INLINE FLINT_DLL #else #define FQ_POLY_INLINE static __inline__ #define FQ_POLY_TEMPLATES_INLINE static __inline__ #endif #include "fq.h" #include "fq_mat.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 #include "fq_poly_factor.h" #endif flint2-2.8.4/fq_poly/000077500000000000000000000000001414523752600144055ustar00rootroot00000000000000flint2-2.8.4/fq_poly/add.c000066400000000000000000000010561414523752600153030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/add.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/add_series.c000066400000000000000000000010651414523752600166550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/add_series.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/add_si.c000066400000000000000000000010121414523752600157660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/add_si.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/clear.c000066400000000000000000000011241414523752600156350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/compose.c000066400000000000000000000010621414523752600162150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/compose.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/compose_divconquer.c000066400000000000000000000010751414523752600204600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/compose_divconquer.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/compose_horner.c000066400000000000000000000010711414523752600175720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/compose_horner.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/compose_mod.c000066400000000000000000000010141414523752600170510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/compose_mod.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/compose_mod_brent_kung.c000066400000000000000000000010531414523752600212720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/compose_mod_brent_kung.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000010441414523752600244020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/compose_mod_brent_kung_precomp_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/compose_mod_brent_kung_preinv.c000066400000000000000000000010621414523752600226550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/compose_mod_brent_kung_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/compose_mod_horner.c000066400000000000000000000010231414523752600204260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/compose_mod_horner.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/compose_mod_horner_preinv.c000066400000000000000000000010321414523752600220110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/compose_mod_horner_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/compose_mod_preinv.c000066400000000000000000000010231414523752600204340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/compose_mod_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/deflate.c000066400000000000000000000011251414523752600161540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/deflate.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/deflation.c000066400000000000000000000011271414523752600165170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/deflation.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/derivative.c000066400000000000000000000010651414523752600167150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/derivative.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/div_basecase.c000066400000000000000000000011471414523752600171640ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2008, 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/div_basecase.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/div_newton_n_preinv.c000066400000000000000000000012041414523752600206220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/div_newton_n_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/div_series.c000066400000000000000000000010731414523752600167060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/div_series.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/divides.c000066400000000000000000000010621414523752600161770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/divides.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/divrem_basecase.c000066400000000000000000000010721414523752600176650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/divrem_basecase.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/divrem_divconquer.c000066400000000000000000000010221414523752600202710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/divrem_divconquer.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/divrem_divconquer_recursive.c000066400000000000000000000010341414523752600223630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/divrem_divconquer_recursive.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/divrem_f.c000066400000000000000000000010071414523752600163420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/divrem_f.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/divrem_newton_n_preinv.c000066400000000000000000000011351414523752600213310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/divrem_newton_n_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/equal.c000066400000000000000000000011241414523752600156560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/equal.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/equal_trunc.c000066400000000000000000000011321414523752600170700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/equal_trunc.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/evaluate_fq.c000066400000000000000000000010661414523752600170500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/evaluate_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/evaluate_fq_vec.c000066400000000000000000000011331414523752600177000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/evaluate_fq_vec.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/evaluate_fq_vec_fast.c000066400000000000000000000011401414523752600207130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/evaluate_fq_vec_fast.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/evaluate_fq_vec_iter.c000066400000000000000000000011401414523752600207210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/evaluate_fq_vec_iter.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/fit_length.c000066400000000000000000000011311414523752600166700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/fit_length.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/fprint.c000066400000000000000000000010071414523752600160510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/fprint.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/fprint_pretty.c000066400000000000000000000010701414523752600174600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/fprint_pretty.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/gcd.c000066400000000000000000000010021414523752600152770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/gcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/gcd_euclidean.c000066400000000000000000000011261414523752600173170ustar00rootroot00000000000000/* Copyright (C) 2011 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/gcd_euclidean.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/gcd_euclidean_f.c000066400000000000000000000010161414523752600176220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/gcd_euclidean_f.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/gcd_hgcd.c000066400000000000000000000010071414523752600162710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/gcd_hgcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/gen.c000066400000000000000000000010041414523752600153150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/gen.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/get_coeff.c000066400000000000000000000012021414523752600164650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/get_coeff.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/get_str.c000066400000000000000000000010071414523752600162160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/get_str.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/get_str_pretty.c000066400000000000000000000010161414523752600176250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/get_str_pretty.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/hamming_weight.c000066400000000000000000000010711414523752600175370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/hamming_weight.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/hgcd.c000066400000000000000000000010031414523752600154500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/hgcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/inflate.c000066400000000000000000000011251414523752600161720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/inflate.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/init.c000066400000000000000000000011231414523752600155110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/init.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/inlines.c000066400000000000000000000011011414523752600162030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_POLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "fq_poly.h" flint2-2.8.4/fq_poly/inv_series_newton.c000066400000000000000000000011021414523752600203030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/inv_series_newton.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/make_monic.c000066400000000000000000000011711414523752600166530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/make_monic.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/mul.c000066400000000000000000000011371414523752600153500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define USE_MUL_REORDER 1 #define T fq #define CAP_T FQ #include "fq_poly_templates/mul.c" #undef CAP_T #undef T #undef USE_MUL_REORDER flint2-2.8.4/fq_poly/mul_KS.c000066400000000000000000000011411414523752600157400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/mul_KS.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/mul_classical.c000066400000000000000000000044741414523752600173750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_poly/mul_reorder.c000066400000000000000000000010661414523752600170730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/mul_reorder.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/mul_univariate.c000066400000000000000000000066041414523752600176030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_poly/mulhigh.c000066400000000000000000000010061414523752600162030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/mulhigh.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/mulhigh_classical.c000066400000000000000000000010201414523752600202150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/mulhigh_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/mullow.c000066400000000000000000000011411414523752600160650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/mullow.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/mullow_KS.c000066400000000000000000000011441414523752600164650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/mullow_KS.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/mullow_classical.c000066400000000000000000000011451414523752600201070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/mullow_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/mullow_univariate.c000066400000000000000000000060311414523752600203170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_poly/mulmod.c000066400000000000000000000010071414523752600160440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/mulmod.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/mulmod_preinv.c000066400000000000000000000011311414523752600174250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/mulmod_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/neg.c000066400000000000000000000010561414523752600153240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/neg.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/normalise.c000066400000000000000000000011301414523752600165350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/normalise.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/one.c000066400000000000000000000010501414523752600153260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/one.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/pow.c000066400000000000000000000010641414523752600153570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/pow.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/pow_trunc.c000066400000000000000000000010721414523752600165710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/pow_trunc.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/pow_trunc_binexp.c000066400000000000000000000011011414523752600201270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/pow_trunc_binexp.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/powmod_fmpz_binexp.c000066400000000000000000000010231414523752600204530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/powmod_fmpz_binexp.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/powmod_fmpz_binexp_preinv.c000066400000000000000000000010321414523752600220360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/powmod_fmpz_binexp_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/powmod_fmpz_sliding_preinv.c000066400000000000000000000010311414523752600222010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/powmod_fmpz_sliding_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/powmod_ui_binexp.c000066400000000000000000000010211414523752600201120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/powmod_ui_binexp.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/powmod_ui_binexp_preinv.c000066400000000000000000000010301414523752600214750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/powmod_ui_binexp_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/powmod_x_fmpz_preinv.c000066400000000000000000000010231414523752600210200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/powmod_x_fmpz_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/profile/000077500000000000000000000000001414523752600160455ustar00rootroot00000000000000flint2-2.8.4/fq_poly/profile/p-compose_mod.c000066400000000000000000000047421414523752600207610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.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; } flint2-2.8.4/fq_poly/profile/p-compose_mod_preinv.c000066400000000000000000000052301414523752600223350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.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; } flint2-2.8.4/fq_poly/profile/p-factor_xnpxp1.c000066400000000000000000000010261414523752600212410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly/profile/p-gcd.c000066400000000000000000000010141414523752600171770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/profile/p-gcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/profile/p-is_irreducible.c000066400000000000000000000010271414523752600214320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly/profile/p-iterated_frobenius.c000066400000000000000000000010331414523752600223200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/profile/p-iterated_frobenius_table.c000066400000000000000000000010411414523752600234660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/profile/p-mul_univariate.c000066400000000000000000000040501414523752600214710ustar00rootroot00000000000000#include "flint.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; } flint2-2.8.4/fq_poly/profile/p-mulmod.c000066400000000000000000000076011414523752600177470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "flint.h" #include "ulong_extras.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_randtest(ctx, state); 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; } flint2-2.8.4/fq_poly/randtest.c000066400000000000000000000011211414523752600163700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/randtest.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/randtest_irreducible.c000066400000000000000000000010251414523752600207440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/randtest_irreducible.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/randtest_monic.c000066400000000000000000000011271414523752600175630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/randtest_monic.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/realloc.c000066400000000000000000000011261414523752600161720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/realloc.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/remove.c000066400000000000000000000012651414523752600160520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/remove.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/reverse.c000066400000000000000000000010101414523752600162140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/reverse.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/scalar_addmul_fq.c000066400000000000000000000011451414523752600200330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/scalar_addmul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/scalar_div_fq.c000066400000000000000000000011421414523752600173440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/scalar_div_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/scalar_mul_fq.c000066400000000000000000000011421414523752600173570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/scalar_mul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/scalar_submul_fq.c000066400000000000000000000011451414523752600200740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/scalar_submul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/set.c000066400000000000000000000011741414523752600153470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/set.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/set_coeff.c000066400000000000000000000011301414523752600165010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/set_coeff.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/set_fmpz_mod_poly.c000066400000000000000000000010221414523752600202750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/set_fmpz_mod_poly.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/set_fq.c000066400000000000000000000010531414523752600160310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/set_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/set_nmod_poly.c000066400000000000000000000010161414523752600174220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/set_nmod_poly.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/set_trunc.c000066400000000000000000000011301414523752600165520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/set_trunc.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/shift_left.c000066400000000000000000000011451414523752600167010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/shift_left.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/shift_right.c000066400000000000000000000011461414523752600170650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/shift_right.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/sqr.c000066400000000000000000000011371414523752600153600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define USE_SQR_REORDER 1 #define T fq #define CAP_T FQ #include "fq_poly_templates/sqr.c" #undef CAP_T #undef T #undef USE_SQR_REORDER flint2-2.8.4/fq_poly/sqr_KS.c000066400000000000000000000011411414523752600157500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/sqr_KS.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/sqr_classical.c000066400000000000000000000010701414523752600173720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/sqr_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/sqr_reorder.c000066400000000000000000000010661414523752600171030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/sqr_reorder.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/sub.c000066400000000000000000000010561414523752600153440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/sub.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/sub_series.c000066400000000000000000000010651414523752600167160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/sub_series.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/swap.c000066400000000000000000000011311414523752600155170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/swap.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/test/000077500000000000000000000000001414523752600153645ustar00rootroot00000000000000flint2-2.8.4/fq_poly/test/t-add.c000066400000000000000000000011321414523752600165160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-add_series.c000066400000000000000000000011411414523752600200700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-compose.c000066400000000000000000000010721414523752600174360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-compose_divconquer.c000066400000000000000000000011051414523752600216720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-compose_divconquer.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/test/t-compose_horner.c000066400000000000000000000011011414523752600210040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-compose_horner.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/test/t-compose_mod.c000066400000000000000000000010231414523752600202710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-compose_mod_brent_kung.c000066400000000000000000000010361414523752600225130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-compose_mod_brent_kung_preinv.c000066400000000000000000000010451414523752600240760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-compose_mod_horner.c000066400000000000000000000010321414523752600216460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-compose_mod_horner_preinv.c000066400000000000000000000010411414523752600232310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-compose_mod_preinv.c000066400000000000000000000010321414523752600216540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-deflate.c000066400000000000000000000010701414523752600173730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-derivative.c000066400000000000000000000010751414523752600201360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-div_basecase.c000066400000000000000000000011421414523752600203770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-div_basecase.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/test/t-div_newton_n_preinv.c000066400000000000000000000011411414523752600220420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-div_series.c000066400000000000000000000011361414523752600201260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-divides.c000066400000000000000000000010721414523752600174200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-divrem_basecase.c000066400000000000000000000011021414523752600210770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-divrem_basecase.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/test/t-divrem_divconquer.c000066400000000000000000000010311414523752600215110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-divrem_divconquer.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/test/t-divrem_newton_n_preinv.c000066400000000000000000000011441414523752600225510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-equal_trunc.c000066400000000000000000000010761414523752600203170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-evaluate_fq.c000066400000000000000000000010761414523752600202710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-evaluate_fq_vec_fast.c000066400000000000000000000011631414523752600221400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-gcd.c000066400000000000000000000010111414523752600165170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-gcd_euclidean.c000066400000000000000000000011351414523752600205370ustar00rootroot00000000000000/* Copyright (C) 2011 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-gcd_euclidean.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/test/t-gcd_euclidean_f.c000066400000000000000000000010251414523752600210420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-gcd_hgcd.c000066400000000000000000000010161414523752600175110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-gcd_hgcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/test/t-get_str.c000066400000000000000000000010171414523752600174370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-get_str_pretty.c000066400000000000000000000010261414523752600210460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-hamming_weight.c000066400000000000000000000011451414523752600207610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-hgcd.c000066400000000000000000000010121414523752600166700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-hgcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/test/t-inflate.c000066400000000000000000000010701414523752600174110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-inv_series_newton.c000066400000000000000000000011471414523752600215340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-make_monic.c000066400000000000000000000011321414523752600200700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mul.c000066400000000000000000000011321414523752600165630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mul_KS.c000066400000000000000000000011351414523752600171630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mul_classical.c000066400000000000000000000011441414523752600206040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mul_reorder.c000066400000000000000000000011421414523752600203060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mul_univariate.c000066400000000000000000000011451414523752600210160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mulhigh.c000066400000000000000000000010151414523752600174230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mulhigh_classical.c000066400000000000000000000010271414523752600214440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mullow.c000066400000000000000000000010711414523752600173070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mullow_KS.c000066400000000000000000000010741414523752600177070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mullow_classical.c000066400000000000000000000011031414523752600213210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mullow_univariate.c000066400000000000000000000011041414523752600215330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mulmod.c000066400000000000000000000010161414523752600172640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-mulmod_preinv.c000066400000000000000000000012041414523752600206460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-neg.c000066400000000000000000000011321414523752600165370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-pow.c000066400000000000000000000011321414523752600165730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-pow_trunc.c000066400000000000000000000011401414523752600200050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-pow_trunc_binexp.c000066400000000000000000000011471414523752600213610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-powmod_fmpz_binexp.c000066400000000000000000000010321414523752600216730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-powmod_fmpz_binexp_preinv.c000066400000000000000000000010411414523752600232560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-powmod_fmpz_sliding_preinv.c000066400000000000000000000010401414523752600234210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-powmod_ui_binexp.c000066400000000000000000000010301414523752600213320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-powmod_ui_binexp_preinv.c000066400000000000000000000010371414523752600227240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-powmod_x_fmpz_preinv.c000066400000000000000000000010321414523752600222400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-randtest_irreducible.c000066400000000000000000000010321414523752600221620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly/test/t-scalar_addmul_fq.c000066400000000000000000000011031414523752600212450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-scalar_div_fq.c000066400000000000000000000011001414523752600205560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-scalar_mul_fq.c000066400000000000000000000011001414523752600205710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-scalar_submul_fq.c000066400000000000000000000011031414523752600213060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-set_fmpz_mod_poly.c000066400000000000000000000037761414523752600215370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_fmpz_poly... "); fflush(stdout); /* 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_randtest(ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_poly/test/t-set_nmod_poly.c000066400000000000000000000010251414523752600206420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-set_trunc.c000066400000000000000000000010741414523752600200010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-shift_left_right.c000066400000000000000000000011471414523752600213200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-sqr.c000066400000000000000000000011321414523752600165730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-sqr_KS.c000066400000000000000000000011351414523752600171730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-sqr_classical.c000066400000000000000000000011441414523752600206140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-sqr_reorder.c000066400000000000000000000011421414523752600203160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-sub.c000066400000000000000000000011321414523752600165570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-sub_series.c000066400000000000000000000011411414523752600201310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-xgcd_euclidean.c000066400000000000000000000010241414523752600207240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/test/t-xgcd_euclidean.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/test/t-xgcd_euclidean_f.c000066400000000000000000000010261414523752600212330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_poly/test/t-xgcd_euclidean_f_composite_characteristic.c000066400000000000000000000061741414523752600263760ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("xgcd_euclidean_f_composite_characteristic...."); fflush(stdout); for (i = 0; i < 10*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 < 999; 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_poly/tree.c000066400000000000000000000010031414523752600155020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/tree.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/truncate.c000066400000000000000000000011271414523752600163770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/truncate.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/xgcd_euclidean.c000066400000000000000000000010151414523752600175040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/xgcd_euclidean.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly/xgcd_euclidean_f.c000066400000000000000000000010171414523752600200130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_templates/xgcd_euclidean_f.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor.h000066400000000000000000000024431414523752600161170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #define FQ_POLY_FACTOR_INLINE FLINT_DLL #else #define FQ_POLY_FACTOR_TEMPLATES_INLINE static __inline__ #define FQ_POLY_FACTOR_INLINE static __inline__ #endif FQ_POLY_FACTOR_INLINE 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; } #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates.h" #undef CAP_T #undef T /* Inlines *******************************************************************/ FLINT_DLL void fq_poly_factor_get_poly(fq_poly_t z, const fq_poly_factor_t fac, slong i, const fq_ctx_t ctx); #endif flint2-2.8.4/fq_poly_factor/000077500000000000000000000000001414523752600157435ustar00rootroot00000000000000flint2-2.8.4/fq_poly_factor/clear.c000066400000000000000000000010151414523752600171720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/concat.c000066400000000000000000000010161414523752600173540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/concat.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/factor.c000066400000000000000000000012741414523752600173710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/factor.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/factor_berlekamp.c000066400000000000000000000010531414523752600214060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #include "fq_mat.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/factor_berlekamp.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/factor_cantor_zassenhaus.c000066400000000000000000000010401414523752600231720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/factor_cantor_zassenhaus.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/factor_distinct_deg.c000066400000000000000000000010321414523752600221010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/factor_distinct_deg.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/factor_equal_deg.c000066400000000000000000000010271414523752600213730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/factor_equal_deg.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/factor_equal_deg_prob.c000066400000000000000000000010351414523752600224140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/factor_equal_deg_prob.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/factor_kaltofen_shoup.c000066400000000000000000000010341414523752600224640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/factor_kaltofen_shoup.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/factor_split_single.c000066400000000000000000000010361414523752600221410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/factor_split_single.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/factor_squarefree.c000066400000000000000000000010301414523752600216010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/factor_squarefree.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/fit_length.c000066400000000000000000000010221414523752600202250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/fit_length.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/init.c000066400000000000000000000010141414523752600170460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/init.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/inlines.c000066400000000000000000000012741414523752600175540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #undef ulong #include #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); } flint2-2.8.4/fq_poly_factor/insert.c000066400000000000000000000010161414523752600174110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/insert.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/is_irreducible.c000066400000000000000000000010261414523752600210720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/is_irreducible.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/is_irreducible_ben_or.c000066400000000000000000000010331414523752600224140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/is_irreducible_ben_or.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/is_irreducible_ddf.c000066400000000000000000000010321414523752600217040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/is_irreducible_ddf.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/is_squarefree.c000066400000000000000000000010251414523752600207420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/is_squarefree.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/iterated_frobenius_preinv.c000066400000000000000000000010371414523752600233500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/iterated_frobenius_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/pow.c000066400000000000000000000010131414523752600167070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/pow.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/print.c000066400000000000000000000010151414523752600172400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/print.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/print_pretty.c000066400000000000000000000010241414523752600206470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/print_pretty.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/realloc.c000066400000000000000000000010171414523752600175270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/realloc.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/roots.c000066400000000000000000000010201414523752600172460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/roots.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/set.c000066400000000000000000000010131414523752600166750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_poly_factor_templates/set.c" #undef CAP_T #undef T flint2-2.8.4/fq_poly_factor/test/000077500000000000000000000000001414523752600167225ustar00rootroot00000000000000flint2-2.8.4/fq_poly_factor/test/t-factor.c000066400000000000000000000013031414523752600206020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-factor_berlekamp.c000066400000000000000000000010371414523752600226300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-factor_cantor_zassenhaus.c000066400000000000000000000010471414523752600244210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-factor_distinct_deg.c000066400000000000000000000010421414523752600233220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-factor_equal_deg_prob.c000066400000000000000000000010441414523752600236340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-factor_kaltofen_shoup.c000066400000000000000000000010441414523752600237050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-factor_split_single.c000066400000000000000000000010451414523752600233610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-factor_squarefree.c000066400000000000000000000010401414523752600230220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-is_irreducible.c000066400000000000000000000010351414523752600223120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-is_irreducible_ben_or.c000066400000000000000000000010421414523752600236340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-is_irreducible_ddf.c000066400000000000000000000010411414523752600231240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-is_squarefree.c000066400000000000000000000010341414523752600221620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-iterated_frobenius_preinv.c000066400000000000000000000010461414523752600245700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor/test/t-roots.c000066400000000000000000000010271414523752600204750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_poly.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 flint2-2.8.4/fq_poly_factor_templates.h000066400000000000000000000155601414523752600202010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef __cplusplus extern "C" { #endif /* Type definitions *********************************************************/ typedef struct { TEMPLATE(T, poly_struct) *poly; slong *exp; slong num; slong alloc; } TEMPLATE(T, poly_factor_struct); typedef TEMPLATE(T, poly_factor_struct) TEMPLATE(T, poly_factor_t)[1]; FLINT_DLL void TEMPLATE(T, poly_factor_init)(TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_factor_clear)(TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_factor_realloc)(TEMPLATE(T, poly_factor_t) fac, slong alloc, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_factor_fit_length)(TEMPLATE(T, poly_factor_t) fac, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void TEMPLATE(T, poly_factor_print)(const TEMPLATE(T, poly_factor_t) fac, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_factor_print_pretty)(const TEMPLATE(T, poly_factor_t) fac, const char * var, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL void TEMPLATE(T, poly_factor_pow)(TEMPLATE(T, poly_factor_t) fac, slong exp, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int _TEMPLATE(T, poly_is_squarefree)(const TEMPLATE(T, struct) * f, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int TEMPLATE(T, poly_is_squarefree)(const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_factor_squarefree)(TEMPLATE(T, poly_factor_t) res, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int TEMPLATE(T, poly_is_irreducible)(const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int TEMPLATE(T, poly_is_irreducible_ddf)(const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int TEMPLATE(T, poly_is_irreducible_ben_or)(const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void TEMPLATE(T, poly_factor_berlekamp)(TEMPLATE(T, poly_factor_t) factors, const TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void TEMPLATE(T, poly_factor_split_single)(TEMPLATE(T, poly_t) linfactor, const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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 flint2-2.8.4/fq_poly_factor_templates/000077500000000000000000000000001414523752600200215ustar00rootroot00000000000000flint2-2.8.4/fq_poly_factor_templates/clear.c000066400000000000000000000016761414523752600212650ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_factor_templates/concat.c000066400000000000000000000017171414523752600214420ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_factor_templates/factor.c000066400000000000000000000161131414523752600214450ustar00rootroot00000000000000/* 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 2.1 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) { flint_bitcnt_t bits = fmpz_bits(TEMPLATE(T, ctx_prime) (ctx)); slong n = TEMPLATE(T, poly_degree) (input, ctx); 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 flint2-2.8.4/fq_poly_factor_templates/factor_berlekamp.c000066400000000000000000000223711414523752600234720ustar00rootroot00000000000000/* 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 2.1 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 p, 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_set(p, TEMPLATE(T, ctx_prime) (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 (fmpz_cmp_ui(p, 3) > 0) { 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, 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 (fmpz_cmp_ui(p, 3) > 0) 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(p); 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 flint2-2.8.4/fq_poly_factor_templates/factor_cantor_zassenhaus.c000066400000000000000000000041101414523752600252510ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_factor_templates/factor_distinct_deg.c000066400000000000000000000143361414523752600241720ustar00rootroot00000000000000/* 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 2.1 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); if (! (h = flint_malloc((2 * m + l + 1) * sizeof(TEMPLATE(T, poly_struct))))) { TEMPLATE_PRINTF("Exception (%s_poly_factor_distinct_deg):\n", T); flint_printf("Not enough memory.\n"); flint_abort(); } 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 flint2-2.8.4/fq_poly_factor_templates/factor_equal_deg.c000066400000000000000000000032361414523752600234550ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_factor_templates/factor_equal_deg_prob.c000066400000000000000000000065671414523752600245110ustar00rootroot00000000000000/* 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 2.1 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) { TEMPLATE_PRINTF("Exception (%s_poly_factor_equal_deg_prob): \n", T); flint_printf("Input polynomial is linear.\n"); flint_abort(); } 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 (fmpz_cmp_ui(TEMPLATE(T, ctx_prime) (ctx), 2) > 0) { /* 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 flint2-2.8.4/fq_poly_factor_templates/factor_kaltofen_shoup.c000066400000000000000000000043401414523752600245450ustar00rootroot00000000000000/* 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 2.1 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; if (! (degs = flint_malloc(TEMPLATE(T, poly_degree) (poly, ctx) * sizeof(slong)))) { TEMPLATE_PRINTF("Exception (%s_poly_factor_kaltofen_shoup): \n", T); flint_printf("Not enough memory.\n"); flint_abort(); } 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 flint2-2.8.4/fq_poly_factor_templates/factor_split_single.c000066400000000000000000000044331414523752600242230ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_factor_templates/factor_squarefree.c000066400000000000000000000115151414523752600236700ustar00rootroot00000000000000/* 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 2.1 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; fmpz_t p; 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); return; } fmpz_init(p); fmpz_set(p, TEMPLATE(T, ctx_prime) (ctx)); 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 */ p_ui = fmpz_get_ui(p); 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); p_ui = fmpz_get_ui(p); 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); } } fmpz_clear(p); 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 flint2-2.8.4/fq_poly_factor_templates/fit_length.c000066400000000000000000000016301414523752600223100ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_factor_templates/init.c000066400000000000000000000020011414523752600211210ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_factor_templates/insert.c000066400000000000000000000031231414523752600214700ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_factor_templates/is_irreducible.c000066400000000000000000000016101414523752600231470ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_factor_templates/is_irreducible_ben_or.c000066400000000000000000000052371414523752600245040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); fmpz_pow_ui(q, TEMPLATE(T, ctx_prime) (ctx), TEMPLATE(T, ctx_degree) (ctx)); 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 flint2-2.8.4/fq_poly_factor_templates/is_irreducible_ddf.c000066400000000000000000000032071414523752600237700ustar00rootroot00000000000000/* 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 2.1 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; if (!(degs = (slong *) flint_malloc(n * sizeof(slong)))) { TEMPLATE_PRINTF("Exception (%s_poly_is_irreducible_ddf): \n", T); flint_printf("Not enough memory.\n"); flint_abort(); } 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 flint2-2.8.4/fq_poly_factor_templates/is_squarefree.c000066400000000000000000000031031414523752600230170ustar00rootroot00000000000000/* 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 2.1 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; TEMPLATE(T, t) invfd; 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) { TEMPLATE(T, init) (invfd, ctx); TEMPLATE(T, inv) (invfd, fd + (dlen - 1), ctx); res = (_TEMPLATE(T, poly_gcd) (g, f, len, fd, dlen, invfd, ctx) == 1); TEMPLATE(T, clear) (invfd, ctx); } 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 flint2-2.8.4/fq_poly_factor_templates/iterated_frobenius_preinv.c000066400000000000000000000034131414523752600254260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_poly_factor_templates/pow.c000066400000000000000000000015241414523752600207740ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_factor_templates/print.c000066400000000000000000000016731414523752600213300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include 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 flint2-2.8.4/fq_poly_factor_templates/print_pretty.c000066400000000000000000000014721414523752600227340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include 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 flint2-2.8.4/fq_poly_factor_templates/realloc.c000066400000000000000000000042651414523752600216150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #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 flint2-2.8.4/fq_poly_factor_templates/roots.c000066400000000000000000000214701414523752600213370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)) { FLINT_ASSERT(fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) > 0); 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 */ FLINT_ASSERT(fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) == 0); 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_basecase)(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)) { FLINT_ASSERT(fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) > 0); 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 { FLINT_ASSERT(fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) == 0); 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 flint2-2.8.4/fq_poly_factor_templates/set.c000066400000000000000000000025631414523752600207660ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_factor_templates/test/000077500000000000000000000000001414523752600210005ustar00rootroot00000000000000flint2-2.8.4/fq_poly_factor_templates/test/t-factor.c000066400000000000000000000207561414523752600226750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor...."); fflush(stdout); /* Default algorithm */ for (iter = 0; iter < 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], prod1; TEMPLATE(T, ctx_randtest) (ctx, state); 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; prod1 = exp[0]; 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; 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, 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 (fmpz_is_even(TEMPLATE(T, ctx_prime) (ctx))) 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); 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"); 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 < 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], prod1; ulong inflation; int found; TEMPLATE(T, ctx_randtest) (ctx, state); 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; 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, 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; prod1 *= exp[i]; 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-factor_berlekamp.c000066400000000000000000000103621414523752600247070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor_berlekamp...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-factor_cantor_zassenhaus.c000066400000000000000000000102611414523752600264750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor_cantor_zassenhaus...."); fflush(stdout); 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_randtest) (ctx, state); 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); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-factor_distinct_deg.c000066400000000000000000000077121414523752600254120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor_distinct_deg...."); fflush(stdout); for (iter = 0; iter < 20 * 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_randtest) (ctx, state); 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."); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-factor_equal_deg_prob.c000066400000000000000000000054531414523752600257220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor_equal_deg_prob...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-factor_kaltofen_shoup.c000066400000000000000000000105001414523752600257600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor_kaltofen_shoup...."); fflush(stdout); 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_randtest) (ctx, state); 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); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-factor_split_single.c000066400000000000000000000043721414523752600254450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor_split_single...."); fflush(stdout); /* Compute a random spliting 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-factor_squarefree.c000066400000000000000000000074471414523752600251210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor_squarefree...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-is_irreducible.c000066400000000000000000000046661414523752600244050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("is_irreducible...."); fflush(stdout); 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_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly2, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-is_irreducible_ben_or.c000066400000000000000000000047221414523752600257220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("is_irreducible_ben_or...."); fflush(stdout); 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_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly2, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-is_irreducible_ddf.c000066400000000000000000000047061414523752600252150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("is_irreducible_ddf...."); fflush(stdout); 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_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly2, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-is_squarefree.c000066400000000000000000000056541414523752600242540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "fmpz_vec.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("is_squarefree...."); fflush(stdout); for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) poly, Q, R, t; fmpz_t x; slong i, num_factors, exp, max_exp; int v, result; TEMPLATE(T, ctx_randtest) (ctx, state); 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); fmpz_randtest_mod(x, state, TEMPLATE(T, ctx_prime) (ctx)); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-iterated_frobenius_preinv.c000066400000000000000000000050661414523752600266540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("iterated_frobenius_preinv...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_factor_templates/test/t-roots.c000066400000000000000000000070411414523752600225550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.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"); flint_abort(); } if (!TEMPLATE(T, is_one)(roots->poly[i].coeffs + 1, ctx) != 0) { flint_printf("FAILED:\ncheck root is monic\n"); 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"); flint_abort(); } if (roots->exp[i] != (want_mult ? multiplicity : 1)) { flint_printf("FAILED:\ncheck root multiplicity\n"); flint_abort(); } } TEMPLATE(T, poly_roots)(roots, q, want_mult, ctx); if (roots->num > 0) { flint_printf("FAILED:\ncheck missing roots\n"); flint_abort(); } TEMPLATE(T, poly_clear)(q, ctx); TEMPLATE(T, poly_clear)(qt, ctx); TEMPLATE(T, poly_clear)(r, ctx); } int main(void) { slong i, j, k, l; FLINT_TEST_INIT(state); flint_printf("roots...."); fflush(stdout); for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) f; TEMPLATE(T, poly_factor_t) r; TEMPLATE(T, ctx_randtest)(ctx, state); TEMPLATE(T, poly_init)(f, ctx); TEMPLATE(T, poly_factor_init)(r, ctx); for (j = 0; j < 4; j++) { TEMPLATE(T, poly_randtest_not_zero)(f, state, n_randint(state, 20) + 1, ctx); for (k = 0; k < 5; 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates.h000066400000000000000000001600541414523752600166420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #ifdef __cplusplus extern "C" { #endif /* Type definitions *********************************************************/ typedef struct { TEMPLATE(T, struct) *coeffs; slong alloc; slong length; } TEMPLATE(T, poly_struct); typedef TEMPLATE(T, poly_struct) TEMPLATE(T, poly_t)[1]; /* Memory management ********************************************************/ FLINT_DLL void TEMPLATE(T, poly_init)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_init2)(TEMPLATE(T, poly_t) poly, slong alloc, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_realloc)(TEMPLATE(T, poly_t) poly, slong alloc, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_truncate)(TEMPLATE(T, poly_t) poly, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_set_trunc)(TEMPLATE(T, poly_t) poly1, TEMPLATE(T, poly_t) poly2, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_fit_length)(TEMPLATE(T, poly_t) poly, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_clear)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, poly_normalise)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, poly_normalise2)(const TEMPLATE(T, struct) *poly, slong *length, const TEMPLATE(T, ctx_t) ctx); FQ_POLY_TEMPLATES_INLINE 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; } /* 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 ***********************************************************/ FLINT_DLL void TEMPLATE(T, poly_randtest)(TEMPLATE(T, poly_t) f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_randtest_not_zero)(TEMPLATE(T, poly_t) f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_randtest_monic) (TEMPLATE(T, poly_t) f, flint_rand_t state, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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 ***************************************/ FLINT_DLL void _TEMPLATE(T, poly_set)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_set)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE3(T, poly_set, T)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL void TEMPLATE(T, poly_set_nmod_poly)(TEMPLATE(T, poly_t) rop, const nmod_poly_t op, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_swap)(TEMPLATE(T, poly_t) op1, TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); FQ_POLY_TEMPLATES_INLINE 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); } FQ_POLY_TEMPLATES_INLINE void TEMPLATE(T, poly_zero)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx) { _TEMPLATE(T, poly_set_length)(poly, 0, ctx); } FLINT_DLL void TEMPLATE(T, poly_one)(TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_gen)(TEMPLATE(T, poly_t) f, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, poly_make_monic)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong length, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_make_monic)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, poly_reverse)(TEMPLATE(T, struct) * res, const TEMPLATE(T, struct) * poly, slong len, slong n, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_reverse)(TEMPLATE(T, poly_t) res, const TEMPLATE(T, poly_t) poly, slong n, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL ulong TEMPLATE(T, poly_deflation)(const TEMPLATE(T, poly_t) input, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_deflate)(TEMPLATE(T, poly_t) result, const TEMPLATE(T, poly_t) input, ulong deflation, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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 ****************************************/ FLINT_DLL void TEMPLATE(T, poly_get_coeff)(TEMPLATE(T, t) x, const TEMPLATE(T, poly_t) poly, slong n, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_set_coeff)(TEMPLATE(T, poly_t) poly, slong n, const TEMPLATE(T, t) x, const TEMPLATE(T, ctx_t) ctx); FQ_POLY_TEMPLATES_INLINE 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); } FQ_POLY_TEMPLATES_INLINE 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)); } /* Comparison **************************************************************/ FLINT_DLL int TEMPLATE(T, poly_equal)(const TEMPLATE(T, poly_t) poly1, const TEMPLATE(T, poly_t) poly2, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); } FQ_POLY_TEMPLATES_INLINE 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)); } FQ_POLY_TEMPLATES_INLINE 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))); } FQ_POLY_TEMPLATES_INLINE 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)); } /* Addition and subtraction ************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _TEMPLATE(T, poly_neg)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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 **************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 **********************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ******************************************************************/ FLINT_DLL void _TEMPLATE(T, poly_sqr_classical)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_sqr_classical)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, poly_sqr_reorder)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_sqr_reorder)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, poly_sqr_KS)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_sqr_KS)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, poly_sqr)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_sqr)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); /* Powering ****************************************************************/ FLINT_DLL void _TEMPLATE(T, poly_pow)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, ulong e, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_pow)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, ulong e, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ****************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 *******************************************************************/ FLINT_DLL slong _TEMPLATE(T, poly_hamming_weight)(const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL slong TEMPLATE(T, poly_hamming_weight)(const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); /* Greatest common divisor *************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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, t) invB, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL slong _TEMPLATE(T, poly_hgcd)(TEMPLATE(T, struct) **M, slong *lenM, TEMPLATE(T, struct)* A, slong *lenA, TEMPLATE(T, struct)* B, slong *lenB, const TEMPLATE(T, struct)* a, slong lena, const TEMPLATE(T, struct)* b, slong lenb, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL slong _TEMPLATE(T, poly_gcd_hgcd)(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); FLINT_DLL void TEMPLATE(T, poly_gcd_hgcd)(TEMPLATE(T, poly_t) G, const TEMPLATE(T, poly_t) A, const TEMPLATE(T, poly_t) B, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL slong _TEMPLATE(T, poly_xgcd_euclidean)(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, t) invB, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_xgcd_euclidean)(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); FQ_POLY_TEMPLATES_INLINE 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, t) invB, const TEMPLATE(T, ctx_t) ctx) { return _TEMPLATE(T, poly_xgcd_euclidean)(G, S, T, A, lenA, B, lenB, invB, ctx); } FQ_POLY_TEMPLATES_INLINE 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) { TEMPLATE(T, poly_xgcd_euclidean)(G, S, T, A, B, ctx); } /* Euclidean division ******************************************************/ FLINT_DLL ulong TEMPLATE(T, poly_remove)(TEMPLATE(T, poly_t) f, const TEMPLATE(T, poly_t) g, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, poly_div_basecase)(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); FLINT_DLL 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); FLINT_DLL void _TEMPLATE(T, poly_divrem_basecase)(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); FLINT_DLL void TEMPLATE(T, poly_divrem_basecase)(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); FLINT_DLL void _TEMPLATE(T, poly_divrem_divconquer_recursive)( TEMPLATE(T, struct) * Q, TEMPLATE(T, struct) * BQ, TEMPLATE(T, struct) * W, const TEMPLATE(T, struct) * A, const TEMPLATE(T, struct) * B, slong lenB, const TEMPLATE(T, t) invB, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, poly_divrem_divconquer)( 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); FLINT_DLL void TEMPLATE(T, poly_divrem_divconquer)(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); FQ_POLY_TEMPLATES_INLINE 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) { _TEMPLATE(T, poly_divrem_divconquer)(Q, R, A, lenA, B, lenB, invB, ctx); } FQ_POLY_TEMPLATES_INLINE 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) { TEMPLATE(T, poly_divrem_divconquer)(Q, R, A, B, ctx); } FQ_POLY_TEMPLATES_INLINE 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_divconquer)(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); } FQ_POLY_TEMPLATES_INLINE 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); } FLINT_DLL 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); FLINT_DLL 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); } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ***************************************************/ FLINT_DLL 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); FLINT_DLL 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 **************************************************************/ FLINT_DLL void _TEMPLATE(T, poly_derivative)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_derivative)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op, const TEMPLATE(T, ctx_t) ctx); /* Evaluation **************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL TEMPLATE(T, poly_struct) ** _TEMPLATE(T, poly_tree_alloc)(slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, poly_tree_free)(TEMPLATE(T, poly_struct) ** tree, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, poly_tree_build)(TEMPLATE(T, poly_struct) ** tree, const TEMPLATE(T, struct) * roots, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 *************************************************************/ FLINT_DLL void _TEMPLATE(T, poly_compose_divconquer)( TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op1, slong len1, const TEMPLATE(T, struct) *op2, slong len2, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_compose_divconquer)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, poly_compose_horner)(TEMPLATE(T, struct) *rop, const TEMPLATE(T, struct) *op1, slong len1, const TEMPLATE(T, struct) *op2, slong len2, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, poly_compose_horner)(TEMPLATE(T, poly_t) rop, const TEMPLATE(T, poly_t) op1, const TEMPLATE(T, poly_t) op2, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ********************************************************/ FLINT_DLL int _TEMPLATE(T, poly_fprint_pretty)(FILE *file, const TEMPLATE(T, struct) *poly, slong len, const char *x, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int TEMPLATE(T, poly_fprint_pretty)(FILE * file, const TEMPLATE(T, poly_t) poly, const char *x, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int _TEMPLATE(T, poly_fprint)(FILE * file, const TEMPLATE(T, struct) *poly, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int TEMPLATE(T, poly_fprint)(FILE * file, const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); FQ_POLY_TEMPLATES_INLINE 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); } FQ_POLY_TEMPLATES_INLINE 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); } FQ_POLY_TEMPLATES_INLINE 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); } FQ_POLY_TEMPLATES_INLINE 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); } FLINT_DLL char * _TEMPLATE(T, poly_get_str_pretty)(const TEMPLATE(T, struct) * poly, slong len, const char *x, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL char * TEMPLATE(T, poly_get_str_pretty)(const TEMPLATE(T, poly_t) poly, const char *x, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL char * _TEMPLATE(T, poly_get_str)(const TEMPLATE(T, struct) * poly, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL char * TEMPLATE(T, poly_get_str)(const TEMPLATE(T, poly_t) poly, const TEMPLATE(T, ctx_t) ctx); /* Characteristic polynomial ************************************************/ FLINT_DLL void TEMPLATE(T, mat_charpoly_danilevsky) (TEMPLATE(T, poly_t) p, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); FQ_POLY_TEMPLATES_INLINE 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_printf("Exception (fq_mat_charpoly). Non-square matrix.\n"); flint_abort(); } TEMPLATE(T, mat_charpoly_danilevsky) (p, A, ctx); TEMPLATE(T, mat_clear) (A, ctx); } /* Minimal polynomial ************************************************/ FLINT_DLL 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 flint2-2.8.4/fq_poly_templates/000077500000000000000000000000001414523752600164635ustar00rootroot00000000000000flint2-2.8.4/fq_poly_templates/add.c000066400000000000000000000032121414523752600173550ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/add_series.c000066400000000000000000000023011414523752600207250ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/add_si.c000066400000000000000000000015661414523752600200620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_poly_templates/clear.c000066400000000000000000000013131414523752600177130ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/compose.c000066400000000000000000000046351414523752600203040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.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) { if (len1 == 1) TEMPLATE(T, set) (rop + 0, op1 + 0, ctx); else if (len2 == 1) _TEMPLATE(T, TEMPLATE(poly_evaluate, T)) (rop + 0, op1, len1, op2 + 0, ctx); else if (len1 <= 4) _TEMPLATE(T, poly_compose_horner) (rop, op1, len1, op2, len2, ctx); else _TEMPLATE(T, poly_compose_divconquer) (rop, op1, len1, op2, len2, 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 flint2-2.8.4/fq_poly_templates/compose_divconquer.c000066400000000000000000000132711414523752600225370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_compose_divconquer) ( TEMPLATE(T, struct) * rop, const TEMPLATE(T, struct) * op1, slong len1, const TEMPLATE(T, struct) * op2, slong len2, const TEMPLATE(T, ctx_t) ctx) { slong i, j, k, n; slong *hlen, alloc, powlen; TEMPLATE(T, struct) * v, **h, *pow, *temp; if (len1 <= 2 || len2 <= 1) { if (len1 == 1) TEMPLATE(T, set) (rop, op1, ctx); else if (len2 == 1) _TEMPLATE(T, TEMPLATE(poly_evaluate, T)) (rop, op1, len1, op2, ctx); else /* len1 == 2 */ _TEMPLATE(T, poly_compose_horner) (rop, op1, len1, op2, len2, ctx); 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 = _TEMPLATE(T, vec_init) (alloc + 2 * powlen, ctx); h = (TEMPLATE(T, struct) **) flint_malloc(((len1 + 1) / 2) * sizeof(TEMPLATE(T, struct) *)); 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 (!TEMPLATE(T, is_zero) (op1 + (j + 1), ctx)) { _TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (h[i], op2, len2, op1 + j + 1, ctx); TEMPLATE(T, add) (h[i], h[i], op1 + j, ctx); hlen[i] = len2; } else if (!TEMPLATE(T, is_zero) (op1 + j, ctx)) { TEMPLATE(T, set) (h[i], op1 + j, ctx); hlen[i] = 1; } } if ((len1 & WORD(1))) { if (!TEMPLATE(T, is_zero) (op1 + j, ctx)) { TEMPLATE(T, set) (h[i], op1 + j, ctx); hlen[i] = 1; } } _TEMPLATE(T, poly_sqr) (pow, op2, 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; _TEMPLATE(T, poly_mul) (temp, pow, powlen, h[1], hlen[1], ctx); _TEMPLATE(T, 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) { _TEMPLATE(T, 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; _TEMPLATE(T, 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))) { _TEMPLATE(T, poly_set) (h[i], h[2 * i], hlen[2 * i], ctx); hlen[i] = hlen[2 * i]; } _TEMPLATE(T, poly_sqr) (temp, pow, powlen, ctx); powlen += powlen - 1; { TEMPLATE(T, struct) * t = pow; pow = temp; temp = t; } } _TEMPLATE(T, poly_mul) (rop, pow, powlen, h[1], hlen[1], ctx); _TEMPLATE(T, poly_add) (rop, rop, hlen[0], h[0], hlen[0], ctx); _TEMPLATE(T, vec_clear) (v, alloc + 2 * powlen, ctx); flint_free(h); flint_free(hlen); } void TEMPLATE(T, poly_compose_divconquer) (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_divconquer) (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_divconquer) (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 flint2-2.8.4/fq_poly_templates/compose_horner.c000066400000000000000000000057221414523752600216570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_compose_horner) (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) { TEMPLATE(T, set) (rop, op1 + 0, ctx); } else { const slong alloc = (len1 - 1) * (len2 - 1) + 1; slong i = len1 - 1, lenr; TEMPLATE(T, struct) * t = _TEMPLATE(T, vec_init) (alloc, ctx); /* Perform the first two steps as one, "res = a(m) * poly2 + a(m-1)". */ { lenr = len2; _TEMPLATE(T, TEMPLATE(poly_scalar_mul, T)) (rop, op2, len2, op1 + i, ctx); i--; TEMPLATE(T, add) (rop + 0, rop + 0, op1 + i, ctx); } while (i--) { _TEMPLATE(T, poly_mul) (t, rop, lenr, op2, len2, ctx); lenr += len2 - 1; _TEMPLATE(T, poly_add) (rop, t, lenr, op1 + i, 1, ctx); } _TEMPLATE(T, vec_clear) (t, alloc, ctx); } } void TEMPLATE(T, poly_compose_horner) (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_horner) (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_horner) (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 flint2-2.8.4/fq_poly_templates/compose_mod.c000066400000000000000000000063241414523752600211400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #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) { TEMPLATE_PRINTF("Exception: division by zero in %s_poly_compose_mod\n", T); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/compose_mod_brent_kung.c000066400000000000000000000122421414523752600233520ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception: division by zero in"); TEMPLATE_PRINTF("%s_poly_compose_mod_brent_kung\n", T); flint_abort(); } if (len1 >= len3) { TEMPLATE_PRINTF ("Exception: %s_poly_compose_brent_kung: the degree of the", T); flint_printf (" first polynomial must be smaller than that of the modulus\n"); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000174241414523752600264710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #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_printf ("Exception (nmod_poly_compose_mod_brent_kung). Division by zero.\n"); flint_abort(); } if (A->r != m || A->c != len) { flint_printf ("Exception (nmod_poly_compose_mod_brent_kung). Wrong dimensions.\n"); flint_abort(); } 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) { TEMPLATE_PRINTF ("Exception (%s_poly_compose_mod_brent_kung). Division by zero.\n", T); flint_abort(); } if (len1 >= len3) { TEMPLATE_PRINTF ("Exception (%s_poly_compose_brent_kung). The degree of the \n", T); flint_printf ("first polynomial must be smaller than that of the modulus.\n"); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/compose_mod_brent_kung_preinv.c000066400000000000000000000130101414523752600247270ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception: division by zero in "); TEMPLATE_PRINTF("%s_poly_compose_mod_brent_kung_preinv\n", T); flint_abort(); } if (len1 >= len3) { TEMPLATE_PRINTF ("Exception: %s_poly_compose_brent_kung: the degree of the", T); flint_printf (" first polynomial must be smaller than that of the modulus\n"); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/compose_mod_horner.c000066400000000000000000000072221414523752600225130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #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) { TEMPLATE_PRINTF ("Exception: division by zero in %s_poly_compose_mod_horner\n", T); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/compose_mod_horner_preinv.c000066400000000000000000000077541414523752600241100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #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) { TEMPLATE_PRINTF ("Exception: division by zero in %s_poly_compose_mod_horner\n", T); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/compose_mod_preinv.c000066400000000000000000000072471414523752600225300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #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) { TEMPLATE_PRINTF("Exception: division by zero in %s_poly_compose_mod\n", T); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/deflate.c000066400000000000000000000024061414523752600202350ustar00rootroot00000000000000/* 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 2.1 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) { TEMPLATE_PRINTF("Exception (%s_poly_deflate). Division by zero.\n", T); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/deflation.c000066400000000000000000000023251414523752600205760ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/derivative.c000066400000000000000000000024551414523752600207770ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/div_basecase.c000066400000000000000000000056231414523752600212450ustar00rootroot00000000000000/* Copyright (C) 2011, 2010 Sebastian Pancratz Copyright (C) 2008, 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_div_basecase) (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) { const slong alloc = (R == NULL) ? lenA : 0; slong lenR = lenB - 1, iQ; if (alloc) R = _TEMPLATE(T, vec_init) (alloc, ctx); if (R != A) _TEMPLATE(T, vec_set) (R + lenR, A + lenR, lenA - lenR, ctx); for (iQ = lenA - lenB; iQ >= 0; iQ--) { if (TEMPLATE(T, is_zero) (R + lenA - 1, ctx)) { TEMPLATE(T, zero) (Q + iQ, ctx); } else { TEMPLATE(T, mul) (Q + iQ, R + lenA - 1, invB, ctx); _TEMPLATE(T, TEMPLATE(vec_scalar_submul, T)) (R + lenA - lenR - 1, B, lenR, Q + iQ, ctx); } if (lenR - 1 >= iQ) { B++; lenR--; } lenA--; } if (alloc) _TEMPLATE(T, vec_clear) (R, alloc, ctx); } 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) { 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_basecase) (q, NULL, 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); } #endif flint2-2.8.4/fq_poly_templates/div_newton_n_preinv.c000066400000000000000000000046451414523752600227140ustar00rootroot00000000000000/* 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 2.1 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) { TEMPLATE_PRINTF("Exception (%s_poly_div_newton). Division by zero.\n", T); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/div_series.c000066400000000000000000000073601414523752600207710ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (fq_poly_div_series). Division by zero.\n"); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/divides.c000066400000000000000000000054661414523752600202710ustar00rootroot00000000000000/* 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 2.1 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)) { TEMPLATE_PRINTF("Exception (%s_poly_divides). B is zero.\n", T); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/divrem_basecase.c000066400000000000000000000060351414523752600217470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_divrem_basecase) (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) { slong iQ, iR; if (R != A) _TEMPLATE(T, poly_set) (R, A, lenA, ctx); for (iQ = lenA - lenB, iR = lenA - 1; iQ >= 0; iQ--, iR--) { if (TEMPLATE(T, is_zero) (R + iR, ctx)) TEMPLATE(T, zero) (Q + iQ, ctx); else { TEMPLATE(T, mul) (Q + iQ, R + iR, invB, ctx); _TEMPLATE(T, TEMPLATE(poly_scalar_submul, T)) (R + iQ, B, lenB, Q + iQ, ctx); } } } void TEMPLATE(T, poly_divrem_basecase) (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_basecase) (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 flint2-2.8.4/fq_poly_templates/divrem_divconquer.c000066400000000000000000000137761414523752600223720ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" static void __TEMPLATE(T, poly_divrem_divconquer) (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) { 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 TEMPLATE(T, struct) * p1 = A + n2; const TEMPLATE(T, struct) * d1 = B + n2; const TEMPLATE(T, struct) * d2 = B; TEMPLATE(T, struct) * W = _TEMPLATE(T, vec_init) ((2 * n1 - 1) + lenB - 1, ctx); TEMPLATE(T, struct) * d1q1 = R + n2; TEMPLATE(T, struct) * d2q1 = W + (2 * n1 - 1); _TEMPLATE(T, poly_divrem_divconquer_recursive) (Q, d1q1, W, p1, d1, n1, invB, ctx); /* Compute d2q1 = Q d2, of length lenB - 1 */ if (n1 >= n2) _TEMPLATE(T, poly_mul) (d2q1, Q, n1, d2, n2, ctx); else _TEMPLATE(T, poly_mul) (d2q1, d2, n2, Q, n1, ctx); /* Compute BQ = d1q1 * x^n1 + d2q1, of length lenB - 1; then compute R = A - BQ */ _TEMPLATE(T, vec_swap) (R, d2q1, n2, ctx); _TEMPLATE(T, poly_add) (R + n2, R + n2, n1 - 1, d2q1 + n2, n1 - 1, ctx); _TEMPLATE(T, poly_sub) (R, A, lenA, R, lenA, ctx); _TEMPLATE(T, vec_clear) (W, (2 * n1 - 1) + lenB - 1, ctx); } else /* lenA = 2 * lenB - 1 */ { TEMPLATE(T, struct) * W = _TEMPLATE(T, vec_init) (lenA, ctx); _TEMPLATE(T, poly_divrem_divconquer_recursive) (Q, R, W, A, B, lenB, invB, ctx); _TEMPLATE(T, poly_sub) (R, A, lenB - 1, R, lenB - 1, ctx); _TEMPLATE(T, vec_clear) (W, lenA, ctx); } } void _TEMPLATE(T, poly_divrem_divconquer) (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) { if (lenA <= 2 * lenB - 1) { __TEMPLATE(T, poly_divrem_divconquer) (Q, R, A, lenA, B, lenB, invB, ctx); } else /* lenA > 2 * lenB - 1 */ { slong shift, n = 2 * lenB - 1; TEMPLATE(T, struct) * QB, *W; _TEMPLATE(T, vec_set) (R, A, lenA, ctx); W = _TEMPLATE(T, vec_init) (2 * n, ctx); QB = W + n; while (lenA >= n) { shift = lenA - n; _TEMPLATE(T, poly_divrem_divconquer_recursive) (Q + shift, QB, W, R + shift, B, lenB, invB, ctx); _TEMPLATE(T, poly_sub) (R + shift, R + shift, n, QB, n, ctx); lenA -= lenB; } if (lenA >= lenB) { __TEMPLATE(T, poly_divrem_divconquer) (Q, W, R, lenA, B, lenB, invB, ctx); _TEMPLATE(T, vec_swap) (W, R, lenA, ctx); } _TEMPLATE(T, vec_clear) (W, 2 * n, ctx); } } void TEMPLATE(T, poly_divrem_divconquer) (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; 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 == 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_divconquer) (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 flint2-2.8.4/fq_poly_templates/divrem_divconquer_recursive.c000066400000000000000000000103231414523752600244420ustar00rootroot00000000000000/* Copyright (C) 2008, 2009 William Hart 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" void _TEMPLATE(T, poly_divrem_divconquer_recursive) ( TEMPLATE(T, struct) * Q, TEMPLATE(T, struct) * BQ, TEMPLATE(T, struct) * W, const TEMPLATE(T, struct) * A, const TEMPLATE(T, struct) * B, slong lenB, const TEMPLATE(T, t) invB, const TEMPLATE(T, ctx_t) ctx) { if (lenB <= TEMPLATE(CAP_T, POLY_DIVREM_DIVCONQUER_CUTOFF)) { _TEMPLATE(T, vec_zero) (BQ, lenB - 1, ctx); _TEMPLATE(T, vec_set) (BQ + (lenB - 1), A + (lenB - 1), lenB, ctx); _TEMPLATE(T, poly_divrem_basecase) (Q, BQ, BQ, 2 * lenB - 1, B, lenB, invB, ctx); _TEMPLATE(T, poly_neg) (BQ, BQ, lenB - 1, ctx); _TEMPLATE(T, vec_set) (BQ + (lenB - 1), A + (lenB - 1), lenB, ctx); } else { const slong n2 = lenB / 2; const slong n1 = lenB - n2; TEMPLATE(T, struct) * W1 = W; TEMPLATE(T, struct) * W2 = W + lenB; const TEMPLATE(T, struct) * p1 = A + 2 * n2; const TEMPLATE(T, struct) * p2; const TEMPLATE(T, struct) * d1 = B + n2; const TEMPLATE(T, struct) * d2 = B; const TEMPLATE(T, struct) * d3 = B + n1; const TEMPLATE(T, struct) * d4 = B; TEMPLATE(T, struct) * q1 = Q + n2; TEMPLATE(T, struct) * q2 = Q; TEMPLATE(T, struct) * dq1 = BQ + n2; TEMPLATE(T, struct) * d1q1 = BQ + 2 * n2; TEMPLATE(T, struct) * 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 */ _TEMPLATE(T, poly_divrem_divconquer_recursive) (q1, d1q1, W1, p1, d1, n1, invB, ctx); /* Compute d2q1 = d2 q1, of length lenB - 1 */ d2q1 = W1; _TEMPLATE(T, poly_mul) (d2q1, q1, n1, d2, n2, ctx); /* Compute dq1 = d1 q1 x^n2 + d2 q1, of length 2 n1 + n2 - 1 */ _TEMPLATE(T, vec_swap) (dq1, d2q1, n2, ctx); _TEMPLATE(T, poly_add) (dq1 + n2, dq1 + n2, n1 - 1, d2q1 + n2, 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; _TEMPLATE(T, poly_sub) (t, A + n2 + (n1 - 1), n2, dq1 + (n1 - 1), n2, ctx); 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; _TEMPLATE(T, poly_divrem_divconquer_recursive) (q2, d3q2, W2, p2, d3, n2, invB, ctx); /* Compute d4q2 = d4 q2, of length n1 + n2 - 1 = lenB - 1 */ d4q2 = W2; _TEMPLATE(T, poly_mul) (d4q2, d4, n1, q2, n2, ctx); /* Compute dq2 = d3q2 x^n1 + d4q2, of length n1 + 2 n2 - 1 */ _TEMPLATE(T, vec_swap) (BQ, d4q2, n2, ctx); _TEMPLATE(T, poly_add) (BQ + n2, BQ + n2, n1 - 1, d4q2 + n2, n1 - 1, ctx); _TEMPLATE(T, poly_add) (BQ + n1, BQ + n1, 2 * n2 - 1, d3q2, 2 * n2 - 1, ctx); /* Note Q = q1 x^n2 + q2, and BQ = dq1 x^n2 + dq2 */ } } #endif flint2-2.8.4/fq_poly_templates/divrem_f.c000066400000000000000000000056641414523752600204350ustar00rootroot00000000000000/* 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 2.1 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_divconquer) (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 flint2-2.8.4/fq_poly_templates/divrem_newton_n_preinv.c000066400000000000000000000063231414523752600234130ustar00rootroot00000000000000/* 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 2.1 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) { TEMPLATE_PRINTF ("Exception (%s_poly_divrem_newton_n_preinv). Division by zero.\n", T); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/equal.c000066400000000000000000000016431414523752600177420ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/equal_trunc.c000066400000000000000000000025301414523752600211510ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/evaluate_fq.c000066400000000000000000000034561414523752600211330ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/evaluate_fq_vec.c000066400000000000000000000027271414523752600217700ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/evaluate_fq_vec_fast.c000066400000000000000000000110321414523752600227720ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/evaluate_fq_vec_iter.c000066400000000000000000000025401414523752600230040ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/fit_length.c000066400000000000000000000015261414523752600207560ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/fprint.c000066400000000000000000000023641414523752600201360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "fmpz.h" 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) (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); } #endif flint2-2.8.4/fq_poly_templates/fprint_pretty.c000066400000000000000000000062551414523752600215500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" /* 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_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_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); } #endif flint2-2.8.4/fq_poly_templates/gcd.c000066400000000000000000000057221414523752600173720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.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, t) invB, const TEMPLATE(T, ctx_t) ctx) { slong cutoff; if (fmpz_bits(TEMPLATE(T, ctx_prime) (ctx)) <= 8) cutoff = TEMPLATE(CAP_T, POLY_SMALL_GCD_CUTOFF); else cutoff = TEMPLATE(CAP_T, POLY_GCD_CUTOFF); if (lenA < cutoff) return _TEMPLATE(T, poly_gcd_euclidean) (G, A, lenA, B, lenB, invB, ctx); else return _TEMPLATE(T, poly_gcd_hgcd) (G, A, lenA, B, lenB, invB, ctx); } 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, t) invB; 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; } TEMPLATE(T, init) (invB, ctx); TEMPLATE(T, inv) (invB, TEMPLATE(T, poly_lead) (B, ctx), ctx); lenG = _TEMPLATE(T, poly_gcd) (g, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); TEMPLATE(T, clear) (invB, 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 flint2-2.8.4/fq_poly_templates/gcd_euclidean.c000066400000000000000000000105241414523752600213770ustar00rootroot00000000000000/* Copyright (C) 2011 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include 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) { if (lenB == 1) { TEMPLATE(T, one) (G, ctx); return 1; } else /* lenA >= lenB > 1 */ { const slong lenW = FLINT_MAX(lenA - lenB + 1, lenB) + lenA + 2 * lenB; TEMPLATE(T, t) invR3; 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) (Q, R1, A, lenA, B, lenB, invB, ctx); lenR3 = lenB - 1; TEMPLATE(CAP_T, VEC_NORM) (R1, lenR3, ctx); if (lenR3 == 0) { _TEMPLATE(T, vec_set) (G, B, lenB, ctx); _TEMPLATE(T, vec_clear) (W, lenW, ctx); return lenB; } TEMPLATE(T, init) (invR3, ctx); T = R3; R3 = R1; R1 = T; _TEMPLATE(T, vec_set) (R2, B, lenB, ctx); lenR2 = lenB; do { TEMPLATE(T, inv) (invR3, R3 + (lenR3 - 1), ctx); _TEMPLATE(T, poly_divrem) (Q, R1, R2, lenR2, R3, lenR3, invR3, ctx); 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); _TEMPLATE(T, vec_clear) (W, lenW, ctx); TEMPLATE(T, clear) (invR3, ctx); return lenR2; } } void TEMPLATE(T, poly_gcd_euclidean) (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) (G, B, A, ctx); } else /* lenA >= lenB >= 0 */ { slong lenA = A->length, lenB = B->length, lenG; TEMPLATE(T, t) invB; 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; } TEMPLATE(T, init) (invB, ctx); TEMPLATE(T, inv) (invB, TEMPLATE(T, poly_lead) (B, ctx), ctx); lenG = _TEMPLATE(T, poly_gcd_euclidean) (g, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); TEMPLATE(T, clear) (invB, 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 flint2-2.8.4/fq_poly_templates/gcd_euclidean_f.c000066400000000000000000000124711414523752600217070ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/gcd_hgcd.c000066400000000000000000000130471414523752600203560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "mpn_extras.h" #define __set(B, lenB, A, lenA) \ do { \ _TEMPLATE(T, vec_set)((B), (A), (lenA), ctx); \ (lenB) = (lenA); \ } while (0) #define __rem(R, lenR, A, lenA, B, lenB, invB) \ do { \ if ((lenA) >= (lenB)) \ { \ _TEMPLATE(T, poly_rem)((R), (A), (lenA), (B), (lenB), (invB), ctx); \ (lenR) = (lenB) - 1; \ TEMPLATE(CAP_T, VEC_NORM)(R, lenR, ctx); \ } \ else \ { \ _TEMPLATE(T, vec_set)((R), (A), (lenA), ctx); \ (lenR) = (lenA); \ } \ } while (0) /* XXX: Incidentally, this implementation currently supports aliasing. But since this may change in the future, no function other than TEMPLATE(T, poly_gcd_hgcd)() should rely on this. */ slong _TEMPLATE(T, poly_gcd_hgcd) (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 cutoff, lenG, lenJ, lenR; TEMPLATE(T, struct) * J = _TEMPLATE(T, vec_init) (2 * lenB, ctx); TEMPLATE(T, struct) * R = J + lenB; TEMPLATE(T, t) inv; if (fmpz_bits(TEMPLATE(T, ctx_prime) (ctx)) <= 8) cutoff = TEMPLATE(CAP_T, POLY_SMALL_GCD_CUTOFF); else cutoff = TEMPLATE(CAP_T, POLY_GCD_CUTOFF); __rem(R, lenR, A, lenA, B, lenB, invB); if (lenR == 0) { __set(G, lenG, B, lenB); } else { TEMPLATE(T, init) (inv, ctx); _TEMPLATE(T, poly_hgcd) (NULL, NULL, G, &(lenG), J, &(lenJ), B, lenB, R, lenR, ctx); while (lenJ != 0) { TEMPLATE(T, inv) (inv, J + lenJ - 1, ctx); __rem(R, lenR, G, lenG, J, lenJ, inv); if (lenR == 0) { __set(G, lenG, J, lenJ); break; } if (lenJ < cutoff) { TEMPLATE(T, inv) (inv, R + lenR - 1, ctx); lenG = _TEMPLATE(T, poly_gcd_euclidean) (G, J, lenJ, R, lenR, inv, ctx); break; } _TEMPLATE(T, poly_hgcd) (NULL, NULL, G, &(lenG), J, &(lenJ), J, lenJ, R, lenR, ctx); } TEMPLATE(T, clear) (inv, ctx); } _TEMPLATE(T, vec_clear) (J, 2 * lenB, ctx); return lenG; } void TEMPLATE(T, poly_gcd_hgcd) (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_hgcd) (G, B, A, ctx); } else /* lenA >= lenB >= 0 */ { slong lenA = A->length, lenB = B->length, lenG; TEMPLATE(T, poly_t) tG; TEMPLATE(T, t) invB; 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) { TEMPLATE(T, poly_init2) (tG, FLINT_MIN(lenA, lenB), ctx); g = tG->coeffs; } else { TEMPLATE(T, poly_fit_length) (G, FLINT_MIN(lenA, lenB), ctx); g = G->coeffs; } TEMPLATE(T, init) (invB, ctx); TEMPLATE(T, inv) (invB, B->coeffs + lenB - 1, ctx); lenG = _TEMPLATE(T, poly_gcd_hgcd) (g, A->coeffs, lenA, B->coeffs, lenB, invB, ctx); if (G == A || G == B) { TEMPLATE(T, poly_swap) (tG, G, ctx); TEMPLATE(T, poly_clear) (tG, ctx); } G->length = lenG; if (G->length == 1) TEMPLATE(T, one) (G->coeffs, ctx); else TEMPLATE(T, poly_make_monic) (G, G, ctx); TEMPLATE(T, clear) (invB, ctx); } } } #undef __set #undef __rem #endif flint2-2.8.4/fq_poly_templates/gen.c000066400000000000000000000012531414523752600174010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_poly_templates/get_coeff.c000066400000000000000000000014661414523752600205570ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/get_str.c000066400000000000000000000036631414523752600203060ustar00rootroot00000000000000/* 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 2.1 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, nz; 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 *)); nz = 0; 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]); nz++; } 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 flint2-2.8.4/fq_poly_templates/get_str_pretty.c000066400000000000000000000054311414523752600217100ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/hamming_weight.c000066400000000000000000000016721414523752600216240ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/hgcd.c000066400000000000000000000443011414523752600175360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" /* We define a whole bunch of macros here which essentially provide the TEMPLATE(T, 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) = (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 { \ _TEMPLATE(T, vec_set)((B), (A), (lenA), ctx); \ (lenB) = (lenA); \ } while (0) #define __swap(u, l, v, m) \ do { \ { TEMPLATE(T, struct)* _; _ = (u), (u) = (v), (v) = _;} \ { slong _; _ = (l), (l) = (m), (m) = _;} \ } while (0) #define __add(C, lenC, A, lenA, B, lenB) \ do { \ _TEMPLATE(T, poly_add)((C), (A), (lenA), (B), (lenB), ctx); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ TEMPLATE(CAP_T, VEC_NORM)((C), (lenC), ctx); \ } while (0) #define __sub(C, lenC, A, lenA, B, lenB) \ do { \ _TEMPLATE(T, poly_sub)((C), (A), (lenA), (B), (lenB), ctx); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ TEMPLATE(CAP_T, VEC_NORM)((C), (lenC), ctx); \ } while (0) #define __mul(C, lenC, A, lenA, B, lenB) \ do { \ if ((lenA) != 0 && (lenB) != 0) \ { \ if ((lenA) >= (lenB)) \ _TEMPLATE(T, poly_mul)((C), (A), (lenA), (B), (lenB), ctx); \ else \ _TEMPLATE(T, 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, invB) \ do { \ if ((lenA) >= (lenB)) \ { \ _TEMPLATE(T, poly_divrem)((Q), (R), (A), (lenA), (B), (lenB), (invB), ctx); \ (lenQ) = (lenA) - (lenB) + 1; \ (lenR) = (lenB) - 1; \ TEMPLATE(CAP_T, VEC_NORM)((R), (lenR), ctx); \ } \ else \ { \ _TEMPLATE(T, vec_set)((R), (A), (lenA), ctx); \ (lenQ) = 0; \ (lenR) = (lenA); \ } \ } while (0) static __inline__ void __mat_one(TEMPLATE(T, struct) ** M, slong * lenM, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, one) (M[0], ctx); TEMPLATE(T, one) (M[3], ctx); lenM[0] = 1; lenM[1] = 0; lenM[2] = 0; lenM[3] = 1; } /* 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 void __mat_mul_classical(TEMPLATE(T, struct) ** C, slong * lenC, TEMPLATE(T, struct) ** A, slong * lenA, TEMPLATE(T, struct) ** B, slong * lenB, TEMPLATE(T, struct) * T, const TEMPLATE(T, ctx_t) ctx) { slong lenT; __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); } /* 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 void __mat_mul_strassen(TEMPLATE(T, struct) ** C, slong * lenC, TEMPLATE(T, struct) ** A, slong * lenA, TEMPLATE(T, struct) ** B, slong * lenB, TEMPLATE(T, struct) * T0, TEMPLATE(T, struct) * T1, const TEMPLATE(T, ctx_t) ctx) { slong lenT0, lenT1; __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); } /* 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 void __mat_mul(TEMPLATE(T, struct) ** C, slong * lenC, TEMPLATE(T, struct) ** A, slong * lenA, TEMPLATE(T, struct) ** B, slong * lenB, TEMPLATE(T, struct) * T0, TEMPLATE(T, struct) * T1, const TEMPLATE(T, 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) { __mat_mul_classical(C, lenC, A, lenA, B, lenB, T0, ctx); } else { __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. */ slong _TEMPLATE(T, poly_hgcd_recursive_iter) ( TEMPLATE(T, struct) ** M, slong * lenM, TEMPLATE(T, struct) ** A, slong * lenA, TEMPLATE(T, struct) ** B, slong * lenB, const TEMPLATE(T, struct) * a, slong lena, const TEMPLATE(T, struct) * b, slong lenb, TEMPLATE(T, struct) * Q, TEMPLATE(T, struct) ** T, TEMPLATE(T, struct) **t, const TEMPLATE(T, ctx_t) ctx) { TEMPLATE(T, t) invB; const slong m = lena / 2; slong sgn = 1; TEMPLATE(CAP_T, VEC_NORM) (b, lenb, ctx); __mat_one(M, lenM, ctx); __set(*A, *lenA, a, lena); __set(*B, *lenB, b, lenb); TEMPLATE(T, init) (invB, ctx); while (*lenB >= m + 1) { slong lenQ, lenT, lent; TEMPLATE(T, inv) (invB, *B + *lenB - 1, ctx); __divrem(Q, lenQ, *T, lenT, *A, *lenA, *B, *lenB, invB); __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; } TEMPLATE(T, clear) (invB, ctx); return sgn; } /* 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. */ slong _TEMPLATE(T, poly_hgcd_recursive) ( TEMPLATE(T, struct)**M, slong * lenM, TEMPLATE(T, struct) * A, slong * lenA, TEMPLATE(T, struct) * B, slong * lenB, const TEMPLATE(T, struct) * a, slong lena, const TEMPLATE(T, struct) * b, slong lenb, TEMPLATE(T, struct) * P, const TEMPLATE(T, ctx_t) ctx, int flag) { const slong m = lena / 2; if (lenb < m + 1) { if (flag) { __mat_one(M, lenM, ctx); } __set(A, *lenA, a, lena); __set(B, *lenB, b, lenb); return 1; } else { /* Readonly pointers */ TEMPLATE(T, struct) * a0, *b0, *s, *t, *a4, *b4, *c0, *d0; slong lena0, lenb0, lens, lent, lena4, lenb4, lenc0, lend0; /* Pointers to independently allocated memory */ TEMPLATE(T, struct) * a2, *b2, *a3, *b3, *q, *d, *T0, *T1; slong lena2, lenb2, lena3, lenb3, lenq, lend, lenT0; TEMPLATE(T, struct) * R[4], *S[4]; slong lenR[4], lenS[4]; slong sgnR, sgnS; a2 = P; b2 = a2 + lena; a3 = b2 + lena; b3 = a3 + lena; q = b3 + lena; d = q + (lena + 1) / 2; T0 = d + lena; T1 = T0 + lena; R[0] = T1 + (lena + 1) / 2; R[1] = R[0] + (lena + 1) / 2; R[2] = R[1] + (lena + 1) / 2; R[3] = R[2] + (lena + 1) / 2; S[0] = R[3] + (lena + 1) / 2; S[1] = S[0] + (lena + 1) / 2; S[2] = S[1] + (lena + 1) / 2; S[3] = S[2] + (lena + 1) / 2; P += 6 * lena + 10 * (lena + 1) / 2; __attach_shift(a0, lena0, (TEMPLATE(T, struct) *) a, lena, m); __attach_shift(b0, lenb0, (TEMPLATE(T, struct) *) b, lenb, m); if (lena0 < TEMPLATE(CAP_T, POLY_HGCD_CUTOFF)) sgnR = _TEMPLATE(T, poly_hgcd_recursive_iter) (R, lenR, &a3, &lena3, &b3, &lenb3, a0, lena0, b0, lenb0, q, &T0, &T1, ctx); else sgnR = _TEMPLATE(T, poly_hgcd_recursive) (R, lenR, a3, &lena3, b3, &lenb3, a0, lena0, b0, lenb0, P, ctx, 1); __attach_truncate(s, lens, (TEMPLATE(T, struct) *) a, lena, m); __attach_truncate(t, lent, (TEMPLATE(T, struct) *) 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); _TEMPLATE(T, vec_zero) (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); TEMPLATE(CAP_T, VEC_NORM) (b2, lenb2, 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); _TEMPLATE(T, vec_zero) (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); TEMPLATE(CAP_T, VEC_NORM) (a2, lena2, 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]); } return sgnR; } else { TEMPLATE(T, t) invB; slong k = 2 * m - lenb2 + 1; TEMPLATE(T, init) (invB, ctx); TEMPLATE(T, inv) (invB, b2 + lenb2 - 1, ctx); __divrem(q, lenq, d, lend, a2, lena2, b2, lenb2, invB); TEMPLATE(T, clear) (invB, ctx); __attach_shift(c0, lenc0, b2, lenb2, k); __attach_shift(d0, lend0, d, lend, k); if (lenc0 < TEMPLATE(CAP_T, POLY_HGCD_CUTOFF)) sgnS = _TEMPLATE(T, poly_hgcd_recursive_iter) ( S, lenS, &a3, &lena3, &b3, &lenb3, c0, lenc0, d0, lend0, a2, &T0, &T1, ctx); /* a2 as temp */ else sgnS = _TEMPLATE(T, poly_hgcd_recursive) (S, lenS, a3, &lena3, b3, &lenb3, c0, lenc0, d0, lend0, P, ctx, 1); __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); _TEMPLATE(T, vec_zero) (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); TEMPLATE(CAP_T, VEC_NORM) (B, *lenB, 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); _TEMPLATE(T, vec_zero) (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); TEMPLATE(CAP_T, VEC_NORM) (A, *lenA, 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); } return -(sgnR * sgnS); } } } /* XXX: Currently supports aliasing between {A,a} and {B,b}. */ slong _TEMPLATE(T, poly_hgcd) (TEMPLATE(T, struct)**M, slong * lenM, TEMPLATE(T, struct) * A, slong * lenA, TEMPLATE(T, struct) * B, slong * lenB, const TEMPLATE(T, struct) * a, slong lena, const TEMPLATE(T, struct) * b, slong lenb, const TEMPLATE(T, ctx_t) ctx) { const slong lenW = 22 * lena + 16 * (FLINT_CLOG2(lena) + 1); slong sgnM; TEMPLATE(T, struct) * W; W = _TEMPLATE(T, vec_init) (lenW, ctx); if (M == NULL) { sgnM = _TEMPLATE(T, poly_hgcd_recursive) (NULL, NULL, A, lenA, B, lenB, a, lena, b, lenb, W, ctx, 0); } else { sgnM = _TEMPLATE(T, poly_hgcd_recursive) (M, lenM, A, lenA, B, lenB, a, lena, b, lenb, W, ctx, 1); } _TEMPLATE(T, vec_clear) (W, lenW, ctx); return sgnM; } #endif flint2-2.8.4/fq_poly_templates/inflate.c000066400000000000000000000033001414523752600202450ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/init.c000066400000000000000000000016121414523752600175720ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/inv_series_newton.c000066400000000000000000000067631414523752600224030ustar00rootroot00000000000000/* 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 2.1 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_basecase) (Qinv, W, 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 flint2-2.8.4/fq_poly_templates/make_monic.c000066400000000000000000000026271414523752600207400ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/mul.c000066400000000000000000000041571414523752600174330ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/mul_KS.c000066400000000000000000000053051414523752600200240ustar00rootroot00000000000000/* 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 2.1 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 = 2 * fmpz_bits(TEMPLATE(T, ctx_prime) (ctx)) + FLINT_BIT_COUNT(d) + FLINT_BIT_COUNT(FLINT_MIN(len1, len2)); 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 flint2-2.8.4/fq_poly_templates/mul_classical.c000066400000000000000000000052121414523752600214420ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/mul_reorder.c000066400000000000000000000131461414523752600211530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" /* Include routines for vectors over \code{fmpz_poly_struct}, for use in the classical multiplication routine in the $X$-direction. */ 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); } } 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 flint2-2.8.4/fq_poly_templates/mulhigh.c000066400000000000000000000054531414523752600202730ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/mulhigh_classical.c000066400000000000000000000074011414523752600223040ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/mullow.c000066400000000000000000000043641414523752600201550ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/mullow_KS.c000066400000000000000000000052751414523752600205540ustar00rootroot00000000000000/* 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 2.1 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 = 2 * fmpz_bits(TEMPLATE(T, ctx_prime) (ctx)) + FLINT_BIT_COUNT(d) + FLINT_BIT_COUNT(FLINT_MIN(len1, len2)); 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 flint2-2.8.4/fq_poly_templates/mullow_classical.c000066400000000000000000000053221414523752600221660ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/mulmod.c000066400000000000000000000055251414523752600201330ustar00rootroot00000000000000/* 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 2.1 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) { TEMPLATE_PRINTF("Exception: %s_poly_mulmod: divide by zero\n", T); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/mulmod_preinv.c000066400000000000000000000077671414523752600215300ustar00rootroot00000000000000/* 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 2.1 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) { TEMPLATE_PRINTF("Exception (%s_poly_mulmod). Divide by zero.\n", T); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/neg.c000066400000000000000000000020511414523752600173760ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/normalise.c000066400000000000000000000017771414523752600206340ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/one.c000066400000000000000000000012631414523752600174120ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/pow.c000066400000000000000000000074651414523752600174500ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/pow_trunc.c000066400000000000000000000055721414523752600206600ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/pow_trunc_binexp.c000066400000000000000000000107611414523752600222210ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/powmod_fmpz_binexp.c000066400000000000000000000110161414523752600225340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #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) { TEMPLATE_PRINTF ("Exception: %s_poly_powmod_fmpz_binexp: divide by zero\n", T); flint_abort(); } if (fmpz_sgn(e) < 0) { TEMPLATE_PRINTF ("Exception: %s_poly_powmod_fmpz_binexp: negative exp not implemented\n", T); flint_abort(); } 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_abs_fits_ui(e)) { ulong exp = fmpz_get_ui(e); if (exp <= 2) { if (exp == 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 (exp == UWORD(1)) { TEMPLATE(T, poly_set) (res, poly, ctx); } else TEMPLATE(T, poly_mulmod) (res, poly, poly, f, ctx); return; } } if (lenf == 1 || len == 0) { TEMPLATE(T, poly_zero) (res, 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 flint2-2.8.4/fq_poly_templates/powmod_fmpz_binexp_preinv.c000066400000000000000000000120141414523752600241160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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) { TEMPLATE_PRINTF ("Exception: %s_poly_powmod_fmpz_binexp_preinv: divide by zero\n", T); flint_abort(); } if (fmpz_sgn(e) < 0) { TEMPLATE_PRINTF ("Exception: %s_poly_powmod_fmpz_binexp_preinv: negative exp not implemented\n", T); flint_abort(); } 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_abs_fits_ui(e)) { ulong exp = fmpz_get_ui(e); if (exp <= 2) { if (exp == 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 (exp == UWORD(1)) { TEMPLATE(T, poly_set) (res, poly, ctx); } else TEMPLATE(T, poly_mulmod_preinv) (res, poly, poly, f, finv, ctx); return; } } if (lenf == 1 || len == 0) { TEMPLATE(T, poly_zero) (res, 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 flint2-2.8.4/fq_poly_templates/powmod_fmpz_sliding_preinv.c000066400000000000000000000200431414523752600242630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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) { TEMPLATE_PRINTF("Exception: %s_poly_powmod_fmpz_sliding_preinv", T); flint_printf(": divide by zero\n"); flint_abort(); } if (fmpz_sgn(e) < 0) { TEMPLATE_PRINTF("Exception: %s_poly_powmod_fmpz_sliding_preinv:", T); flint_printf(" negative exp not implemented\n"); flint_abort(); } 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_abs_fits_ui(e)) { ulong exp = fmpz_get_ui(e); if (exp <= 2) { if (exp == 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 (exp == UWORD(1)) { TEMPLATE(T, poly_set) (res, poly, ctx); } else TEMPLATE(T, poly_mulmod_preinv) (res, poly, poly, f, finv, ctx); return; } } if (lenf == 1 || len == 0) { TEMPLATE(T, poly_zero) (res, 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 flint2-2.8.4/fq_poly_templates/powmod_ui_binexp.c000066400000000000000000000103501414523752600221750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #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) { TEMPLATE_PRINTF ("Exception: %s_poly_powmod_ui_binexp: divide by zero\n", T); flint_abort(); } 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 <= 2) { 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_set) (res, poly, ctx); } else TEMPLATE(T, poly_mulmod) (res, poly, poly, f, ctx); return; } if (lenf == 1 || len == 0) { TEMPLATE(T, poly_zero) (res, 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 flint2-2.8.4/fq_poly_templates/powmod_ui_binexp_preinv.c000066400000000000000000000110511414523752600235570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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) { TEMPLATE_PRINTF("Exception: %s_poly_powmod: divide by zero\n", T); flint_abort(); } 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 <= 2) { 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_set) (res, poly, ctx); } else TEMPLATE(T, poly_mulmod_preinv) (res, poly, poly, f, finv, ctx); return; } if (lenf == 1 || len == 0) { TEMPLATE(T, poly_zero) (res, 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 flint2-2.8.4/fq_poly_templates/powmod_x_fmpz_preinv.c000066400000000000000000000133561414523752600231120ustar00rootroot00000000000000/* 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 2.1 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) { TEMPLATE_PRINTF("Exception: %s_poly_powmod_x_preinv:", T); flint_printf(" divide by zero\n"); flint_abort(); } if (fmpz_sgn(e) < 0) { TEMPLATE_PRINTF("Exception: %s_poly_powmod_x_preinv: ", T); flint_printf(" negative exp not implemented\n"); flint_abort(); } 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 (fmpz_abs_fits_ui(e)) { ulong exp = fmpz_get_ui(e); if (exp <= 2) { if (exp == 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 (exp == 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 flint2-2.8.4/fq_poly_templates/profile/000077500000000000000000000000001414523752600201235ustar00rootroot00000000000000flint2-2.8.4/fq_poly_templates/profile/p-factor_xnpxp1.c000066400000000000000000000031211414523752600233150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_poly_templates/profile/p-gcd-old.c000066400000000000000000000125551414523752600220450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "profiler.h" /* Profiling and benchmarking code for GCD in fq_poly_templates. 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(int argc, char** argv) { FLINT_TEST_INIT(state); fmpz_t pp; slong ext = atoi(argv[1]); 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}}; long double cpu[3][2][N]; slong i, k, c, n; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) A, B, C, G; fmpz_init(pp); for (i = 0; i < 3; i++) { flint_printf("---[Modulus %wu^%wd]---\n", p[i], ext), fflush(stdout); fmpz_set_ui(pp, p[i]); TEMPLATE(T, ctx_init)(ctx, pp, ext, "a"); for (k = 0; k < N; k++) { const slong d = degs[k]; slong r = runs[i][k]; /*r = 5;*/ cpu[i][0][k] = (long double) 0.0; cpu[i][1][k] = (long double) 0.0; TEMPLATE(T, poly_init)(A, ctx); TEMPLATE(T, poly_init)(B, ctx); TEMPLATE(T, poly_init)(C, ctx); TEMPLATE(T, poly_init)(G, ctx); for (c = 0; c < 100; c++) { TEMPLATE(T, poly_randtest)(A, state, d/2, ctx); TEMPLATE(T, poly_randtest)(B, state, d/2, ctx); TEMPLATE(T, poly_randtest)(C, state, d/2, ctx); TEMPLATE(T, poly_mul)(A, A, C, ctx); TEMPLATE(T, poly_mul)(B, B, C, ctx); flint_printf("%4ld %10.8lf %10.8lf\n", A->length, cpu[i][0][k], cpu[i][1][k]); init_clock(0); prof_start(); for (n = 0; n < r; n++) TEMPLATE(T, poly_gcd_euclidean)(G, A, B, ctx); prof_stop(); cpu[i][1][k] += get_clock(0); init_clock(0); prof_start(); for (n = 0; n < r; n++) TEMPLATE(T, poly_gcd_hgcd)(G, A, B, ctx); prof_stop(); cpu[i][1][k] += get_clock(0); } 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.8llf %10.8llf\n", A->length, cpu[i][0][k], cpu[i][1][k]); fflush(stdout); 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); } } 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 EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/profile/p-gcd.c000066400000000000000000000055111414523752600212630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 50 int main(int argc, char** argv) { fmpz_t p, q; int l, n, reps = 0; slong d, len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, g; slong i; double beta; double s[nalgs]; FLINT_TEST_INIT(state); fmpz_init(p); fmpz_set_str(p, argv[1], 10); d = atol(argv[2]); len = atol(argv[3]); TEMPLATE(T, ctx_init)(ctx, p, d, "a"); TEMPLATE(T, poly_init)(a, ctx); TEMPLATE(T, poly_init)(b, ctx); TEMPLATE(T, poly_init)(c, ctx); TEMPLATE(T, poly_init)(g, ctx); fmpz_init(q); TEMPLATE(T, ctx_order)(q, ctx); for (l = 0; l < nalgs; l++) s[l] = 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)(a, state, len / 2, ctx); TEMPLATE(T, poly_randtest_monic)(b, state, len / 2, ctx); TEMPLATE(T, poly_randtest_monic)(c, state, len / 2, ctx); TEMPLATE(T, poly_mul)(a, a, c, ctx); TEMPLATE(T, poly_mul)(b, b, c, ctx); } loop: t[0] = 0.0; init_clock(0); prof_start(); for (lo = 0; lo < loops; lo++) { TEMPLATE(T, poly_gcd_euclidean)(g, a, b, 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_gcd_hgcd)(g, a, b, ctx); } prof_stop(); t[1] += get_clock(0); for (l = 0; l < nalgs; l++) if (t[l] * FLINT_CLOCK_SCALE_FACTOR <= cpumin) { loops *= 10; goto loop; } for (l = 0; l < nalgs; l++) s[l] += t[l]; reps += loops; } for (l = 0; l < nalgs; l++) { printf("%20f", s[l] / (double) reps); fflush(stdout); } printf("\n"); 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); fmpz_clear(p); fmpz_clear(q); FLINT_TEST_CLEANUP(state); return 0; } #endif flint2-2.8.4/fq_poly_templates/profile/p-is_irreducible.c000066400000000000000000000045101414523752600235100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_poly_templates/profile/p-iterated_frobenius.c000066400000000000000000000112651414523752600244060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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"); 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 flint2-2.8.4/fq_poly_templates/profile/p-iterated_frobenius_table.c000066400000000000000000000245011414523752600255520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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"); 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"); 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"); 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 flint2-2.8.4/fq_poly_templates/profile/p-mullow.c000066400000000000000000000051511414523752600220450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_poly_templates/profile/p-sqr.c000066400000000000000000000046061414523752600213370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_poly_templates/randtest.c000066400000000000000000000027371414523752600204640ustar00rootroot00000000000000/* 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 2.1 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) { TEMPLATE_PRINTF("Exception (%s_poly_randtest_not_zero). len = 0.\n", T); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/randtest_irreducible.c000066400000000000000000000044431414523752600230310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 */ fmpz_init_set(q, TEMPLATE(T, ctx_prime) (ctx)); fmpz_pow_ui(q, q, TEMPLATE(T, ctx_degree) (ctx)); 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 flint2-2.8.4/fq_poly_templates/randtest_monic.c000066400000000000000000000017051414523752600216430ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/realloc.c000066400000000000000000000033471414523752600202570ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/remove.c000066400000000000000000000022701414523752600201250ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/reverse.c000066400000000000000000000032521414523752600203040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_poly_templates/scalar_addmul_fq.c000066400000000000000000000041371414523752600221150ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/scalar_div_fq.c000066400000000000000000000033151414523752600214260ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (fq_poly_scalar_div) Division by zero"); flint_abort(); } 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 flint2-2.8.4/fq_poly_templates/scalar_mul_fq.c000066400000000000000000000031351414523752600214410ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/scalar_submul_fq.c000066400000000000000000000041461414523752600221560ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/set.c000066400000000000000000000023741414523752600174300ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/set_coeff.c000066400000000000000000000025131414523752600205650ustar00rootroot00000000000000/* 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 2.1 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); } #endif flint2-2.8.4/fq_poly_templates/set_fmpz_mod_poly.c000066400000000000000000000015731414523752600223660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" FLINT_DLL 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 flint2-2.8.4/fq_poly_templates/set_fq.c000066400000000000000000000016431414523752600201140ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/set_nmod_poly.c000066400000000000000000000015511414523752600215040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" FLINT_DLL 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 flint2-2.8.4/fq_poly_templates/set_trunc.c000066400000000000000000000021611414523752600206350ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/shift_left.c000066400000000000000000000032211414523752600207540ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/shift_right.c000066400000000000000000000031221414523752600211370ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/sqr.c000066400000000000000000000033341414523752600174370ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/sqr_KS.c000066400000000000000000000040421414523752600200310ustar00rootroot00000000000000/* 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 2.1 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 = 2 * fmpz_bits(TEMPLATE(T, ctx_prime) (ctx)) + FLINT_BIT_COUNT(d) + FLINT_BIT_COUNT(len); 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 flint2-2.8.4/fq_poly_templates/sqr_classical.c000066400000000000000000000047111414523752600214550ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/sqr_reorder.c000066400000000000000000000124721414523752600211640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" /* Include routines for vectors over \code{fmpz_poly_struct}, for use in the classical multiplication routine in the $X$-direction. */ 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); } } 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 flint2-2.8.4/fq_poly_templates/sub.c000066400000000000000000000031541414523752600174230ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/sub_series.c000066400000000000000000000023011414523752600207660ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/swap.c000066400000000000000000000017611414523752600176060ustar00rootroot00000000000000/* 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 2.1 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) { if (op1 != op2) { slong temp; TEMPLATE(T, struct) * temp_c; temp = op1->length; op1->length = op2->length; op2->length = temp; temp = op1->alloc; op1->alloc = op2->alloc; op2->alloc = temp; temp_c = op1->coeffs; op1->coeffs = op2->coeffs; op2->coeffs = temp_c; } } #endif flint2-2.8.4/fq_poly_templates/test/000077500000000000000000000000001414523752600174425ustar00rootroot00000000000000flint2-2.8.4/fq_poly_templates/test/t-add.c000066400000000000000000000165531414523752600206110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add... "); fflush(stdout); /* Check aliasing: a = a + b */ for (i = 0; i < 100 * 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_randtest) (ctx, state); 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"); 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 < 100 * 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_randtest) (ctx, state); 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"); 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 < 100 * 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-add_series.c000066400000000000000000000142031414523752600221510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add_series... "); fflush(stdout); /* Check aliasing: a = a + b */ for (i = 0; i < 100 * 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_randtest) (ctx, state); 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"); 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 < 100 * 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_randtest) (ctx, state); 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"); 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 < 100 * 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-compose.c000066400000000000000000000122401414523752600215130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose... "); fflush(stdout); /* 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_randtest) (ctx, state); 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, 40), 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"); 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_randtest) (ctx, state); 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, 40), 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"); 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 < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) f, g, h, s, t; slong k; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 40), 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-compose_divconquer.c000066400000000000000000000123421414523752600237550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_divconquer... "); fflush(stdout); /* 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_randtest) (ctx, state); 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, 40), ctx); TEMPLATE(T, poly_randtest) (g, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_compose_divconquer) (h, f, g, ctx); TEMPLATE(T, poly_compose_divconquer) (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"); 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_randtest) (ctx, state); 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, 40), ctx); TEMPLATE(T, poly_randtest) (g, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_compose_divconquer) (h, f, g, ctx); TEMPLATE(T, poly_compose_divconquer) (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"); 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 < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) f, g, h, s, t; slong k; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 40), 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_divconquer) (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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-compose_horner.c000066400000000000000000000123121414523752600230700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_horner... "); fflush(stdout); /* 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_randtest) (ctx, state); 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, 40), ctx); TEMPLATE(T, poly_randtest) (g, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_compose_horner) (h, f, g, ctx); TEMPLATE(T, poly_compose_horner) (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"); 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_randtest) (ctx, state); 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, 40), ctx); TEMPLATE(T, poly_randtest) (g, state, n_randint(state, 20), ctx); TEMPLATE(T, poly_compose_horner) (h, f, g, ctx); TEMPLATE(T, poly_compose_horner) (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"); 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 < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) f, g, h, s, t; slong k; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 40), 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_horner) (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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-compose_mod.c000066400000000000000000000163021414523752600223550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose_mod...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-compose_mod_brent_kung.c000066400000000000000000000167221414523752600246010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-compose_mod_brent_kung_preinv.c000066400000000000000000000214341414523752600261600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung_preinv...."); fflush(stdout); for (i = 0; i < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d, e; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-compose_mod_horner.c000066400000000000000000000163721414523752600237410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose_mod_horner...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-compose_mod_horner_preinv.c000066400000000000000000000205131414523752600253140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose_mod_horner_preinv...."); fflush(stdout); for (i = 0; i < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d, e; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-compose_mod_preinv.c000066400000000000000000000204651414523752600237450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose_mod_preinv...."); fflush(stdout); for (i = 0; i < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d, e; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, cinv, d; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-deflate.c000066400000000000000000000072711414523752600214620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("deflate...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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"); 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"); 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"); abort(); } TEMPLATE(T, poly_deflate) (poly2, poly2, infl, ctx); if (!TEMPLATE(T, poly_equal) (poly3, poly2, ctx)) { flint_printf("FAIL: aliasing\n"); abort(); } } TEMPLATE(T, poly_clear) (poly1, ctx); TEMPLATE(T, poly_clear) (poly2, ctx); TEMPLATE(T, poly_clear) (poly3, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-derivative.c000066400000000000000000000126531414523752600222200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("derivative... "); fflush(stdout); /* Check aliasing */ 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_randtest) (ctx, state); 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"); 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 < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-div_basecase.c000066400000000000000000000122701414523752600224610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_basecase...."); fflush(stdout); /* Compare to divrem_basecase */ 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_randtest) (ctx, state); 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_basecase) (q, a, b, ctx); TEMPLATE(T, poly_divrem_basecase) (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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q; TEMPLATE(T, ctx_randtest) (ctx, state); 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_basecase) (q, a, b, ctx); TEMPLATE(T, poly_div_basecase) (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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q; TEMPLATE(T, ctx_randtest) (ctx, state); 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_basecase) (q, a, b, ctx); TEMPLATE(T, poly_div_basecase) (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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (q, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-div_newton_n_preinv.c000066400000000000000000000160751414523752600241340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_newton_n_preinv...."); fflush(stdout); /* Check result of divrem */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r, test; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 200), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 200), 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 200), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 200), 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 200), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 200), 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 200), ctx); while (b->length <= 2); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 200), 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-div_series.c000066400000000000000000000050601414523752600222040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_series...."); fflush(stdout); /* Check A*B^{-1} * B is congruent A mod t^n */ for (i = 0; i < 500 * 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-divides.c000066400000000000000000000115461414523752600215050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divides... "); fflush(stdout); /* Check that b divides a b and that the quotient is a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, q; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 50) + 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"); 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_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 50) + 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"); 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_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 50) + 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-divrem_basecase.c000066400000000000000000000210501414523752600231610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divrem_basecase... "); fflush(stdout); /* 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_randtest) (ctx, state); 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_basecase) (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"); 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 < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, r; TEMPLATE(T, ctx_randtest) (ctx, state); 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_basecase) (q, r, a, b, ctx); TEMPLATE(T, poly_divrem_basecase) (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"); 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 < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, r; TEMPLATE(T, ctx_randtest) (ctx, state); 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_basecase) (q, r, a, b, ctx); TEMPLATE(T, poly_divrem_basecase) (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"); 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 < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, r; TEMPLATE(T, ctx_randtest) (ctx, state); 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_basecase) (q, r, a, b, ctx); TEMPLATE(T, poly_divrem_basecase) (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"); 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 < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, r; TEMPLATE(T, ctx_randtest) (ctx, state); 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_basecase) (q, r, a, b, ctx); TEMPLATE(T, poly_divrem_basecase) (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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-divrem_divconquer.c000066400000000000000000000127211414523752600235770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divrem_divconquer...."); fflush(stdout); /* Check q*b + r = a, no aliasing */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, r, t; TEMPLATE(T, ctx_randtest) (ctx, state); 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_init) (t, 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_divrem_divconquer) (q, r, a, b, ctx); TEMPLATE(T, poly_mul) (t, q, b, ctx); TEMPLATE(T, poly_add) (t, t, r, ctx); result = (TEMPLATE(T, poly_equal) (a, t, ctx)); if (!result) { flint_printf("FAIL #1:\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("r = "), TEMPLATE(T, poly_print) (r, ctx), flint_printf("\n\n"); flint_printf("t = "), TEMPLATE(T, poly_print) (t, ctx), flint_printf("\n\n"); 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, poly_clear) (t, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Alias a and q, b and r */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, r; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 100) + 1, ctx); TEMPLATE(T, poly_divrem_divconquer) (q, r, a, b, ctx); TEMPLATE(T, poly_divrem_divconquer) (a, b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (q, a, ctx) && TEMPLATE(T, poly_equal) (r, b, ctx)); if (!result) { flint_printf("FAIL #2:\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("r = "), TEMPLATE(T, poly_print) (r, ctx), flint_printf("\n\n"); 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); } /* Alias b and q, a and r */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, q, r; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 100) + 1, ctx); TEMPLATE(T, poly_divrem_divconquer) (q, r, a, b, ctx); TEMPLATE(T, poly_divrem_divconquer) (b, a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (q, b, ctx) && TEMPLATE(T, poly_equal) (r, a, ctx)); if (!result) { flint_printf("FAIL #3:\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("r = "), TEMPLATE(T, poly_print) (r, ctx), flint_printf("\n\n"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-divrem_newton_n_preinv.c000066400000000000000000000314171414523752600246350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divrem_newton_n_preinv...."); fflush(stdout); /* Check result of divrem */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r, test; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, binv, q, r; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-equal_trunc.c000066400000000000000000000071711414523752600223770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("equal_trunc... "); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-evaluate_fq.c000066400000000000000000000104041414523752600223420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("evaluate_fq... "); fflush(stdout); /* Check aliasing */ for (i = 0; i < 200 * 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-evaluate_fq_vec_fast.c000066400000000000000000000046511414523752600242230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); TEMPLATE_PRINTF("evaluate_%s_vec_fast....", T); fflush(stdout); 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_randtest)(ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-gcd.c000066400000000000000000000156001414523752600206060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd...."); fflush(stdout); /* 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, 15) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 10 * flint_test_multiplier(); i++) { slong len, j; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, g; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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); 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); 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"); 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, 200) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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, 200) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-gcd_euclidean.c000066400000000000000000000160261414523752600226220ustar00rootroot00000000000000/* Copyright (C) 2011 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd_euclidean...."); fflush(stdout); /* 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, 15) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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_euclidean) (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"); 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 < 10 * flint_test_multiplier(); i++) { slong len, j; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, g; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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_euclidean) (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); 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); 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_euclidean) (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"); 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 < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, g; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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_euclidean) (g, a, b, ctx); TEMPLATE(T, poly_gcd_euclidean) (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"); 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 < 100 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, g; len = n_randint(state, 15) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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_euclidean) (g, a, b, ctx); TEMPLATE(T, poly_gcd_euclidean) (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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-gcd_euclidean_f.c000066400000000000000000000136111414523752600231240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd_euclidean_f...."); fflush(stdout); /* 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) f; TEMPLATE(T, poly_t) a, b, c, d; TEMPLATE(T, ctx_randtest_reducible) (ctx, state); 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, 60), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 60), 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"); 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); } FLINT_TEST_CLEANUP(state); /* 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; TEMPLATE(T, t) f1, f2; len = n_randint(state, 60) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, init) (f1, ctx); TEMPLATE(T, init) (f2, 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_euclidean_f) (f1, g, a, b, ctx); TEMPLATE(T, poly_gcd_euclidean_f) (f2, 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"); flint_printf("f1 = "), TEMPLATE(T, print) (f1, ctx), flint_printf("\n"); flint_printf("f2 = "), TEMPLATE(T, print) (f2, ctx), flint_printf("\n"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, clear) (f1, ctx); TEMPLATE(T, clear) (f2, 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; TEMPLATE(T, t) f1, f2; len = n_randint(state, 60) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, init) (f1, ctx); TEMPLATE(T, init) (f2, 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_euclidean_f) (f1, g, a, b, ctx); TEMPLATE(T, poly_gcd_euclidean_f) (f2, b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (g, b, ctx) && TEMPLATE(T, equal) (f1, f2, ctx)); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = "), TEMPLATE(T, poly_print_pretty) (a, "X", ctx), flint_printf(":wq\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"); flint_printf("f1 = "), TEMPLATE(T, print) (f1, ctx), flint_printf("\n"); flint_printf("f2 = "), TEMPLATE(T, print) (f2, ctx), flint_printf("\n"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, clear) (f1, ctx); TEMPLATE(T, clear) (f2, ctx); TEMPLATE(T, ctx_clear) (ctx); } flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-gcd_hgcd.c000066400000000000000000000112341414523752600215720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd_hgcd...."); fflush(stdout); /* Find coprime polys, multiply by another poly and check the GCD is that poly */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, c, g; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (c, ctx); TEMPLATE(T, poly_init) (g, ctx); do { TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 300), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 300), ctx); TEMPLATE(T, poly_gcd_hgcd) (g, a, b, ctx); } while (g->length != 1); do { TEMPLATE(T, poly_randtest) (c, state, n_randint(state, 300), ctx); } while (c->length < 2); 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_hgcd) (g, a, b, ctx); result = (TEMPLATE(T, poly_equal) (g, 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) (b, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (c, "x", ctx), flint_printf("\n\n"); TEMPLATE(T, poly_print_pretty) (g, "x", ctx), flint_printf("\n\n"); 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++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, g; TEMPLATE(T, ctx_randtest) (ctx, state); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 300), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 300), ctx); TEMPLATE(T, poly_gcd_hgcd) (g, a, b, ctx); TEMPLATE(T, poly_gcd_hgcd) (a, a, b, ctx); result = (TEMPLATE(T, poly_equal) (a, g, 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"); 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++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, g; TEMPLATE(T, ctx_randtest) (ctx, state); TEMPLATE(T, poly_init) (a, ctx); TEMPLATE(T, poly_init) (b, ctx); TEMPLATE(T, poly_init) (g, ctx); TEMPLATE(T, poly_randtest) (a, state, n_randint(state, 300), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 300), ctx); TEMPLATE(T, poly_gcd_hgcd) (g, a, b, ctx); TEMPLATE(T, poly_gcd_hgcd) (b, a, b, ctx); result = (TEMPLATE(T, poly_equal) (b, g, 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (g, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-get_str.c000066400000000000000000000023231414523752600215160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, len; char *str; TEMPLATE(T, poly_t) a; TEMPLATE(T, ctx_t) ctx; FLINT_TEST_INIT(state); flint_printf("get_str...."); fflush(stdout); TEMPLATE(T, ctx_randtest) (ctx, state); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-get_str_pretty.c000066400000000000000000000023621414523752600231300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, len; char *str; TEMPLATE(T, poly_t) a; TEMPLATE(T, ctx_t) ctx; FLINT_TEST_INIT(state); flint_printf("get_str_pretty...."); fflush(stdout); TEMPLATE(T, ctx_randtest) (ctx, state); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-hamming_weight.c000066400000000000000000000064101414523752600230370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("hamming_weight... "); fflush(stdout); /* 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_randtest) (ctx, state); 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); 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_randtest) (ctx, state); 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); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-hgcd.c000066400000000000000000000150701414523752600207570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "ulong_extras.h" #include "mpn_extras.h" #define __mul(C, lenC, A, lenA, B, lenB) \ do { \ if ((lenA) != 0 && (lenB) != 0) \ { \ if ((lenA) >= (lenB)) \ _TEMPLATE(T, poly_mul)((C), (A), (lenA), (B), (lenB), ctx); \ else \ _TEMPLATE(T, poly_mul)((C), (B), (lenB), (A), (lenA), ctx); \ (lenC) = (lenA) + (lenB) - 1; \ } \ else \ { \ (lenC) = 0; \ } \ } while (0) #define __swap(u, l, v, m) \ do { \ { TEMPLATE(T, struct)* _; _ = (u), (u) = (v), (v) = _;} \ { slong _; _ = (l), (l) = (m), (m) = _;} \ } while (0) int main(void) { int i, result; flint_rand_t state; flint_randinit(state); flint_printf("hgcd...."); fflush(stdout); /* Find coprime polys, multiply by another poly and check the GCD is that poly */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, c, d, c1, d1, s, t; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, struct) * M[4]; slong lenM[4]; slong sgnM; TEMPLATE(T, ctx_randtest) (ctx, state); 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) (c1, ctx); TEMPLATE(T, poly_init) (d1, ctx); TEMPLATE(T, poly_init) (s, ctx); TEMPLATE(T, poly_init) (t, ctx); do { TEMPLATE(T, poly_randtest_not_zero) (a, state, n_randint(state, 800) + 1, ctx); TEMPLATE(T, poly_randtest_not_zero) (b, state, n_randint(state, 800) + 1, ctx); } while (a->length == b->length); if (a->length < b->length) TEMPLATE(T, poly_swap) (a, b, ctx); M[0] = _TEMPLATE(T, vec_init) (a->length, ctx); M[1] = _TEMPLATE(T, vec_init) (a->length, ctx); M[2] = _TEMPLATE(T, vec_init) (a->length, ctx); M[3] = _TEMPLATE(T, vec_init) (a->length, ctx); TEMPLATE(T, poly_fit_length) (c, a->length, ctx); TEMPLATE(T, poly_fit_length) (d, b->length, ctx); sgnM = _TEMPLATE(T, poly_hgcd) (M, lenM, c->coeffs, &(c->length), d->coeffs, &(d->length), a->coeffs, a->length, b->coeffs, b->length, ctx); TEMPLATE(T, poly_fit_length) (s, 2 * a->length, ctx); TEMPLATE(T, poly_fit_length) (t, 2 * a->length, ctx); /* [c1,d1] := sgnM * M^{-1} [a,b] */ { __swap(M[0], lenM[0], M[3], lenM[3]); _TEMPLATE(T, vec_neg) (M[1], M[1], lenM[1], ctx); _TEMPLATE(T, 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); TEMPLATE(T, 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); TEMPLATE(T, poly_add) (d1, s, t, ctx); } if (sgnM < 0) { TEMPLATE(T, poly_neg) (c1, c1, ctx); TEMPLATE(T, poly_neg) (d1, d1, ctx); } result = (TEMPLATE(T, poly_equal) (c, c1, ctx) && TEMPLATE(T, poly_equal) (d, d1, 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("c1 = "), TEMPLATE(T, poly_print_pretty) (c1, "x", ctx), flint_printf("\n\n"); flint_printf("d1 = "), TEMPLATE(T, poly_print_pretty) (d1, "x", ctx), flint_printf("\n\n"); 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) (c1, ctx); TEMPLATE(T, poly_clear) (d1, ctx); TEMPLATE(T, poly_clear) (s, ctx); TEMPLATE(T, poly_clear) (t, ctx); _TEMPLATE(T, vec_clear) (M[0], a->length, ctx); _TEMPLATE(T, vec_clear) (M[1], a->length, ctx); _TEMPLATE(T, vec_clear) (M[2], a->length, ctx); _TEMPLATE(T, vec_clear) (M[3], a->length, ctx); TEMPLATE(T, ctx_clear) (ctx); } flint_randclear(state); flint_printf("PASS\n"); return 0; } #undef __mul #undef __swap #endif flint2-2.8.4/fq_poly_templates/test/t-inflate.c000066400000000000000000000053631414523752600215000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("inflate...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-inv_series_newton.c000066400000000000000000000043731414523752600236160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("inv_series_newton...."); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-make_monic.c000066400000000000000000000054311414523752600221540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("make_monic...."); fflush(stdout); /* test aliasing */ for (i = 0; i < 100 * 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_randtest) (ctx, state); 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_randtest) (ctx, state); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-mul.c000066400000000000000000000177031414523752600206540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul... "); fflush(stdout); /* Check aliasing: a = a * b */ 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_randtest) (ctx, state); 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"); 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 < 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-mul_KS.c000066400000000000000000000177471414523752600212610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_KS... "); fflush(stdout); /* Check aliasing: a = a * b */ 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_randtest) (ctx, state); 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"); 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 < 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-mul_classical.c000066400000000000000000000200421414523752600226600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_classical... "); fflush(stdout); /* Check aliasing: a = a * b */ 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_randtest) (ctx, state); 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"); 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 < 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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 < 2000; 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-mul_reorder.c000066400000000000000000000201751414523752600223730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_reorder... "); fflush(stdout); /* Check aliasing: a = a * b */ 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_randtest) (ctx, state); 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"); 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 < 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-mul_univariate.c000066400000000000000000000201071414523752600230730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_univariate... "); fflush(stdout); /* Check aliasing: a = a * b */ 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_randtest) (ctx, state); 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"); 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 < 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-mulhigh.c000066400000000000000000000040471414523752600215110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulhigh...."); fflush(stdout); /* Compare with left truncated product of a and b */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; slong j, n; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-mulhigh_classical.c000066400000000000000000000124221414523752600235230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulhigh_classical...."); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; slong j, start; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c; slong j, start; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; slong j, start; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-mullow.c000066400000000000000000000044561414523752600213770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow... "); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-mullow_KS.c000066400000000000000000000044641414523752600217730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow_KS... "); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-mullow_classical.c000066400000000000000000000044771414523752600234200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow_classical... "); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-mullow_univariate.c000066400000000000000000000045041414523752600236200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow_univariate... "); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-mulmod.c000066400000000000000000000164341414523752600213540ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2011, 2010 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulmod...."); fflush(stdout); /* Check aliasing of res and a */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, res, f; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, f, res; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, f, res; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, res1, res2, t, f; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-mulmod_preinv.c000066400000000000000000000264431414523752600227400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulmod_preinv...."); fflush(stdout); /* Aliasing res and a */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, res, t, f, finv; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, res, t, f, finv; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, res, t, f, finv; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, res, t, f, finv; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-neg.c000066400000000000000000000074661414523752600206350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg... "); fflush(stdout); /* Check aliasing: a = -a */ 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_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, ctx_clear) (ctx); } /* Check that -(-a) == a */ 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_randtest) (ctx, state); 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) (b, b, ctx); result = (TEMPLATE(T, poly_equal) (a, b, ctx)); if (!result) { flint_printf("FAIL (-(-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"); 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_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-pow.c000066400000000000000000000073431414523752600206630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow... "); fflush(stdout); /* Check aliasing */ for (i = 0; i < 20 * 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_randtest) (ctx, state); 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); 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_randtest) (ctx, state); 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); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-pow_trunc.c000066400000000000000000000070171414523752600220740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow_trunc...."); fflush(stdout); /* Check powering against naive method */ for (i = 0; i < 1000 * 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_randtest) (ctx, state); 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"); 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 < 1000 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, c; TEMPLATE(T, ctx_t) ctx; slong e, trunc; TEMPLATE(T, ctx_randtest) (ctx, state); 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_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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-pow_trunc_binexp.c000066400000000000000000000070531414523752600234410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow_trunc_binexp...."); fflush(stdout); /* Check powering against naive method */ for (i = 0; i < 1000 * 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_randtest) (ctx, state); 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"); 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 < 1000 * flint_test_multiplier(); i++) { TEMPLATE(T, poly_t) a, b, c; TEMPLATE(T, ctx_t) ctx; slong e, trunc; TEMPLATE(T, ctx_randtest) (ctx, state); 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_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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-powmod_fmpz_binexp.c000066400000000000000000000176401414523752600237650ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_fmpz_binexp...."); fflush(stdout); /* Aliasing of res and a */ for (i = 0; i < 5 * 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_randtest) (ctx, state); 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) (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("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"); 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 < 5 * 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_randtest) (ctx, state); 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) (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("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"); 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); } /* No aliasing */ for (i = 0; i < 5 * 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_randtest) (ctx, state); 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, 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("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"); 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 < 5 * 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_randtest) (ctx, state); 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); 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("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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-powmod_fmpz_binexp_preinv.c000066400000000000000000000222241414523752600253420ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_fmpz_binexp_preinv..."); fflush(stdout); /* Aliasing of res and a */ for (i = 0; i < 2.5 * 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_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 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"); 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 < 2.5 * 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_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 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"); 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); } /* No aliasing */ for (i = 0; i < 5 * 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_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 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"); 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 < 5 * 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_randtest) (ctx, state); 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); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-powmod_fmpz_sliding_preinv.c000066400000000000000000000236241414523752600255130ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_fmpz_sliding_preinv..."); fflush(stdout); /* Aliasing of res and a */ for (i = 0; i < 2.5 * 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_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 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"); 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 < 2.5 * 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_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 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"); 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); } /* No aliasing */ for (i = 0; i < 5 * 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_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 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_sliding_preinv) (res2, a, expz, 0, f, finv, ctx); /* TODO: Fix */ 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"); 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 < 5 * 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_randtest) (ctx, state); 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); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-powmod_ui_binexp.c000066400000000000000000000171741414523752600234300ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_ui_binexp...."); fflush(stdout); /* Aliasing of res and a */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, t, f; ulong exp; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, t, f; ulong exp; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 5 * 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_randtest) (ctx, state); 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, 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_zero) (res2, ctx); TEMPLATE(T, poly_one) (res2, ctx); for (j = 1; j <= exp; j++) TEMPLATE(T, poly_mulmod) (res2, res2, a, 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"); 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 < 5 * 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_randtest) (ctx, state); 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, 20), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 20) + 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("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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-powmod_ui_binexp_preinv.c000066400000000000000000000213141414523752600250020ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_ui_binexp_preinv...."); fflush(stdout); /* Aliasing of res and a */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, t, f, finv; ulong exp; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 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"); 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 < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, res1, t, f, finv; ulong exp; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 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"); 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 < 100 * 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_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 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_zero) (res2, ctx); TEMPLATE(T, poly_one) (res2, ctx); for (j = 1; j <= exp; j++) TEMPLATE(T, poly_mulmod) (res2, res2, a, 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"); 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 < 5 * 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_randtest) (ctx, state); 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, 50), ctx); TEMPLATE(T, poly_randtest_not_zero) (f, state, n_randint(state, 50) + 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-powmod_x_fmpz_preinv.c000066400000000000000000000103431414523752600243230ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_x_fmpz_preinv..."); fflush(stdout); /* Aliasing of res and f */ for (i = 0; i < 2.5 * 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_randtest) (ctx, state); 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, 50) + 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"); 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 < 10 * 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_randtest) (ctx, state); 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, 50) + 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-randtest_irreducible.c000066400000000000000000000025531414523752600242510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("randtest_irreducible...."); fflush(stdout); for (iter = 0; iter < 10 * flint_test_multiplier(); iter++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) poly; slong length; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (poly, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-scalar_addmul_fq.c000066400000000000000000000076731414523752600233450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_addmul_fq... "); fflush(stdout); /* Check aliasing */ for (i = 0; i < 200 * 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-scalar_div_fq.c000066400000000000000000000066621414523752600226560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_div_fq... "); fflush(stdout); /* Check aliasing */ 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-scalar_mul_fq.c000066400000000000000000000040351414523752600226610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_fq... "); fflush(stdout); /* Check aliasing */ 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_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, clear) (x, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-scalar_submul_fq.c000066400000000000000000000076731414523752600234060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_submul_fq... "); fflush(stdout); /* Check aliasing */ for (i = 0; i < 200 * 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-set_nmod_poly.c000066400000000000000000000041451414523752600227260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_nmod_poly... "); fflush(stdout); /* 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_randtest)(ctx, state); TEMPLATE(T, init)(r, ctx); TEMPLATE(T, init)(s, ctx); TEMPLATE(T, poly_init)(a, ctx); nmod_poly_init(b, fmpz_get_ui(TEMPLATE(T, ctx_prime)(ctx))); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-set_trunc.c000066400000000000000000000047771414523752600220740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_trunc... "); fflush(stdout); /* 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_randtest) (ctx, state); 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, 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_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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-shift_left_right.c000066400000000000000000000113071414523752600233750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("shift_left/right... "); fflush(stdout); /* Check aliasing for left shift */ 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_randtest) (ctx, state); 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, 100); 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"); 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 < 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_randtest) (ctx, state); 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, 100); 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"); 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_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-sqr.c000066400000000000000000000110031414523752600206470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqr... "); fflush(stdout); /* Check aliasing: a = a * a */ for (i = 0; i < 200 * 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-sqr_KS.c000066400000000000000000000110221414523752600212450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqr_KS... "); fflush(stdout); /* Check aliasing: a = a * a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 50) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; len = n_randint(state, 50) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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, 50) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-sqr_classical.c000066400000000000000000000110651414523752600226750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqr_classical... "); fflush(stdout); /* Check aliasing: a = a * a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 50) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; len = n_randint(state, 50) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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, 50) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-sqr_reorder.c000066400000000000000000000110531414523752600223760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqr_reorder... "); fflush(stdout); /* Check aliasing: a = a * a */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, c; len = n_randint(state, 50) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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 < 200 * flint_test_multiplier(); i++) { slong len; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, c, d; len = n_randint(state, 50) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); 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, 50) + 1; TEMPLATE(T, ctx_randtest) (ctx, state); 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"); abort(); } TEMPLATE(T, poly_clear) (a, ctx); TEMPLATE(T, poly_clear) (b, ctx); TEMPLATE(T, poly_clear) (c, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-sub.c000066400000000000000000000135511414523752600206450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub... "); fflush(stdout); /* Check aliasing: a = a - b */ 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_randtest) (ctx, state); 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"); 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 < 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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 < 200 * 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-sub_series.c000066400000000000000000000142031414523752600222120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub_series... "); fflush(stdout); /* Check aliasing: a = a - b */ for (i = 0; i < 100 * 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_randtest) (ctx, state); 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"); 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 < 100 * 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_randtest) (ctx, state); 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"); 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 < 100 * 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_poly_templates/test/t-xgcd_euclidean.c000066400000000000000000000423511414523752600230120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("xgcd_euclidean...."); fflush(stdout); /* Generic case, most likely co-prime arguments ***************************** */ /* Compare with result from GCD and check correctness */ for (i = 0; i < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, d, g, s, t, v, w; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_gcd_euclidean) (d, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean) (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"); 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_randtest) (ctx, state); 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) (d, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean) (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"); 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 < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, g, s, t, v, w; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_xgcd_euclidean) (g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean) (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"); 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 < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, g, s, t, v, w; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_xgcd_euclidean) (g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean) (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"); 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 < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, d, g, s, t, w; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_xgcd_euclidean) (g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean) (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"); 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 < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, d, g, s, t, w; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_xgcd_euclidean) (g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean) (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"); 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 < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, d, g, s, t, w; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_xgcd_euclidean) (g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean) (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"); 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 < 5 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, poly_t) a, b, d, g, s, t, w; TEMPLATE(T, ctx_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), ctx); TEMPLATE(T, poly_xgcd_euclidean) (g, s, t, a, b, ctx); TEMPLATE(T, poly_xgcd_euclidean) (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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/test/t-xgcd_euclidean_f.c000066400000000000000000000473061414523752600233240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("xgcd_euclidean_f...."); fflush(stdout); /* Generic case, most likely co-prime arguments ***************************** */ /* Compare with result from GCD and check correctness */ for (i = 0; i < 5 * 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_randtest_reducible) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), 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"); 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_randtest_reducible) (ctx, state); 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"); 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 < 5 * 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_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), 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"); 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 < 5 * 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_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), 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"); 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 < 5 * 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_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), 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"); 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 < 5 * 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_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), 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"); 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 < 5 * 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_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), 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"); 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 < 5 * 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_randtest) (ctx, state); 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, 100), ctx); TEMPLATE(T, poly_randtest) (b, state, n_randint(state, 100), 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_poly_templates/tree.c000066400000000000000000000065411414523752600175740ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/truncate.c000066400000000000000000000015441414523752600204600ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_poly_templates/xgcd_euclidean.c000066400000000000000000000202151414523752600215650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" slong _TEMPLATE(T, poly_xgcd_euclidean) (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, t) invB, const TEMPLATE(T, ctx_t) ctx) { _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, set) (G + 0, B + 0, ctx); TEMPLATE(T, one) (T + 0, ctx); return 1; } else { TEMPLATE(T, struct) * Q, *R; slong lenQ, lenR; Q = _TEMPLATE(T, vec_init) (2 * lenA, ctx); R = Q + lenA; _TEMPLATE(T, poly_divrem) (Q, R, A, lenA, B, lenB, invB, ctx); 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, t) inv; TEMPLATE(T, struct) * D, *U, *V1, *V3, *W; slong lenD, lenU, lenV1, lenV3, lenW; TEMPLATE(T, init) (inv, ctx); 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, inv) (inv, V3 + (lenV3 - 1), ctx); _TEMPLATE(T, poly_divrem) (Q, R, D, lenD, V3, lenV3, inv, ctx); 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) (T, W, Q, lenQ, B, lenB, invB, ctx); } _TEMPLATE(T, vec_clear) (W, FLINT_MAX(5 * lenB, lenA + lenB), ctx); _TEMPLATE(T, vec_clear) (Q, 2 * lenA, ctx); TEMPLATE(T, clear) (inv, ctx); return lenD; } } } void TEMPLATE(T, poly_xgcd_euclidean) (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) (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_euclidean) (g, s, t, A->coeffs, lenA, B->coeffs, lenB, inv, 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 flint2-2.8.4/fq_poly_templates/xgcd_euclidean_f.c000066400000000000000000000222061414523752600220740ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_templates.h000066400000000000000000000034671414523752600156030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" FLINT_DLL void TEMPLATE(T, gcdinv)(TEMPLATE(T, t) rop, TEMPLATE(T, t) inv, const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int TEMPLATE(T, is_invertible)(const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int TEMPLATE(T, is_invertible_f)(TEMPLATE(T, t) rop, const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void TEMPLATE(T, div)(TEMPLATE(T, t) rop, const TEMPLATE(T, t) op1, const TEMPLATE(T, t) op2, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL int TEMPLATE(T, multiplicative_order)(fmpz_t ord, const TEMPLATE(T, t) op, const TEMPLATE(T, ctx_t) ctx); #ifdef B FLINT_DLL void TEMPLATE4(T, get, B, mat)(TEMPLATE(B, mat_t) col, const TEMPLATE(T, t) a, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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) { fmpz_t tmp; int ret; fmpz_init(tmp); ret = TEMPLATE(T, multiplicative_order)(tmp, op, ctx) == 1; fmpz_clear(tmp); return ret; } #endif flint2-2.8.4/fq_templates/000077500000000000000000000000001414523752600154205ustar00rootroot00000000000000flint2-2.8.4/fq_templates/div.c000066400000000000000000000013441414523752600163500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_templates/is_invertible.c000066400000000000000000000011051414523752600204170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_templates/is_invertible_f.c000066400000000000000000000013431414523752600207300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_templates/is_square.c000066400000000000000000000021261414523752600175600ustar00rootroot00000000000000/* 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 2.1 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 (TEMPLATE(T, is_zero)(op, ctx) || TEMPLATE(T, is_one)(op, ctx) || fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) == 0) { 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 flint2-2.8.4/fq_templates/multiplicative_order.c000066400000000000000000000030221414523752600220070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int TEMPLATE(T, multiplicative_order)(fmpz_t 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 (TEMPLATE(T, is_zero)(op, ctx)) { fmpz_set_ui(ord, 0); return 0; } fmpz_init(tmp); 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++) { fmpz_set(tmp, ord); for (j = ord_fact->exp[i]; j > 0; j--) { fmpz_cdiv_q(tmp, tmp, ord_fact->p + i); TEMPLATE(T, pow)(one, op, tmp, ctx); if (!TEMPLATE(T, is_one)(one, ctx)) break; is_primitive = -1; } if (j > 0) fmpz_mul(ord, tmp, ord_fact->p + i); else fmpz_set(ord, tmp); } fmpz_clear(tmp); fmpz_factor_clear(ord_fact); TEMPLATE(T, clear)(one, ctx); return is_primitive; } #endif flint2-2.8.4/fq_templates/sqrt.c000066400000000000000000000056151414523752600165640ustar00rootroot00000000000000/* 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 2.1 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); else if (fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) == 0) 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 flint2-2.8.4/fq_templates/test/000077500000000000000000000000001414523752600163775ustar00rootroot00000000000000flint2-2.8.4/fq_templates/test/t-add.c000066400000000000000000000147021414523752600175400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add... "); fflush(stdout); /* 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_randtest)(ctx, state); 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, add)(c, a, b, ctx); TEMPLATE(T, add)(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"); 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_randtest)(ctx, state); 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, add)(c, a, b, ctx); TEMPLATE(T, add)(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"); 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_randtest)(ctx, state); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, add)(c, a, a, ctx); TEMPLATE(T, add)(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"); 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_randtest)(ctx, state); 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, add)(c1, a, b, ctx); TEMPLATE(T, add)(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"); 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_randtest)(ctx, state); 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, add)(lhs, a, b, ctx); TEMPLATE(T, add)(lhs, lhs, c, ctx); TEMPLATE(T, add)(rhs, b, c, ctx); TEMPLATE(T, add)(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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-assign.c000066400000000000000000000020141414523752600202650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("assignments... "); fflush(stdout); /* Check that gen does not segfault */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) x; TEMPLATE(T, ctx_randtest)(ctx, state); TEMPLATE(T, init)(x, ctx); TEMPLATE(T, gen)(x, ctx); TEMPLATE(T, clear)(x, ctx); TEMPLATE(T, ctx_clear)(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-ctx_init.c000066400000000000000000000056021414523752600206300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "fmpz_mod_poly.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, k, result; FLINT_TEST_INIT(state); flint_printf("ctx_init... "); fflush(stdout); for (i = 0; i < 3 * flint_test_multiplier(); i++) { fmpz_t p; slong d; TEMPLATE(T, ctx_t) ctx; fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, FLINT_MIN(FLINT_BITS - 1, 50)), 1)); d = n_randint(state, 20) + 1; TEMPLATE(T, ctx_init)(ctx, p, d, "a"); TEMPLATE(T, ctx_clear)(ctx); } for (i = 0; i < 3 * flint_test_multiplier(); i++) { fmpz_t p; slong d; TEMPLATE(T, ctx_t) ctx_conway, ctx_mod; TEMPLATE(T, t) a, b, lhs, rhs; fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, 3), 1)); d = n_randint(state, 10) + 1; TEMPLATE(T, ctx_init_conway)(ctx_conway, p, d, "a"); TEMPLATE(T, ctx_init_modulus)(ctx_mod, ctx_conway->modulus, "a"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-div.c000066400000000000000000000035111414523752600175660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div... "); fflush(stdout); /* Check aliasing: a = a * b */ for (i = 0; i < 20 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, c, d; TEMPLATE(T, ctx_randtest)(ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-frobenius.c000066400000000000000000000165061414523752600210100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("frobenius... "); fflush(stdout); /* 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_randtest)(ctx, state); 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); 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_randtest)(ctx, state); 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); fmpz_pow_ui(t, TEMPLATE(T, ctx_prime)(ctx), e); 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); 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_randtest)(ctx, state); 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); 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_randtest)(ctx, state); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-inv.c000066400000000000000000000055721414523752600176110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("inv... "); fflush(stdout); /* 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_randtest)(ctx, state); 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); 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_randtest)(ctx, state); 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"); abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(c, ctx); TEMPLATE(T, ctx_clear)(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-is_invertible.c000066400000000000000000000024041414523752600216420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_invertible... "); fflush(stdout); for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a; TEMPLATE(T, ctx_randtest)(ctx, state); 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); abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, ctx_clear)(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-is_invertible_f.c000066400000000000000000000037561414523752600221620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_invertible_f...."); fflush(stdout); /* 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 (i = 0; i < 50 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, ainv, f, g; TEMPLATE(T, ctx_randtest_reducible)(ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_templates/test/t-is_primitive.c000066400000000000000000000031171414523752600215110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_primitive... "); fflush(stdout); /* 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_randtest)(ctx, state); 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); abort(); } fmpz_clear(ord); fmpz_clear(field_ord); TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, ctx_clear)(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-is_square.c000066400000000000000000000053301414523752600210000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_square... "); fflush(stdout); /* Check is_square(a^2) == 1 */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b; TEMPLATE(T, ctx_randtest)(ctx, state); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); 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"); abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Check non-squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, b, z; TEMPLATE(T, ctx_randtest)(ctx, state); if (fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) != 0) { TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); 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"); abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, clear)(z, ctx); TEMPLATE(T, ctx_clear)(ctx); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-mul.c000066400000000000000000000147341414523752600176120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul... "); fflush(stdout); /* 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_randtest)(ctx, state); 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"); 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_randtest)(ctx, state); 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"); 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_randtest)(ctx, state); 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"); 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_randtest)(ctx, state); 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"); 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_randtest)(ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-mul_fmpz.c000066400000000000000000000056611414523752600206450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "fmpz.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_fmpz...."); fflush(stdout); /* 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_randtest)(ctx, state); 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"); 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_randtest)(ctx, state); 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"); abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(c, ctx); fmpz_poly_clear(b); fmpz_clear(x); TEMPLATE(T, ctx_clear)(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_templates/test/t-mul_si.c000066400000000000000000000053501414523752600202770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "fmpz.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_si...."); fflush(stdout); /* 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_randtest)(ctx, state); 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); 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_randtest)(ctx, state); 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); abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(c, ctx); fmpz_poly_clear(b); TEMPLATE(T, ctx_clear)(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_templates/test/t-mul_ui.c000066400000000000000000000053501414523752600203010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include #include "flint.h" #include "fmpz.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_ui...."); fflush(stdout); /* 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_randtest)(ctx, state); 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); 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_randtest)(ctx, state); 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); abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(c, ctx); fmpz_poly_clear(b); TEMPLATE(T, ctx_clear)(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_templates/test/t-multiplicative_order.c000066400000000000000000000057501414523752600232410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("multiplicative_order... "); fflush(stdout); /* Test that the computed multiplicative order is a multiple of the real one */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) a, tmp; fmpz_t ord; TEMPLATE(T, ctx_randtest)(ctx, state); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(tmp, ctx); TEMPLATE(T, randtest)(a, state, ctx); fmpz_init(ord); result = TEMPLATE(T, multiplicative_order)(ord, a, ctx); TEMPLATE(T, pow)(tmp, a, ord, ctx); if (result && !TEMPLATE(T, is_one)(tmp, 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); abort(); } fmpz_clear(ord); TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(tmp, ctx); TEMPLATE(T, ctx_clear)(ctx); } /* Test that the computed multiplicative order is coherent with powering by p-1 */ for (i = 0; i < 10 * flint_test_multiplier(); i++) { TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) X, a; fmpz_t ord, size, pm1; TEMPLATE(T, ctx_randtest)(ctx, state); TEMPLATE(T, init)(X, ctx); TEMPLATE(T, init)(a, ctx); fmpz_init(ord); fmpz_init(size); fmpz_init(pm1); TEMPLATE(T, gen)(X, ctx); if (TEMPLATE(T, is_primitive)(X, ctx)) { 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); 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); abort(); } } fmpz_clear(pm1); fmpz_clear(ord); fmpz_clear(size); TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(X, ctx); TEMPLATE(T, ctx_clear)(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-neg.c000066400000000000000000000060541414523752600175620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg... "); fflush(stdout); /* 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_randtest)(ctx, state); 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"); 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_randtest)(ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-norm.c000066400000000000000000000047741414523752600177730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" #include "long_extras.h" #include "fmpz_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("norm... "); fflush(stdout); /* 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_randtest)(ctx, state); 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"); } 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-pow.c000066400000000000000000000061521414523752600176150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow... "); fflush(stdout); /* 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_randtest)(ctx, state); 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"); 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_randtest)(ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-pth_root.c000066400000000000000000000032071414523752600206440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pth_root... "); fflush(stdout); /* 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; TEMPLATE(T, ctx_randtest)(ctx, state); TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, pth_root)(b, a, ctx); TEMPLATE(T, pow)(b, b, TEMPLATE(T, ctx_prime)(ctx), 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"); abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(b, ctx); TEMPLATE(T, ctx_clear)(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-sqr.c000066400000000000000000000055721414523752600176220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqr... "); fflush(stdout); /* 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_randtest)(ctx, state); 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"); 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_randtest)(ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-sqrt.c000066400000000000000000000072061414523752600200020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int j, i, result; TEMPLATE(T, ctx_t) ctx; FLINT_TEST_INIT(state); flint_printf("sqrt... "); fflush(stdout); for (j = 0; j < 10; j++) { TEMPLATE(T, ctx_randtest)(ctx, state); /* Check aliasing: a = a * a */ for (i = 0; i < 200; i++) { TEMPLATE(T, t) a, c; TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(c, ctx); 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"); abort(); } TEMPLATE(T, clear)(a, ctx); TEMPLATE(T, clear)(c, ctx); } /* Check sqrt(a^2) = a and that x*a^2 is not a square */ for (i = 0; i < 200; i++) { int r; TEMPLATE(T, t) a, b, c, d, x; TEMPLATE(T, init)(a, ctx); TEMPLATE(T, init)(b, ctx); TEMPLATE(T, init)(c, ctx); TEMPLATE(T, init)(d, ctx); TEMPLATE(T, init)(x, ctx); TEMPLATE(T, randtest)(a, state, ctx); TEMPLATE(T, sqr)(b, a, ctx); r = TEMPLATE(T, sqrt)(c, b, ctx); TEMPLATE(T, sqr)(d, c, ctx); result = (r && TEMPLATE(T, equal)(d, b, ctx)); if (!result) { flint_printf("FAIL (sqrt(a^2) == a):\n\n"); flint_printf("r = %d\n", r); 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"); abort(); } if (ctx->is_conway && fmpz_cmp_ui(TEMPLATE(T, ctx_prime)(ctx), 2) != 0 && !TEMPLATE(T, is_zero)(b, ctx)) { TEMPLATE(T, gen)(x, ctx); TEMPLATE(T, mul)(b, b, x, ctx); r = TEMPLATE(T, sqrt)(c, b, ctx); result = !r; /* 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-sub.c000066400000000000000000000147441414523752600176070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub... "); fflush(stdout); /* 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_randtest)(ctx, state); 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"); 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_randtest)(ctx, state); 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"); 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_randtest)(ctx, state); 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"); 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_randtest)(ctx, state); 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"); 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_randtest)(ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_templates/test/t-trace.c000066400000000000000000000047101414523752600201040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("trace... "); fflush(stdout); /* Compare with sum 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_randtest)(ctx, state); 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 (j = 0; j < TEMPLATE(T, ctx_degree)(ctx); j++) { TEMPLATE(T, frobenius)(c, a, j, 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 (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"); } 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } #endif flint2-2.8.4/fq_vec.h000066400000000000000000000026501414523752600143530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #define FQ_VEC_INLINE FLINT_DLL #else #define FQ_VEC_TEMPLATES_INLINE static __inline__ #define FQ_VEC_INLINE static __inline__ #endif #include "fq.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 flint2-2.8.4/fq_vec/000077500000000000000000000000001414523752600141775ustar00rootroot00000000000000flint2-2.8.4/fq_vec/add.c000066400000000000000000000010001414523752600150620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/add.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/clear.c000066400000000000000000000010021414523752600154220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/dot.c000066400000000000000000000015311414523752600151310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_vec/equal.c000066400000000000000000000010021414523752600154430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/equal.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/fprint.c000066400000000000000000000010031414523752600156370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/fprint.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/init.c000066400000000000000000000010011414523752600152760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/init.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/inlines.c000066400000000000000000000010541414523752600160040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_VEC_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "fq_vec.h" flint2-2.8.4/fq_vec/is_zero.c000066400000000000000000000010041414523752600160100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/is_zero.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/neg.c000066400000000000000000000010001414523752600151030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/neg.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/randtest.c000066400000000000000000000010051414523752600161630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/randtest.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/scalar_addmul_fq.c000066400000000000000000000010151414523752600176210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/scalar_addmul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/scalar_mul_fq.c000066400000000000000000000010121414523752600171450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/scalar_mul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/scalar_submul_fq.c000066400000000000000000000010151414523752600176620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/scalar_submul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/set.c000066400000000000000000000010001414523752600151250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/set.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/sub.c000066400000000000000000000010001414523752600151230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/sub.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/swap.c000066400000000000000000000010011414523752600153050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/swap.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec/test/000077500000000000000000000000001414523752600151565ustar00rootroot00000000000000flint2-2.8.4/fq_vec/test/t-add.c000066400000000000000000000010071414523752600163110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_vec/test/t-is_zero.c000066400000000000000000000010131414523752600172300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_vec/test/t-neg.c000066400000000000000000000010071414523752600163320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_vec/test/t-sub.c000066400000000000000000000010071414523752600163520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_vec/test/t-swap.c000066400000000000000000000010101414523752600165250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_vec/test/t-zero.c000066400000000000000000000010101414523752600165320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_vec/zero.c000066400000000000000000000010011414523752600153120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_vec.h" #ifdef T #undef T #endif #define T fq #define CAP_T FQ #include "fq_vec_templates/zero.c" #undef CAP_T #undef T flint2-2.8.4/fq_vec_templates.h000066400000000000000000000120431414523752600164260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "flint.h" #include "templates.h" #include "ulong_extras.h" #ifdef __cplusplus extern "C" { #endif /* Memory management *******************************************************/ FLINT_DLL TEMPLATE(T, struct) * _TEMPLATE(T, vec_init)(slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, vec_clear)(TEMPLATE(T, struct) * vec, slong len, const TEMPLATE(T, ctx_t) ctx); /* Randomisation ***********************************************************/ FLINT_DLL 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 ********************************************************/ FLINT_DLL int _TEMPLATE(T, vec_fprint)(FILE * file, const TEMPLATE(T, struct) * vec, slong len, const TEMPLATE(T, ctx_t) ctx); FQ_VEC_TEMPLATES_INLINE 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); } /* Conversions *************************************************************/ /* Assignment and basic manipulation ***************************************/ FLINT_DLL void _TEMPLATE(T, vec_set)(TEMPLATE(T, struct) * v, const TEMPLATE(T, struct) * f, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, vec_swap)(TEMPLATE(T, struct) * vec1, TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, vec_zero)(TEMPLATE(T, struct) * v, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL void _TEMPLATE(T, vec_neg)(TEMPLATE(T, struct) * vec1, const TEMPLATE(T, struct) * vec2, slong len2, const TEMPLATE(T, ctx_t) ctx); /* Comparison **************************************************************/ FLINT_DLL int _TEMPLATE(T, vec_is_zero)(const TEMPLATE(T, struct) * vec, slong len, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL 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 ****************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /* ****************************************************************************/ FLINT_DLL 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 flint2-2.8.4/fq_vec_templates/000077500000000000000000000000001414523752600162555ustar00rootroot00000000000000flint2-2.8.4/fq_vec_templates/add.c000066400000000000000000000014411414523752600171510ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_vec_templates/clear.c000066400000000000000000000012631414523752600175110ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_vec_templates/dot.c000066400000000000000000000016441414523752600172140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_vec_templates/equal.c000066400000000000000000000015121414523752600175270ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_vec_templates/fprint.c000066400000000000000000000027361414523752600177330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include /* 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, "%li", 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; } #endif flint2-2.8.4/fq_vec_templates/init.c000066400000000000000000000012671414523752600173720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_vec_templates/is_zero.c000066400000000000000000000013311414523752600200710ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_vec_templates/neg.c000066400000000000000000000013401414523752600171700ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_vec_templates/randtest.c000066400000000000000000000021751414523752600202520ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_vec_templates/scalar_addmul_fq.c000066400000000000000000000017011414523752600217010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_vec_templates/scalar_mul_fq.c000066400000000000000000000014531414523752600212340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_vec_templates/scalar_submul_fq.c000066400000000000000000000017011414523752600217420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_vec_templates/set.c000066400000000000000000000013401414523752600172120ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_vec_templates/sub.c000066400000000000000000000014411414523752600172120ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_vec_templates/swap.c000066400000000000000000000013141414523752600173720ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_vec_templates/test/000077500000000000000000000000001414523752600172345ustar00rootroot00000000000000flint2-2.8.4/fq_vec_templates/test/t-add.c000066400000000000000000000055301414523752600203740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); printf("add...."); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_vec_templates/test/t-is_zero.c000066400000000000000000000040321414523752600213120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); printf("is_zero...."); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_vec_templates/test/t-neg.c000066400000000000000000000047371414523752600204250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include int main(void) { int i, result; FLINT_TEST_INIT(state); printf("neg...."); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); _TEMPLATE(T, vec_clear) (b, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_vec_templates/test/t-sub.c000066400000000000000000000077561414523752600204510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); printf("sub...."); fflush(stdout); /* 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_vec_templates/test/t-swap.c000066400000000000000000000034721414523752600206210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); printf("swap...."); fflush(stdout); 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_randtest) (ctx, state); 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_vec_templates/test/t-zero.c000066400000000000000000000026411414523752600206230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifdef T #include "templates.h" #include #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); printf("zero...."); fflush(stdout); /* 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_randtest) (ctx, state); 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"); abort(); } _TEMPLATE(T, vec_clear) (a, len, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } #endif flint2-2.8.4/fq_vec_templates/zero.c000066400000000000000000000012341414523752600174000ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_zech.h000066400000000000000000000251401414523752600145260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL /* #define FQ_TEMPLATES_INLINE FLINT_DLL */ #else #define FQ_ZECH_INLINE static __inline__ /* #define FQ_TEMPLATES_INLINE static __inline__ */ #endif #include "fq_nmod.h" /* Data types and context ****************************************************/ #ifdef __cplusplus extern "C" { #endif typedef struct { mp_limb_t value; } fq_zech_struct; typedef fq_zech_struct fq_zech_t[1]; typedef struct { mp_limb_t qm1; /* q - 1 */ mp_limb_t qm1o2; /* (q - 1) / 2 or 1 when p == 2 */ mp_limb_t qm1opm1; /* (q - 1) / (p - 1) */ mp_limb_t p; double ppre; mp_limb_t prime_root; /* primitive root for prime subfield */ mp_limb_t *zech_log_table; mp_limb_t *prime_field_table; mp_limb_t *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]; FLINT_DLL void fq_zech_ctx_init(fq_zech_ctx_t ctx, const fmpz_t p, slong d, const char *var); FLINT_DLL int fq_zech_ctx_init_fq_nmod_ctx_check(fq_zech_ctx_t ctx, fq_nmod_ctx_t ctxn); FLINT_DLL void fq_zech_ctx_init_fq_nmod_ctx(fq_zech_ctx_t ctx, fq_nmod_ctx_t ctxn); FLINT_DLL int _fq_zech_ctx_init_conway(fq_zech_ctx_t ctx, const fmpz_t p, slong d, const char *var); FLINT_DLL void fq_zech_ctx_init_conway(fq_zech_ctx_t ctx, const fmpz_t p, slong d, const char *var); FLINT_DLL void fq_zech_ctx_init_random(fq_zech_ctx_t ctx, const fmpz_t p, slong d, const char *var); FLINT_DLL void fq_zech_ctx_init_modulus(fq_zech_ctx_t ctx, const nmod_poly_t modulus, const char *var); FLINT_DLL int fq_zech_ctx_init_modulus_check(fq_zech_ctx_t ctx, const nmod_poly_t modulus, const char *var); FLINT_DLL void fq_zech_ctx_randtest(fq_zech_ctx_t ctx, flint_rand_t state); FLINT_DLL void fq_zech_ctx_randtest_reducible(fq_zech_ctx_t ctx, flint_rand_t state); FLINT_DLL 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 fq_nmod_ctx_modulus(ctx->fq_nmod_ctx); } FQ_ZECH_INLINE slong fq_zech_ctx_degree(const fq_zech_ctx_t ctx) { return fq_nmod_ctx_degree(ctx->fq_nmod_ctx); } FQ_ZECH_INLINE void fq_zech_ctx_order(fmpz_t f, const fq_zech_ctx_t ctx) { fq_nmod_ctx_order(f, ctx->fq_nmod_ctx); } FQ_ZECH_INLINE mp_limb_t fq_zech_ctx_order_ui(const fq_zech_ctx_t ctx) { return ctx->qm1 + 1; } #define fq_zech_ctx_prime(ctx) fq_nmod_ctx_prime(ctx->fq_nmod_ctx) FQ_ZECH_INLINE 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); } FQ_ZECH_INLINE void fq_zech_ctx_print(const fq_zech_ctx_t ctx) { fq_zech_ctx_fprint(stdout, ctx); } /* Memory managment *********************************************************/ 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 **********************************************************/ FLINT_DLL void fq_zech_add(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_sub(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_sub_one(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_neg(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_mul(fq_zech_t rop, const fq_zech_t op1, const fq_zech_t op2, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_mul_fmpz(fq_zech_t rop, const fq_zech_t op, const fmpz_t x, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_mul_si(fq_zech_t rop, const fq_zech_t op, slong x, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_mul_ui(fq_zech_t rop, const fq_zech_t op, ulong x, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_sqr(fq_zech_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_inv(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fq_zech_pow(fq_zech_t rop, const fq_zech_t op1, const fmpz_t e, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_pow_ui(fq_zech_t rop, const fq_zech_t op1, const ulong e, const fq_zech_ctx_t ctx); /* Roots *********************************************************************/ FLINT_DLL int fq_zech_sqrt(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_pth_root(fq_zech_t rop, const fq_zech_t op1, const fq_zech_ctx_t ctx); FLINT_DLL int fq_zech_is_square(const fq_zech_t op1, const fq_zech_ctx_t ctx); /* Randomisation *************************************************************/ FLINT_DLL void fq_zech_randtest(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_randtest_not_zero(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_rand(fq_zech_t rop, flint_rand_t state, const fq_zech_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL void fq_zech_set_fmpz(fq_zech_t rop, const fmpz_t x, const fq_zech_ctx_t ctx); FQ_ZECH_INLINE 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); } FQ_ZECH_INLINE 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); } 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; } FLINT_DLL void fq_zech_set_fq_nmod(fq_zech_t rop, const fq_nmod_t op, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_get_fq_nmod(fq_nmod_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_get_nmod_poly(nmod_poly_t a, const fq_zech_t b, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_set_nmod_poly(fq_zech_t a, const nmod_poly_t b, const fq_zech_ctx_t ctx); /* Output ********************************************************************/ FQ_ZECH_INLINE 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); } FQ_ZECH_INLINE void fq_zech_print_pretty(const fq_zech_t op, const fq_zech_ctx_t ctx) { fq_zech_fprint_pretty(stdout, op, ctx); } FQ_ZECH_INLINE int fq_zech_fprint(FILE * file, const fq_zech_t op, const fq_zech_ctx_t ctx) { return flint_fprintf(file, "%wd", op->value); } FQ_ZECH_INLINE void fq_zech_print(const fq_zech_t op, const fq_zech_ctx_t ctx) { fq_zech_fprint(stdout, op, ctx); } FLINT_DLL char * fq_zech_get_str(const fq_zech_t op, const fq_zech_ctx_t ctx); FLINT_DLL char * fq_zech_get_str_pretty(const fq_zech_t op, const fq_zech_ctx_t ctx); /* Special functions *********************************************************/ FLINT_DLL void fq_zech_trace(fmpz_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_frobenius(fq_zech_t rop, const fq_zech_t op, slong e, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_norm(fmpz_t rop, const fq_zech_t op, const fq_zech_ctx_t ctx); /* Bit packing ******************************************************/ FLINT_DLL void fq_zech_bit_pack(fmpz_t f, const fq_zech_t op, flint_bitcnt_t bit_size, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_bit_unpack(fq_zech_t rop, const fmpz_t f, flint_bitcnt_t bit_size, const fq_zech_ctx_t ctx); /* Inlines *******************************************************************/ FLINT_DLL void __fq_zech_ctx_prime(fmpz_t p, fq_zech_ctx_t ctx); #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 flint2-2.8.4/fq_zech/000077500000000000000000000000001414523752600143535ustar00rootroot00000000000000flint2-2.8.4/fq_zech/add.c000066400000000000000000000016571414523752600152600ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/fq_zech/bit_pack.c000066400000000000000000000013241414523752600162730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech/bit_unpack.c000066400000000000000000000013461414523752600166420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech/clear.c000066400000000000000000000007751414523752600156160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" void osxdummy2394872398429() /* OSX doesn't like empty files */ { } flint2-2.8.4/fq_zech/ctx_clear.c000066400000000000000000000013241414523752600164630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" void fq_zech_ctx_clear(fq_zech_ctx_t ctx) { flint_free(ctx->zech_log_table); flint_free(ctx->prime_field_table); flint_free(ctx->eval_table); if (ctx->owns_fq_nmod_ctx) { fq_nmod_ctx_clear(ctx->fq_nmod_ctx); flint_free(ctx->fq_nmod_ctx); } } flint2-2.8.4/fq_zech/ctx_init.c000066400000000000000000000140471414523752600163460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fq_zech.h" void fq_zech_ctx_init(fq_zech_ctx_t ctx, const fmpz_t p, slong d, const char *var) { if (!_fq_zech_ctx_init_conway(ctx, p, d, var)) fq_zech_ctx_init_random(ctx, p, d, var); } void fq_zech_ctx_init_conway(fq_zech_ctx_t ctx, const fmpz_t 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_conway(fq_nmod_ctx, p, d, var); fq_zech_ctx_init_fq_nmod_ctx(ctx, fq_nmod_ctx); ctx->owns_fq_nmod_ctx = 1; ctx->is_conway = 1; } int _fq_zech_ctx_init_conway(fq_zech_ctx_t ctx, const fmpz_t p, slong d, const char *var) { int result; fq_nmod_ctx_struct * fq_nmod_ctx; fq_nmod_ctx = flint_malloc(sizeof(fq_nmod_ctx_struct)); result = _fq_nmod_ctx_init_conway(fq_nmod_ctx, p, d, var); if (!result) { flint_free(fq_nmod_ctx); ctx->is_conway = 0; return result; } else ctx->is_conway = 1; fq_zech_ctx_init_fq_nmod_ctx(ctx, fq_nmod_ctx); ctx->owns_fq_nmod_ctx = 1; return result; } void fq_zech_ctx_init_random(fq_zech_ctx_t ctx, const fmpz_t p, slong d, const char *var) { fq_nmod_ctx_struct * fq_nmod_ctx; flint_rand_t state; nmod_poly_t poly; fq_nmod_ctx = flint_malloc(sizeof(fq_nmod_ctx_struct)); flint_randinit(state); nmod_poly_init2(poly, fmpz_get_ui(p), d + 1); nmod_poly_randtest_monic_primitive(poly, state, d + 1); fq_nmod_ctx_init_modulus(fq_nmod_ctx, poly, var); nmod_poly_clear(poly); flint_randclear(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 fq_nmod_ctx) { ulong i, n; fq_nmod_t r, gen; slong up, q; fmpz_t result, order; mp_limb_t j, nz, result_ui; mp_limb_t *n_reverse_table; ctx->fq_nmod_ctx = fq_nmod_ctx; ctx->owns_fq_nmod_ctx = 0; fmpz_init(order); fq_nmod_ctx_order(order, fq_nmod_ctx); if (fmpz_bits(order) > FLINT_BITS) { flint_printf("Exception (fq_zech_ctx_init_fq_nmod_ctx). Requires q < 2^FLINT_BITS\n"); flint_abort(); } q = fmpz_get_ui(order); up = fmpz_get_ui(fq_nmod_ctx_prime(fq_nmod_ctx)); 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(fq_nmod_ctx) & 1) ? ctx->p - fq_nmod_ctx->a[0] : fq_nmod_ctx->a[0]; ctx->zech_log_table = (mp_limb_t *) flint_malloc(q * sizeof(mp_limb_t)); ctx->prime_field_table = (mp_limb_t *) flint_malloc(up * sizeof(mp_limb_t)); n_reverse_table = (mp_limb_t *) flint_malloc(q * sizeof(mp_limb_t)); ctx->eval_table = (mp_limb_t *) flint_malloc(q * sizeof(mp_limb_t)); 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); fmpz_init(result); for (i = 0; i < ctx->qm1; i++) { nmod_poly_evaluate_fmpz(result, r, fq_nmod_ctx_prime(fq_nmod_ctx)); result_ui = fmpz_get_ui(result); if (n_reverse_table[result_ui] != ctx->qm1) return 0; /* failure: modulus not primitive */ n_reverse_table[result_ui] = i; ctx->eval_table[i] = result_ui; if (r->length == 1) { ctx->prime_field_table[result_ui] = i; } fq_nmod_mul(r, r, gen, fq_nmod_ctx); } 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, fq_nmod_ctx); fq_nmod_clear(gen, fq_nmod_ctx); flint_free(n_reverse_table); fmpz_clear(result); fmpz_clear(order); 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_printf("Exception (fq_zech_ctx_init_fq_nmod_ctx). Polynomial is not primitive.\n"); flint_abort(); } } flint2-2.8.4/fq_zech/ctx_randtest.c000066400000000000000000000017551414523752600172310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include "fq_nmod.h" #include "ulong_extras.h" #include "long_extras.h" #include void fq_zech_ctx_randtest(fq_zech_ctx_t ctx, flint_rand_t state) { fmpz_t p; slong max_d, d; fmpz_init(p); fmpz_set_ui(p, n_randprime(state, 2 + n_randint(state, 4), 1)); if (n_randlimb(state) % 16 == 0) /* slow */ max_d = floor(log(n_pow(2, 15)) / log(fmpz_get_ui(p))); else max_d = floor(log(n_pow(2, 11)) / log(fmpz_get_ui(p))); d = n_randint(state, max_d - 1) + 2; fq_zech_ctx_init_random(ctx, p, d, "a"); fmpz_clear(p); ctx->owns_fq_nmod_ctx = 1; } flint2-2.8.4/fq_zech/ctx_randtest_reducible.c000066400000000000000000000010061414523752600212340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" void fq_zech_ctx_randtest_reducible(fq_zech_ctx_t ctx, flint_rand_t state) { fq_zech_ctx_randtest(ctx, state); } flint2-2.8.4/fq_zech/div.c000066400000000000000000000010071414523752600152770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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/div.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech/frobenius.c000066400000000000000000000016721414523752600165210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_zech/gcdinv.c000066400000000000000000000012331414523752600157700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fq_zech/get_fq_nmod.c000066400000000000000000000015641414523752600170070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech/get_nmod_poly.c000066400000000000000000000016431414523752600173620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech/get_set_fmpz_mod_mat.c000066400000000000000000000020621414523752600207050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech/get_str.c000066400000000000000000000012201414523752600161610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech/get_str_pretty.c000066400000000000000000000016111414523752600175740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" #include 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; } flint2-2.8.4/fq_zech/inlines.c000066400000000000000000000013461414523752600161640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_ZECH_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fq_zech.h" void __fq_zech_ctx_prime(fmpz_t p, fq_zech_ctx_t ctx) { fmpz_set(p, fq_zech_ctx_prime(ctx)); } flint2-2.8.4/fq_zech/inv.c000066400000000000000000000014331414523752600153140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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_printf("Exception (fq_inv). Zero is not invertible.\n"); flint_abort(); } if (fq_zech_is_one(op, ctx)) { fq_zech_one(rop, ctx); return; } rop->value = ctx->qm1 - op->value; } flint2-2.8.4/fq_zech/is_invertible.c000066400000000000000000000010211414523752600173470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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/is_invertible.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech/is_invertible_f.c000066400000000000000000000010231414523752600176560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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/is_invertible_f.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech/is_square.c000066400000000000000000000011351414523752600165120ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fq_zech/mul.c000066400000000000000000000013361414523752600153170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); } flint2-2.8.4/fq_zech/mul_fmpz.c000066400000000000000000000012571414523752600163550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" 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); } flint2-2.8.4/fq_zech/mul_si.c000066400000000000000000000014731414523752600160140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" 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); } } flint2-2.8.4/fq_zech/mul_ui.c000066400000000000000000000015271414523752600160160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech.h" 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); } flint2-2.8.4/fq_zech/multiplicative_order.c000066400000000000000000000010301414523752600207370ustar00rootroot00000000000000/* 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 2.1 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/multiplicative_order.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech/neg.c000066400000000000000000000013341414523752600152710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } } flint2-2.8.4/fq_zech/norm.c000066400000000000000000000012031414523752600154660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } } flint2-2.8.4/fq_zech/pow.c000066400000000000000000000025151414523752600153270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (fq_zech_pow). e < 0.\n"); flint_abort(); } 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); } flint2-2.8.4/fq_zech/pth_root.c000066400000000000000000000016051414523752600163570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech/rand.c000066400000000000000000000012431414523752600154430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech/randtest.c000066400000000000000000000012771414523752600163520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech/set_fmpz.c000066400000000000000000000013071414523752600163470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech/set_fq_nmod.c000066400000000000000000000014461414523752600170220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fq_zech/set_nmod_poly.c000066400000000000000000000016751414523752600174030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/fq_zech/sqr.c000066400000000000000000000012001414523752600153150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_zech/sqrt.c000066400000000000000000000015041414523752600155100ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/fq_zech/sub.c000066400000000000000000000017511414523752600153140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/fq_zech/sub_one.c000066400000000000000000000011641414523752600161530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fq_zech/test/000077500000000000000000000000001414523752600153325ustar00rootroot00000000000000flint2-2.8.4/fq_zech/test/t-add.c000066400000000000000000000145741414523752600165020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int j, i, result; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("add... "); fflush(stdout); for (j = 0; j < 10; j++) { fq_zech_ctx_randtest(ctx, state); /* 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_add(c, a, b, ctx); fq_zech_add(a, a, b, ctx); result = (fq_zech_equal(a, c, ctx)); if (!result) { flint_printf("FAIL a = 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("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); 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_add(c, a, b, ctx); fq_zech_add(b, a, b, ctx); result = (fq_zech_equal(b, c, ctx)); if (!result) { flint_printf("FAIL 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("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); 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_add(c, a, a, ctx); fq_zech_add(a, a, a, ctx); result = (fq_zech_equal(a, 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("c = "), fq_zech_print_pretty(c, ctx), flint_printf("\n"); abort(); } fq_zech_clear(a, ctx); fq_zech_clear(c, ctx); } /* Check that a + b == b + a */ for (i = 0; i < 200; 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_add(c1, a, b, ctx); fq_zech_add(c2, b, a, ctx); result = (fq_zech_equal(c1, c2, ctx)); if (!result) { flint_printf("FAIL a + b = b + 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("c1 = "), fq_zech_print_pretty(c1, ctx), flint_printf("\n"); flint_printf("c2 = "), fq_zech_print_pretty(c2, ctx), flint_printf("\n"); 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_add(lhs, a, b, ctx); fq_zech_add(lhs, lhs, c, ctx); fq_zech_add(rhs, b, c, ctx); fq_zech_add(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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-assign.c000066400000000000000000000010221414523752600172160ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_zech/test/t-ctx_init.c000066400000000000000000000064431414523752600175670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { slong 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 p, e; fq_nmod_ctx_struct *fq_nmod_ctx; fq_nmod_t lhs, rhs, one; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("ctx_init... "); fflush(stdout); fmpz_init(p); fmpz_init(e); for (i = 0; i < 10; i++) { fmpz_set_ui(p, primes[i]); for (d = 2; d < exponents[i]; d++) { for (random = 0; random <= 1; random++) { if (random) fq_zech_ctx_init_random(ctx, p, d, "a"); else fq_zech_ctx_init_conway(ctx, p, 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"); 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(p); fmpz_clear(e); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-div.c000066400000000000000000000010161414523752600165170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_zech/test/t-frobenius.c000066400000000000000000000057271414523752600177460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int j, i, result; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("frobenius... "); fflush(stdout); for (j = 0; j < 10; j++) { fq_zech_ctx_randtest(ctx, state); /* Check aliasing: a = frob(a, e) */ for (i = 0; i < 100; i++) { 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"); abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fmpz_clear(e); } /* Compare with exponentiation, for integral values */ for (i = 0; i < 100; i++) { 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_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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-get_set_fq_nmod.c000066400000000000000000000036641414523752600211050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("get_fq_nmod/set_fq_nmod... "); fflush(stdout); for (i = 0; i < 100*flint_test_multiplier(); i++) { fq_zech_ctx_t ctx; fq_zech_t a, b; fq_nmod_t c; fq_zech_ctx_randtest(ctx, state); fq_zech_init(a, ctx); fq_zech_init(b, ctx); fq_nmod_init(c, ctx->fq_nmod_ctx); for (j = 0; j < 20; j++) { 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-get_set_nmod_poly.c000066400000000000000000000041541414523752600214550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { slong i, j; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("get/set_nmod_poly... "); fflush(stdout); for (j = 0; j < 10*flint_test_multiplier(); j++) { fq_zech_ctx_randtest(ctx, state); for (i = 0; i < 100; 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]); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-inv.c000066400000000000000000000055141414523752600165400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int j, i, result; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("inv... "); fflush(stdout); for (j = 0; j < 10; j++) { fq_zech_ctx_randtest(ctx, state); /* 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_not_zero(a, state, ctx); 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)); if (!result) { flint_printf("FAIL (aliasing):\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); abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); } /* Check a * ~a == 1 for units */ 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_not_zero(a, state, ctx); 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 (a * (~a) == 1):\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"); abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fq_zech_clear(c, ctx); } fq_zech_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-is_invertible.c000066400000000000000000000010301414523752600205670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_zech/test/t-is_invertible_f.c000066400000000000000000000010321414523752600210760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_zech/test/t-is_primitive.c000066400000000000000000000010271414523752600204420ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_zech/test/t-is_square.c000066400000000000000000000010251414523752600177300ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_zech/test/t-mul.c000066400000000000000000000137401414523752600165410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int j, i, result; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("mul... "); fflush(stdout); for (j = 0; j < 10; j++) { fq_zech_ctx_randtest(ctx, state); /* 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_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"); 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_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"); 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 < 200; i++) { 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"); abort(); } fq_zech_clear(a, ctx); fq_zech_clear(c, ctx); } /* Check that a * b == b * a */ for (i = 0; i < 200; 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_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"); 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 < 200; 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_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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-mul_fmpz.c000066400000000000000000000070651414523752600176000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int j, i, result; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("mul_fmpz... "); fflush(stdout); for (j = 0; j < 50; j++) { fq_zech_ctx_randtest(ctx, state); for (i = 0; i < 200; i++) { fmpz_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); fmpz_init(x); fmpz_randtest_mod_signed(x, state, fq_zech_ctx_prime(ctx)); 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"); abort(); } fmpz_clear(x); fq_nmod_clear(bb, ctx->fq_nmod_ctx); fq_nmod_clear(aa, ctx->fq_nmod_ctx); } for (i = 0; i < 200; i++) { fmpz_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); fmpz_init(x); fmpz_randtest_mod_signed(x, state, fq_zech_ctx_prime(ctx)); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-mul_ui.c000066400000000000000000000067561414523752600172470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int j, i, result; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("mul_ui... "); fflush(stdout); for (j = 0; j < 50; j++) { fq_zech_ctx_randtest(ctx, state); for (i = 0; i < 200; i++) { 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"); abort(); } fq_nmod_clear(bb, ctx->fq_nmod_ctx); fq_nmod_clear(aa, ctx->fq_nmod_ctx); } for (i = 0; i < 200; i++) { 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"); abort(); } fq_nmod_clear(bb, ctx->fq_nmod_ctx); fq_nmod_clear(aa, ctx->fq_nmod_ctx); } fq_zech_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-multiplicative_order.c000066400000000000000000000010371414523752600221660ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_zech/test/t-neg.c000066400000000000000000000060231414523752600165110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, j, result; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("neg... "); fflush(stdout); for (j = 0; j < 10; j++) { fq_zech_ctx_randtest(ctx, state); /* 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-norm.c000066400000000000000000000042141414523752600167130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int j, i, result; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("norm... "); fflush(stdout); for (j = 0; j < 50; j++) { fq_zech_ctx_randtest(ctx, state); for (i = 0; i < 200; i++) { 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-pow.c000066400000000000000000000057261414523752600165560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int j, i, result; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("pow... "); fflush(stdout); for (j = 0; j < 10; j++) { fq_zech_ctx_randtest(ctx, state); /* Check aliasing: a = a^e */ for (i = 0; i < 100; i++) { 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"); abort(); } fq_zech_clear(a, ctx); fq_zech_clear(b, ctx); fmpz_clear(e); } /* Compare with multiplication, for integral values */ for (i = 0; i < 100; i++) { 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-pth_root.c000066400000000000000000000010231414523752600175710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 flint2-2.8.4/fq_zech/test/t-sqr.c000066400000000000000000000052611414523752600165500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int j, i, result; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("sqr... "); fflush(stdout); for (j = 0; j < 10; j++) { fq_zech_ctx_randtest(ctx, state); /* Check aliasing: a = a * a */ for (i = 0; i < 200; i++) { 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"); abort(); } fq_zech_clear(a, ctx); fq_zech_clear(c, ctx); } /* Check a^2 + a^2 = a(a + a) */ for (i = 0; i < 200; i++) { 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-sqrt.c000066400000000000000000000010201414523752600167210ustar00rootroot00000000000000/* 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 2.1 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 flint2-2.8.4/fq_zech/test/t-sub.c000066400000000000000000000136461414523752600165420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int j, i, result; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("sub... "); fflush(stdout); for (j = 0; j < 10; j++) { fq_zech_ctx_randtest(ctx, state); /* 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"); 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/test/t-trace.c000066400000000000000000000040771414523752600170450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int j, i, result; fq_zech_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("trace... "); fflush(stdout); for (j = 0; j < 50; j++) { fq_zech_ctx_randtest(ctx, state); for (i = 0; i < 200; i++) { 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech/trace.c000066400000000000000000000022261414523752600156170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_zech_embed.h000066400000000000000000000035301414523752600156610ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #define FQ_EMBED_TEMPLATES_INLINE FLINT_DLL #else #define FQ_ZECH_EMBED_INLINE static __inline__ #define FQ_EMBED_TEMPLATES_INLINE static __inline__ #endif #include "fq_zech.h" #include "fq_nmod_embed.h" #define T fq_zech #define B nmod #include "fq_embed_templates.h" FQ_EMBED_TEMPLATES_INLINE 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 FQ_ZECH_EMBED_INLINE 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); } #endif flint2-2.8.4/fq_zech_embed/000077500000000000000000000000001414523752600155075ustar00rootroot00000000000000flint2-2.8.4/fq_zech_embed/composition_matrix.c000066400000000000000000000016171414523752600216070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_embed/embed.c000066400000000000000000000011401414523752600167230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_embed.h" #include "fq_zech_poly.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" #undef B #undef CAP_T #undef T flint2-2.8.4/fq_zech_embed/matrices.c000066400000000000000000000011431414523752600174610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_embed.h" #include "fq_zech_poly.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/matrices.c" #undef B #undef CAP_T #undef T flint2-2.8.4/fq_zech_embed/mul_matrix.c000066400000000000000000000014471414523752600200420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_embed/test/000077500000000000000000000000001414523752600164665ustar00rootroot00000000000000flint2-2.8.4/fq_zech_embed/test/t-composition_matrix.c000066400000000000000000000011341414523752600230210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_embed/test/t-embed.c000066400000000000000000000011501414523752600201440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_embed.h" #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_embed/test/t-embed_matrices.c000066400000000000000000000112571414523752600220440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech_embed.h" int main(void) { int i, j; int primes[4] = {2, 3, 5}; int degrees[2] = {2, 3}; FLINT_TEST_INIT(state); flint_printf("embed matrices... "); fflush(stdout); /* 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_randtest(ctx, state); 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(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"); 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; fmpz_t p; fmpz_init(p); fmpz_set_si(p, primes[i % 3]); m = degrees[i % 2]; fq_zech_ctx_init_random(ctx1, p, 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"); 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); fmpz_clear(p); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech_embed/test/t-mono_dual_matrix.c000066400000000000000000000011321414523752600224310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_embed/test/t-mul_matrix.c000066400000000000000000000011241414523752600212520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat.h000066400000000000000000000023461414523752600153720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #define FQ_ZECH_MAT_INLINE FLINT_DLL #else #define FQ_MAT_TEMPLATES_INLINE static __inline__ #define FQ_ZECH_MAT_INLINE static __inline__ #endif #include "fq_zech.h" #include "fq_zech_vec.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 FQ_ZECH_MAT_INLINE 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; } #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates.h" #undef CAP_T #undef T #endif flint2-2.8.4/fq_zech_mat/000077500000000000000000000000001414523752600152145ustar00rootroot00000000000000flint2-2.8.4/fq_zech_mat/add.c000066400000000000000000000010171414523752600161070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/add.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/can_solve.c000066400000000000000000000010261414523752600173300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/can_solve.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/charpoly_danilevsky.c000066400000000000000000000011221414523752600214260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #include "fq_zech_poly.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/charpoly_danilevsky.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/clear.c000066400000000000000000000010211414523752600164400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/concat_horizontal.c000066400000000000000000000010431414523752600210760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/concat_horizontal.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/concat_vertical.c000066400000000000000000000010411414523752600205140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/concat_vertical.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/equal.c000066400000000000000000000010211414523752600164610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/equal.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/fprint.c000066400000000000000000000010221414523752600166550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/fprint.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/init.c000066400000000000000000000010201414523752600163140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/init.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/init_set.c000066400000000000000000000010241414523752600171730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/init_set.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/inlines.c000066400000000000000000000010661414523752600170240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_ZECH_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "fq_zech_mat.h" flint2-2.8.4/fq_zech_mat/inv.c000066400000000000000000000010171414523752600161530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/inv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/is_one.c000066400000000000000000000010231414523752600166300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/is_one.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/is_zero.c000066400000000000000000000010231414523752600170260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/is_zero.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/lu.c000066400000000000000000000010161414523752600157760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/lu.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/lu_classical.c000066400000000000000000000010301414523752600200100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/lu_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/lu_recursive.c000066400000000000000000000010301414523752600200610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/lu_recursive.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/minpoly.c000066400000000000000000000011061414523752600170450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #include "fq_zech_poly.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/minpoly.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/mul.c000066400000000000000000000010171414523752600161540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/mul.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/mul_KS.c000066400000000000000000000010221414523752600165450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/mul_KS.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/mul_classical.c000066400000000000000000000010311414523752600201660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/mul_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/mul_vec.c000066400000000000000000000010571414523752600170150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/mul_vec.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/neg.c000066400000000000000000000010171414523752600161300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/neg.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/nullspace.c000066400000000000000000000010251414523752600173440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/nullspace.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/one.c000066400000000000000000000010201414523752600161320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/one.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/randops.c000066400000000000000000000010231414523752600170220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/randops.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/randpermdiag.c000066400000000000000000000010301414523752600200070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/randpermdiag.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/randrank.c000066400000000000000000000010241414523752600171550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/randrank.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/randtest.c000066400000000000000000000010241414523752600172010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/randtest.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/randtril.c000066400000000000000000000010241414523752600171740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/randtril.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/randtriu.c000066400000000000000000000010241414523752600172050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/randtriu.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/rank.c000066400000000000000000000010201414523752600163040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/rank.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/reduce_row.c000066400000000000000000000011111414523752600175100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #include "fq_zech_poly.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/reduce_row.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/rref.c000066400000000000000000000010201414523752600163070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/rref.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/set.c000066400000000000000000000010171414523752600161520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/set.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/set_fmpz_mod_mat.c000066400000000000000000000010351414523752600207060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/set_fmpz_mod_mat.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/set_nmod_mat.c000066400000000000000000000010311414523752600200240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/set_nmod_mat.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/similarity.c000066400000000000000000000011111414523752600175400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #include "fq_zech_poly.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/similarity.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/solve.c000066400000000000000000000010221414523752600165030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/solve.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/solve_tril.c000066400000000000000000000010261414523752600175410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/solve_tril.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/solve_tril_classical.c000066400000000000000000000010401414523752600215530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/solve_tril_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/solve_tril_recursive.c000066400000000000000000000010401414523752600216240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/solve_tril_recursive.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/solve_triu.c000066400000000000000000000010261414523752600175520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/solve_triu.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/solve_triu_classical.c000066400000000000000000000010401414523752600215640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/solve_triu_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/solve_triu_recursive.c000066400000000000000000000010401414523752600216350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/solve_triu_recursive.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/sub.c000066400000000000000000000010171414523752600161500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/sub.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/submul.c000066400000000000000000000010221414523752600166620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/submul.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/swap.c000066400000000000000000000010201414523752600163230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/swap.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/test/000077500000000000000000000000001414523752600161735ustar00rootroot00000000000000flint2-2.8.4/fq_zech_mat/test/t-add_sub.c000066400000000000000000000010321414523752600201750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-can_solve.c000066400000000000000000000010351414523752600205500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-charpoly.c000066400000000000000000000010651414523752600204230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-concat_horizontal.c000066400000000000000000000010521414523752600223160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-concat_vertical.c000066400000000000000000000010501414523752600217340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-equal.c000066400000000000000000000010301414523752600177010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-inv.c000066400000000000000000000010261414523752600173730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-is_zero.c000066400000000000000000000010321414523752600202460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-lu_classical.c000066400000000000000000000010371414523752600212370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-lu_recursive.c000066400000000000000000000010371414523752600213100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-minpoly.c000066400000000000000000000010641414523752600202700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-mul.c000066400000000000000000000010261414523752600173740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-mul_KS.c000066400000000000000000000010311414523752600177650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-mul_vec.c000066400000000000000000000010351414523752600202310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-nullspace.c000066400000000000000000000010341414523752600205640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-one.c000066400000000000000000000010271414523752600173610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-rank.c000066400000000000000000000010271414523752600175330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-rref.c000066400000000000000000000010271414523752600175360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-set_fmpz_mod_mat.c000066400000000000000000000010441414523752600221260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-set_nmod_mat.c000066400000000000000000000010401414523752600212440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-solve.c000066400000000000000000000010311414523752600177230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-solve_tril.c000066400000000000000000000010351414523752600207610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-solve_tril_classical.c000066400000000000000000000010471414523752600230020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-solve_tril_recursive.c000066400000000000000000000010471414523752600230530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-solve_triu.c000066400000000000000000000010351414523752600207720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-solve_triu_classical.c000066400000000000000000000010471414523752600230130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-solve_triu_recursive.c000066400000000000000000000010471414523752600230640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-submul.c000066400000000000000000000010311414523752600201020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-vec_mul.c000066400000000000000000000010351414523752600202310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-window_init_clear.c000066400000000000000000000010521414523752600222760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/test/t-zero.c000066400000000000000000000010271414523752600175570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_mat/vec_mul.c000066400000000000000000000010571414523752600170150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/vec_mul.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/window_clear.c000066400000000000000000000010301414523752600200270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/window_clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/window_init.c000066400000000000000000000010271414523752600177120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/window_init.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mat/zero.c000066400000000000000000000010201414523752600163300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mat.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_mat_templates/zero.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_mpoly.h000066400000000000000000001030271414523752600157470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define FQ_ZECH_MPOLY_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fq_zech.h" #include "fq_zech_poly.h" #include "fq_nmod_mpoly.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 ************************************************************/ FLINT_DLL 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); FLINT_DLL void fq_zech_mpoly_ctx_init(fq_zech_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, const fq_zech_ctx_t fqctx); FLINT_DLL 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 ********************************************************/ FLINT_DLL void fq_zech_mpoly_init(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_init2(fq_zech_mpoly_t A, slong alloc, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_init3(fq_zech_mpoly_t A, slong alloc, flint_bitcnt_t bits, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_realloc(fq_zech_mpoly_t A, slong alloc, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_fit_length(fq_zech_mpoly_t A, slong length, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void _fq_zech_mpoly_fit_length(fq_zech_struct ** coeff, ulong ** exps, slong * alloc, slong len, slong N, const fq_zech_ctx_t fqctx); FLINT_DLL 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); FLINT_DLL 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; } } FQ_ZECH_MPOLY_INLINE 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; } } /* Input/output **************************************************************/ FLINT_DLL 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); FLINT_DLL char * fq_zech_mpoly_get_str_pretty(const fq_zech_mpoly_t A, const char ** x, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL int fq_zech_mpoly_fprint_pretty(FILE * file, const fq_zech_mpoly_t A, const char ** x, const fq_zech_mpoly_ctx_t ctx); FQ_ZECH_MPOLY_INLINE 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); } /* Basic manipulation *******************************************************/ FLINT_DLL void fq_zech_mpoly_gen(fq_zech_mpoly_t A, slong var, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL int fq_zech_mpoly_is_gen(const fq_zech_mpoly_t A, slong var, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_set(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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) { fq_zech_mpoly_struct t = *A; *A = *B; *B = t; } /* Constants *****************************************************************/ FLINT_DLL int fq_zech_mpoly_is_fq_zech(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_get_fq_zech(fq_zech_t c, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_set_fq_zech(fq_zech_mpoly_t A, const fq_zech_t c, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_set_ui(fq_zech_mpoly_t A, ulong c, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_set_fq_zech_gen(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL int fq_zech_mpoly_is_one(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); /* Degrees *******************************************************************/ FQ_ZECH_MPOLY_INLINE 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); } FQ_ZECH_MPOLY_INLINE 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); } FQ_ZECH_MPOLY_INLINE 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); } FQ_ZECH_MPOLY_INLINE 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); } FQ_ZECH_MPOLY_INLINE 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); } FQ_ZECH_MPOLY_INLINE 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); } FQ_ZECH_MPOLY_INLINE 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); } FQ_ZECH_MPOLY_INLINE 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); } /* Coefficients **************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ****************************************************************/ FLINT_DLL 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 ******************************************************/ FLINT_DLL 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; } FLINT_DLL void fq_zech_mpoly_resize(fq_zech_mpoly_t A, slong new_length, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FQ_ZECH_MPOLY_INLINE 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); } FQ_ZECH_MPOLY_INLINE 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fq_zech_mpoly_sort_terms(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_combine_like_terms(fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_reverse(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_assert_canonical(const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void _fq_zech_mpoly_radix_sort1(fq_zech_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask); FLINT_DLL void _fq_zech_mpoly_radix_sort(fq_zech_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask); FLINT_DLL void _fq_zech_mpoly_push_exp_ffmpz(fq_zech_mpoly_t A, const fmpz * exp, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void _fq_zech_mpoly_push_exp_pfmpz(fq_zech_mpoly_t A, fmpz * const * exp, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void _fq_zech_mpoly_push_exp_ui(fq_zech_mpoly_t A, const ulong * exp, const fq_zech_mpoly_ctx_t ctx); /* Random generation *********************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ******************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_DLL 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 *********************************************************/ FLINT_DLL void fq_zech_mpoly_neg(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fq_zech_mpoly_make_monic(fq_zech_mpoly_t A, const fq_zech_mpoly_t B, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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 **********************************************************/ FLINT_DLL 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 ****************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ******************************************************************/ FLINT_DLL 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); FLINT_DLL 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 ******************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ***********************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fq_zech_mpoly_deflation(fmpz * shift, fmpz * stride, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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 ***************************************************************/ FLINT_DLL void fq_zech_mpoly_univar_init(fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_univar_clear(fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_univar_fit_length(fq_zech_mpoly_univar_t A, slong length, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_univar_print_pretty(const fq_zech_mpoly_univar_t A, const char ** x, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_univar_assert_canonical(fq_zech_mpoly_univar_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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_DLL 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); FLINT_DLL 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) { fq_zech_mpoly_univar_struct t = *A; *A = *B; *B = t; } FQ_ZECH_MPOLY_INLINE 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); } 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; } FQ_ZECH_MPOLY_INLINE 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); } 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) ******************************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int fq_zech_mpoly_repack_bits_inplace(fq_zech_mpoly_t A, flint_bitcnt_t Abits, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_ctx_change_modulus(fq_zech_mpoly_ctx_t ctx, slong deg); FLINT_DLL 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); FLINT_DLL 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 ********************************************************************/ FLINT_DLL int fq_zech_mpolyu_is_canonical(const fq_zech_mpolyu_t poly, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpolyu_init(fq_zech_mpolyu_t A, flint_bitcnt_t bits, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpolyu_clear(fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t uctx); FLINT_DLL void fq_zech_mpolyu_swap(fq_zech_mpolyu_t A, fq_zech_mpolyu_t B); FLINT_DLL void fq_zech_mpolyu_zero(fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t uctx); FLINT_DLL int fq_zech_mpolyu_is_one(fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t uctx); FLINT_DLL void fq_zech_mpolyu_print_pretty(const fq_zech_mpolyu_t poly, const char ** x, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpolyu_fit_length(fq_zech_mpolyu_t A, slong length, const fq_zech_mpoly_ctx_t uctx); FLINT_DLL void fq_zech_mpolyu_one(fq_zech_mpolyu_t A, const fq_zech_mpoly_ctx_t uctx); #ifdef __cplusplus } #endif #endif flint2-2.8.4/fq_zech_mpoly/000077500000000000000000000000001414523752600155735ustar00rootroot00000000000000flint2-2.8.4/fq_zech_mpoly/add.c000066400000000000000000000076171414523752600165020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/clear.c000066400000000000000000000012631414523752600170270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_zech_mpoly/combine_like_terms.c000066400000000000000000000031231414523752600215700ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/ctx_change_modulus.c000066400000000000000000000012231414523752600216100ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly.h" void fq_zech_mpoly_ctx_change_modulus(fq_zech_mpoly_ctx_t ctx, slong deg) { fmpz_t P; fmpz_init_set_ui(P, fq_zech_ctx_mod(ctx->fqctx).n); fq_zech_ctx_clear(ctx->fqctx); fq_zech_ctx_init(ctx->fqctx, P, deg, "#"); fmpz_clear(P); } flint2-2.8.4/fq_zech_mpoly/ctx_clear.c000066400000000000000000000010301414523752600176750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly.h" void fq_zech_mpoly_ctx_clear(fq_zech_mpoly_ctx_t ctx) { mpoly_ctx_clear(ctx->minfo); fq_zech_ctx_clear(ctx->fqctx); } flint2-2.8.4/fq_zech_mpoly/ctx_init.c000066400000000000000000000020521414523752600175570ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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) { fmpz_t P; mpoly_ctx_init(ctx->minfo, nvars, ord); fmpz_init_set_ui(P, p); fq_zech_ctx_init(ctx->fqctx, P, deg, "#"); fmpz_clear(P); } void fq_zech_mpoly_ctx_init(fq_zech_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, const fq_zech_ctx_t fqctx) { mpoly_ctx_init(ctx->minfo, nvars, ord); flint_printf("fq_zech_mpoly_ctx_init not implemented\n"); flint_abort(); /* fq_nmod_ctx_init_modulus(ctx->fqctx, fqctx->modulus, fqctx->var);*/ } flint2-2.8.4/fq_zech_mpoly/derivative.c000066400000000000000000000066471414523752600201160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/divides.c000066400000000000000000000013011414523752600173610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fq_zech_mpoly/divides_monagan_pearce.c000066400000000000000000000317661414523752600224220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 indicies */ 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 cofficient 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); } flint2-2.8.4/fq_zech_mpoly/divrem.c000066400000000000000000000013131414523752600172230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fq_zech_mpoly/divrem_monagan_pearce.c000066400000000000000000000312751414523752600222540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 indicies */ 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 cofficient 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 neccesary */ 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); } flint2-2.8.4/fq_zech_mpoly/equal.c000066400000000000000000000043611414523752600170520ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/evaluate_all.c000066400000000000000000000051501414523752600203760ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_mpoly/evaluate_one.c000066400000000000000000000122411414523752600204060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_mpoly/fit_length.c000066400000000000000000000040311414523752600200600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/fq_zech_mpoly/fit_length_reset_bits.c000066400000000000000000000027171414523752600223140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly.h" 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; } flint2-2.8.4/fq_zech_mpoly/fprint_pretty.c000066400000000000000000000045561414523752600206620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech_mpoly.h" 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; } flint2-2.8.4/fq_zech_mpoly/gcd.c000066400000000000000000000027511414523752600165010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/gcd_cofactors.c000066400000000000000000000062531414523752600205450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/gen.c000066400000000000000000000017621414523752600165160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/get_coeff_vars_ui.c000066400000000000000000000105641414523752600214160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/get_set_fq_nmod_mpoly000066400000000000000000000032041414523752600220720ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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) { flint_bitcnt_t bits = B->bits; slong N = mpoly_words_per_exp(bits, ctxB->minfo); FLINT_ASSERT(ctxA->minfo->ord == ctxB->ord); FLINT_ASSERT(ctxA->minfo->nvars == ctxB->minfo->nvars); fq_nmod_mpoly_fit_length_set_bits(A, B->length, bits, ctxA); for (i = 0; i < B->length; i++) fq_zech_get_fq_nmod(A->coeffs + i, B->coeffs + i, ctxB->fqctx); mpoly_copy_monomials(A->exps, B->exps, B->length, N); A->length = B->length; } 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) { flint_bitcnt_t bits = B->bits; slong N->mpoly_words_per_exp(bits, ctxB->minfo); FLINT_ASSERT(ctxA->minfo->ord == ctxB->ord); FLINT_ASSERT(ctxA->minfo->nvars == ctxB->minfo->nvars); fq_zech_mpoly_fit_length_set_bits(A, B->length, bits, ctxA); for (i = 0; i < B->length; i++) fq_zech_set_fq_nmod(A->coeffs + i, B->coeffs + i, ctxA->fqctx); mpoly_copy_monomials(A->exps, B->exps, B->length, N); A->length = B->length; } flint2-2.8.4/fq_zech_mpoly/get_set_fq_nmod_mpoly.c000066400000000000000000000040741414523752600223210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly.h" #include "fq_nmod_mpoly_factor.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); } flint2-2.8.4/fq_zech_mpoly/get_set_nmod_mpoly.c000066400000000000000000000040761414523752600216350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_mpoly/init.c000066400000000000000000000032321414523752600167020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_mpoly/is_canonical.c000066400000000000000000000033701414523752600203640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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"); } } flint2-2.8.4/fq_zech_mpoly/is_fq_zech.c000066400000000000000000000013551414523752600200550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_mpoly/is_one.c000066400000000000000000000013271414523752600172160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_mpoly/lead_coeff_vars.c000066400000000000000000000040041414523752600210370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/fq_zech_mpoly/make_monic.c000066400000000000000000000015461414523752600200470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_mpoly/mpolyu.c000066400000000000000000000110551414523752600172660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fq_zech_mpoly/mul.c000066400000000000000000000011761414523752600165410ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fq_zech_mpoly/mul_johnson.c000066400000000000000000000224771414523752600203060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/neg.c000066400000000000000000000025171414523752600165150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_mpoly/pow_rmul.c000066400000000000000000000016771414523752600176160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fq_zech_mpoly/pow_ui.c000066400000000000000000000036561414523752600172530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/repack_bits.c000066400000000000000000000043651414523752600202350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/scalar_addmul_fq_zech.c000066400000000000000000000104261414523752600222340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/scalar_mul_fq_zech.c000066400000000000000000000024511414523752600215620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly.h" 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); } flint2-2.8.4/fq_zech_mpoly/set.c000066400000000000000000000025131414523752600165330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/set_fq_zech.c000066400000000000000000000015571414523752600202410ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_mpoly/set_ui.c000066400000000000000000000015701414523752600172320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_mpoly/sort_terms.c000066400000000000000000000126131414523752600201430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); ULONG_SWAP(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); ULONG_SWAP(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; } flint2-2.8.4/fq_zech_mpoly/sub.c000066400000000000000000000103121414523752600165250ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly/sub_fq_zech.c000066400000000000000000000042221414523752600202270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_zech_mpoly/test/000077500000000000000000000000001414523752600165525ustar00rootroot00000000000000flint2-2.8.4/fq_zech_mpoly/test/t-empty.c000066400000000000000000000010611414523752600203130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech_mpoly.h" int main(void) { flint_printf("empty...."); fflush(stdout); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_zech_mpoly/univar.c000066400000000000000000000350011414523752600172420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } } 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); } flint2-2.8.4/fq_zech_mpoly_factor.h000066400000000000000000000517661414523752600173210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define FQ_ZECH_MPOLY_FACTOR_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "fq_zech_mpoly.h" #include "nmod_mpoly_factor.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; } FLINT_DLL 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; } FQ_ZECH_MPOLY_FACTOR_INLINE 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--; } FLINT_DLL 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; } FLINT_DLL int fq_zech_bpoly_equal(const fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx); FQ_ZECH_MPOLY_FACTOR_INLINE 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); } 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; } FLINT_DLL slong fq_zech_bpoly_degree1(const fq_zech_bpoly_t A, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_bpoly_set_poly_var1(fq_zech_bpoly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_bpoly_set_poly_var0(fq_zech_bpoly_t A, const fq_zech_poly_t B, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_bpoly_print_pretty(const fq_zech_bpoly_t A, const char * var0, const char * var1, const fq_zech_ctx_t ctx); FLINT_DLL int fq_zech_bpoly_is_canonical(const fq_zech_bpoly_t A, const fq_zech_ctx_t ctx); FLINT_DLL int fq_zech_bpoly_fq_equal( const fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fq_zech_bpoly_make_monic( fq_zech_bpoly_t A, slong order, const fq_zech_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fq_zech_bpoly_one( fq_zech_bpoly_t A, const fq_zech_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fq_zech_bpoly_derivative( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void fq_zech_bpoly_set( fq_zech_bpoly_t A, const fq_zech_bpoly_t B, const fq_zech_ctx_t ctx); FLINT_DLL void fq_zech_bpoly_make_primitive( fq_zech_poly_t g, fq_zech_bpoly_t A, const fq_zech_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fq_zech_bpoly_taylor_shift_var0( fq_zech_bpoly_t A, const fq_zech_t alpha, const fq_zech_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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; } FLINT_DLL void fq_zech_tpoly_fit_length(fq_zech_tpoly_t A, slong len, const fq_zech_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL void fq_zech_polyu_clear(fq_zech_polyu_t A, const fq_zech_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL 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); FLINT_DLL void fq_zech_polyu3_degrees( slong * deg0, slong * deg1, slong * deg2, const fq_zech_polyu_t A); FLINT_DLL 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; } FLINT_DLL void fq_zech_polyun_clear(fq_zech_polyun_t A, const fq_zech_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int fq_zech_polyun_is_canonical( const fq_zech_polyun_t A, const fq_zech_ctx_t ctx); /*****************************************************************************/ FLINT_DLL int fq_zech_mpoly_is_fq_zech_poly( const fq_zech_mpoly_t A, slong var, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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]; FLINT_DLL void fq_zech_mpoly_factor_init(fq_zech_mpoly_factor_t f, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_factor_realloc(fq_zech_mpoly_factor_t f, slong alloc, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_factor_fit_length(fq_zech_mpoly_factor_t f, slong len, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpoly_factor_clear(fq_zech_mpoly_factor_t f, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void fq_zech_mpoly_factor_print_pretty(const fq_zech_mpoly_factor_t f, const char ** vars, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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; } FQ_ZECH_MPOLY_FACTOR_INLINE 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_DLL 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; } FLINT_DLL void _fq_zech_mpoly_get_lead0( fq_zech_mpoly_t c, const fq_zech_mpoly_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL void fq_zech_mpolyv_clear(fq_zech_mpolyv_t A, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpolyv_print_pretty(const fq_zech_mpolyv_t poly, const char ** x, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL void fq_zech_mpolyv_fit_length(fq_zech_mpolyv_t A, slong length, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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]; FLINT_DLL 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); FLINT_DLL void fq_zech_mpoly_pfrac_clear( fq_zech_mpoly_pfrac_t I, const fq_zech_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 flint2-2.8.4/fq_zech_mpoly_factor/000077500000000000000000000000001414523752600171315ustar00rootroot00000000000000flint2-2.8.4/fq_zech_mpoly_factor/bpoly.c000066400000000000000000000410211414523752600204200ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_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; } 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"); } 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_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); } flint2-2.8.4/fq_zech_mpoly_factor/bpoly_factor_smprime.c000066400000000000000000000566171414523752600235330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly_factor.h" #include "nmod_poly.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); SLONG_SWAP(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); SLONG_SWAP(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 */ local_fac->num = 0; /* stupid */ 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 attemp 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; } flint2-2.8.4/fq_zech_mpoly_factor/bpoly_hlift.c000066400000000000000000000256371414523752600216250ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly_factor/clear.c000066400000000000000000000014541414523752600203670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_mpoly_factor/eval.c000066400000000000000000000142121414523752600202240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly_factor/factor.c000066400000000000000000000043551414523752600205620ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/fq_zech_mpoly_factor/fit_length.c000066400000000000000000000012621414523752600214210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fq_zech_mpoly_factor/get_set_is_fq_nmod_poly.c000066400000000000000000000070471414523752600242000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_mpoly_factor.h" #include "nmod_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); } flint2-2.8.4/fq_zech_mpoly_factor/get_set_lead0.c000066400000000000000000000025421414523752600217770ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fq_zech_mpoly_factor/init.c000066400000000000000000000012461414523752600202430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly_factor/irred_smprime_wang.c000066400000000000000000000213421414523752600231540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly_factor/irred_smprime_zassenhaus.c000066400000000000000000000262471414523752600244150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 evalutaion */ 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; } flint2-2.8.4/fq_zech_mpoly_factor/irred_smprime_zippel.c000066400000000000000000001157121414523752600235300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 comming 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); ULONG_SWAP(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; } flint2-2.8.4/fq_zech_mpoly_factor/lcc_wang.c000066400000000000000000000107411414523752600210550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly_factor/mpoly_hlift.c000066400000000000000000000272351414523752600216340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/fq_zech_mpoly_factor/mpoly_pfrac.c000066400000000000000000000242371414523752600216200ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly_factor/mpoly_univar.c000066400000000000000000000013331414523752600220210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/fq_zech_mpoly_factor/mpolyv.c000066400000000000000000000064731414523752600206350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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_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); } flint2-2.8.4/fq_zech_mpoly_factor/polyu.c000066400000000000000000000057021414523752600204510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_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_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; } flint2-2.8.4/fq_zech_mpoly_factor/polyu3_hlift.c000066400000000000000000000333421414523752600217230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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--) { ULONG_SWAP(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; } flint2-2.8.4/fq_zech_mpoly_factor/polyun.c000066400000000000000000000053761414523752600206360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } 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"); } 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; } flint2-2.8.4/fq_zech_mpoly_factor/print_pretty.c000066400000000000000000000015331414523752600220420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/fq_zech_mpoly_factor/realloc.c000066400000000000000000000037101414523752600207170ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/fq_zech_mpoly_factor/test/000077500000000000000000000000001414523752600201105ustar00rootroot00000000000000flint2-2.8.4/fq_zech_mpoly_factor/test/t-empty.c000066400000000000000000000011231414523752600216500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fq_zech_mpoly.h" #include "fq_zech_mpoly_factor.h" int main(void) { flint_printf("empty...."); fflush(stdout); flint_printf("PASS\n"); return 0; } flint2-2.8.4/fq_zech_mpoly_factor/tpoly.c000066400000000000000000000024171414523752600204500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/fq_zech_poly.h000066400000000000000000000024471414523752600155760ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #define FQ_POLY_TEMPLATES_INLINE FLINT_DLL #else #define FQ_ZECH_POLY_INLINE static __inline__ #define FQ_POLY_TEMPLATES_INLINE static __inline__ #endif #include "fq_zech_mat.h" #include "fmpz_mod_poly.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 #include "fq_zech_poly_factor.h" #endif flint2-2.8.4/fq_zech_poly/000077500000000000000000000000001414523752600154165ustar00rootroot00000000000000flint2-2.8.4/fq_zech_poly/add.c000066400000000000000000000010211414523752600163040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/add_series.c000066400000000000000000000010301414523752600176560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/add_series.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/add_si.c000066400000000000000000000010271414523752600170050ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/add_si.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/clear.c000066400000000000000000000010231414523752600166440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/compose.c000066400000000000000000000010251414523752600172250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/compose.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/compose_divconquer.c000066400000000000000000000010401414523752600214610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/compose_divconquer.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/compose_horner.c000066400000000000000000000010341414523752600206020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/compose_horner.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/compose_mod.c000066400000000000000000000010311414523752600200610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/compose_mod.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/compose_mod_brent_kung.c000066400000000000000000000010441414523752600223030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/compose_mod_brent_kung.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000010631414523752600254140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/compose_mod_brent_kung_precomp_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/compose_mod_brent_kung_preinv.c000066400000000000000000000010531414523752600236660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/compose_mod_brent_kung_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/compose_mod_horner.c000066400000000000000000000010401414523752600214360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/compose_mod_horner.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/compose_mod_horner_preinv.c000066400000000000000000000010471414523752600230300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/compose_mod_horner_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/compose_mod_preinv.c000066400000000000000000000010401414523752600214440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/compose_mod_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/deflate.c000066400000000000000000000010251414523752600171640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/deflate.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/deflation.c000066400000000000000000000010271414523752600175270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/deflation.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/derivative.c000066400000000000000000000010301414523752600177160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/derivative.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/div_basecase.c000066400000000000000000000010321414523752600201660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/div_basecase.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/div_newton_n_preinv.c000066400000000000000000000010411414523752600216320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/div_newton_n_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/div_series.c000066400000000000000000000010301414523752600177100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/div_series.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/divides.c000066400000000000000000000010251414523752600172070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/divides.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/divrem_basecase.c000066400000000000000000000010351414523752600206750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/divrem_basecase.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/divrem_divconquer.c000066400000000000000000000010371414523752600213100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/divrem_divconquer.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/divrem_divconquer_recursive.c000066400000000000000000000010511414523752600233730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/divrem_divconquer_recursive.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/divrem_f.c000066400000000000000000000010261414523752600173540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/divrem_f.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/divrem_newton_n_preinv.c000066400000000000000000000010441414523752600223410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/divrem_newton_n_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/equal.c000066400000000000000000000010231414523752600166650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/equal.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/equal_trunc.c000066400000000000000000000010311414523752600200770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/equal_trunc.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/evaluate_fq.c000066400000000000000000000010311414523752600200510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/evaluate_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/evaluate_fq_vec.c000066400000000000000000000011521414523752600207120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/evaluate_fq_vec.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/evaluate_fq_vec_fast.c000066400000000000000000000011571414523752600217340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/evaluate_fq_vec_fast.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/evaluate_fq_vec_iter.c000066400000000000000000000011571414523752600217420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/evaluate_fq_vec_iter.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/fit_length.c000066400000000000000000000010301414523752600176770ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/fit_length.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/fprint.c000066400000000000000000000010241414523752600170610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/fprint.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/fprint_pretty.c000066400000000000000000000010331414523752600204700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/fprint_pretty.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/gcd.c000066400000000000000000000010211414523752600163110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/gcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/gcd_euclidean.c000066400000000000000000000010331414523752600203250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/gcd_euclidean.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/gcd_euclidean_f.c000066400000000000000000000010351414523752600206340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/gcd_euclidean_f.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/gcd_hgcd.c000066400000000000000000000010261414523752600173030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/gcd_hgcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/gen.c000066400000000000000000000010211414523752600163250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/gen.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/get_coeff.c000066400000000000000000000010271414523752600175030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/get_coeff.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/get_str.c000066400000000000000000000010251414523752600172270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/get_str.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/get_str_pretty.c000066400000000000000000000010341414523752600206360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/get_str_pretty.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/hamming_weight.c000066400000000000000000000010341414523752600205470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/hamming_weight.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/hgcd.c000066400000000000000000000010221414523752600164620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/hgcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/inflate.c000066400000000000000000000010251414523752600172020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/inflate.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/init.c000066400000000000000000000010221414523752600165200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/init.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/inlines.c000066400000000000000000000011121414523752600172160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_ZECH_POLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "fq_zech_poly.h" flint2-2.8.4/fq_zech_poly/inv_series_newton.c000066400000000000000000000010371414523752600213230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/inv_series_newton.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/make_monic.c000066400000000000000000000010301414523752600176560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/make_monic.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/mul.c000066400000000000000000000010211414523752600163510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/mul.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/mul_KS.c000066400000000000000000000010241414523752600167510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/mul_KS.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/mul_classical.c000066400000000000000000000010331414523752600203720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/mul_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/mulhigh.c000066400000000000000000000010251414523752600172150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/mulhigh.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/mulhigh_classical.c000066400000000000000000000010371414523752600212360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/mulhigh_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/mullow.c000066400000000000000000000010241414523752600170760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/mullow.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/mullow_KS.c000066400000000000000000000010271414523752600174760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/mullow_KS.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/mullow_classical.c000066400000000000000000000010361414523752600211170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/mullow_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/mulmod.c000066400000000000000000000010241414523752600170540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/mulmod.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/mulmod_preinv.c000066400000000000000000000010331414523752600204370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/mulmod_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/neg.c000066400000000000000000000010211414523752600163250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/neg.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/normalise.c000066400000000000000000000010271414523752600175530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/normalise.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/one.c000066400000000000000000000010211414523752600163350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/one.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/pow.c000066400000000000000000000010211414523752600163610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/pow.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/pow_trunc.c000066400000000000000000000010271414523752600176020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/pow_trunc.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/pow_trunc_binexp.c000066400000000000000000000010361414523752600211470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/pow_trunc_binexp.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/powmod_fmpz_binexp.c000066400000000000000000000010401414523752600214630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/powmod_fmpz_binexp.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/powmod_fmpz_binexp_preinv.c000066400000000000000000000010471414523752600230550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/powmod_fmpz_binexp_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/powmod_fmpz_sliding_preinv.c000066400000000000000000000010501414523752600232130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/powmod_fmpz_sliding_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/powmod_ui_binexp.c000066400000000000000000000010361414523752600211310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/powmod_ui_binexp.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/powmod_ui_binexp_preinv.c000066400000000000000000000010451414523752600225140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/powmod_ui_binexp_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/powmod_x_fmpz_preinv.c000066400000000000000000000010421414523752600220320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/powmod_x_fmpz_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/profile/000077500000000000000000000000001414523752600170565ustar00rootroot00000000000000flint2-2.8.4/fq_zech_poly/profile/p-factor_kaltofen_shoup_vs_fq_nmod_poly.c000066400000000000000000000065171414523752600273250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" #include "profiler.h" #include "fq_zech_poly.h" #include "fq_nmod_poly.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_zech_poly_t f, g; fq_nmod_poly_t fn; fq_zech_ctx_t ctx; fq_nmod_ctx_t ctxn; 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_nmod_ctx_init(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(p); fmpz_clear(temp); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_zech_poly/profile/p-factor_vs_fq_nmod.c000066400000000000000000000062131414523752600231520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "fq_nmod_poly.h" #include "fq_zech_poly.h" #include "profiler.h" #define nalgs 2 #define cpumin 2 #define ncases 10 int main(int argc, char** argv) { fmpz_t 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); fmpz_init(p); fmpz_set_str(p, argv[1], 10); d = atol(argv[2]); len = atol(argv[3]); fq_nmod_ctx_init(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); fmpz_clear(p); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/fq_zech_poly/profile/p-factor_xnpxp1.c000066400000000000000000000010451414523752600222530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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-factor_xnpxp1.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/profile/p-gcd.c000066400000000000000000000010331414523752600202110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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-gcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/profile/p-is_irreducible.c000066400000000000000000000010461414523752600224440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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-is_irreducible.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/profile/p-iterated_frobenius.c000066400000000000000000000010521414523752600233320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/profile/p-iterated_frobenius_table.c000066400000000000000000000010601414523752600245000ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/profile/p-mullow.c000066400000000000000000000010361414523752600207760ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/profile/p-sqr.c000066400000000000000000000010331414523752600202610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/randtest.c000066400000000000000000000010261414523752600174050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/randtest.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/randtest_irreducible.c000066400000000000000000000010421414523752600217540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/randtest_irreducible.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/randtest_monic.c000066400000000000000000000010341414523752600205710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/randtest_monic.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/realloc.c000066400000000000000000000010251414523752600172010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/realloc.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/remove.c000066400000000000000000000010241414523752600170540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/remove.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/reverse.c000066400000000000000000000010251414523752600172330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/reverse.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/scalar_addmul_fq.c000066400000000000000000000010361414523752600210430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/scalar_addmul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/scalar_div_fq.c000066400000000000000000000010331414523752600203540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/scalar_div_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/scalar_mul_fq.c000066400000000000000000000010331414523752600203670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/scalar_mul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/scalar_submul_fq.c000066400000000000000000000010361414523752600211040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/scalar_submul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/set.c000066400000000000000000000010211414523752600163470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/set.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/set_coeff.c000066400000000000000000000010271414523752600175170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/set_coeff.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/set_fmpz_mod_poly.c000066400000000000000000000010411414523752600213070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/set_fmpz_mod_poly.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/set_fq.c000066400000000000000000000010241414523752600170400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/set_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/set_nmod_poly.c000066400000000000000000000010351414523752600204340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/set_nmod_poly.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/set_trunc.c000066400000000000000000000010271414523752600175700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/set_trunc.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/shift_left.c000066400000000000000000000010301414523752600177030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/shift_left.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/shift_right.c000066400000000000000000000010311414523752600200670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/shift_right.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/sqr.c000066400000000000000000000010211414523752600163610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/sqr.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/sqr_KS.c000066400000000000000000000010241414523752600167610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/sqr_KS.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/sqr_classical.c000066400000000000000000000010331414523752600204020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/sqr_classical.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/sub.c000066400000000000000000000010211414523752600163450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/sub.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/sub_series.c000066400000000000000000000010301414523752600177170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/sub_series.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/swap.c000066400000000000000000000010221414523752600165270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/swap.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/test/000077500000000000000000000000001414523752600163755ustar00rootroot00000000000000flint2-2.8.4/fq_zech_poly/test/t-add.c000066400000000000000000000010301414523752600175240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-add_series.c000066400000000000000000000010371414523752600211050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-compose.c000066400000000000000000000010341414523752600204450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-compose_divconquer.c000066400000000000000000000010471414523752600227100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_divconquer.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/test/t-compose_horner.c000066400000000000000000000010431414523752600220220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_horner.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/test/t-compose_mod.c000066400000000000000000000010401414523752600213010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-compose_mod_brent_kung.c000066400000000000000000000010531414523752600235230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-compose_mod_brent_kung_preinv.c000066400000000000000000000010621414523752600251060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-compose_mod_horner.c000066400000000000000000000010471414523752600226650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-compose_mod_horner_preinv.c000066400000000000000000000010561414523752600242500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-compose_mod_preinv.c000066400000000000000000000010471414523752600226730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-deflate.c000066400000000000000000000010341414523752600204040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-derivative.c000066400000000000000000000010371414523752600211450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-div_basecase.c000066400000000000000000000010411414523752600214060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_basecase.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/test/t-div_newton_n_preinv.c000066400000000000000000000010501414523752600230520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-div_series.c000066400000000000000000000010371414523752600211370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-divides.c000066400000000000000000000010341414523752600204270ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-divrem_basecase.c000066400000000000000000000010441414523752600221150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_basecase.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/test/t-divrem_divconquer.c000066400000000000000000000010461414523752600225300ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_divconquer.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/test/t-divrem_newton_n_preinv.c000066400000000000000000000010531414523752600235610ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-equal_trunc.c000066400000000000000000000010401414523752600213170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-evaluate_fq.c000066400000000000000000000010401414523752600212710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-evaluate_fq_vec_fast.c000066400000000000000000000012021414523752600231430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-gcd.c000066400000000000000000000010301414523752600175310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-gcd_euclidean.c000066400000000000000000000010421414523752600215450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/test/t-gcd_euclidean_f.c000066400000000000000000000010441414523752600220540ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-gcd_hgcd.c000066400000000000000000000010351414523752600205230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_hgcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/test/t-get_str.c000066400000000000000000000010341414523752600204470ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-get_str_pretty.c000066400000000000000000000010431414523752600220560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-hamming_weight.c000066400000000000000000000010431414523752600217670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-hgcd.c000066400000000000000000000010311414523752600177020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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-hgcd.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/test/t-inflate.c000066400000000000000000000010341414523752600204220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-inv_series_newton.c000066400000000000000000000010461414523752600225430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-make_monic.c000066400000000000000000000010371414523752600211050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-mul.c000066400000000000000000000010301414523752600175710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-mul_KS.c000066400000000000000000000010331414523752600201710ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-mul_classical.c000066400000000000000000000010421414523752600216120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-mulhigh.c000066400000000000000000000010341414523752600204350ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-mulhigh_classical.c000066400000000000000000000010461414523752600224560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-mullow.c000066400000000000000000000010331414523752600203160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-mullow_KS.c000066400000000000000000000010361414523752600207160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-mullow_classical.c000066400000000000000000000010451414523752600223370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-mulmod.c000066400000000000000000000010331414523752600202740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-mulmod_preinv.c000066400000000000000000000010421414523752600216570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-neg.c000066400000000000000000000010301414523752600175450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-pow.c000066400000000000000000000010301414523752600176010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-pow_trunc.c000066400000000000000000000010361414523752600210220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-pow_trunc_binexp.c000066400000000000000000000010451414523752600223670ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-powmod_fmpz_binexp.c000066400000000000000000000010471414523752600227120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-powmod_fmpz_binexp_preinv.c000066400000000000000000000010561414523752600242750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-powmod_fmpz_sliding_preinv.c000066400000000000000000000010571414523752600244420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-powmod_ui_binexp.c000066400000000000000000000010451414523752600223510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-powmod_ui_binexp_preinv.c000066400000000000000000000010541414523752600237340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-powmod_x_fmpz_preinv.c000066400000000000000000000010511414523752600232520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-randtest_irreducible.c000066400000000000000000000010511414523752600231740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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-randtest_irreducible.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/test/t-scalar_addmul_fq.c000066400000000000000000000010451414523752600222630ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-scalar_div_fq.c000066400000000000000000000010421414523752600215740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-scalar_mul_fq.c000066400000000000000000000010421414523752600216070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-scalar_submul_fq.c000066400000000000000000000010451414523752600223240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-set_fmpz_mod_poly.c000066400000000000000000000042601414523752600225350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #include #include #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_fmpz_poly... "); fflush(stdout); /* 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_randtest(ctx, state); fq_zech_init(r, ctx); fq_zech_init(s, ctx); fq_zech_poly_init(a, ctx); fmpz_mod_ctx_init(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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/fq_zech_poly/test/t-set_nmod_poly.c000066400000000000000000000010441414523752600216540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-set_trunc.c000066400000000000000000000010361414523752600210100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-shift_left_right.c000066400000000000000000000010451414523752600223260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-sqr.c000066400000000000000000000010301414523752600176010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-sqr_KS.c000066400000000000000000000010331414523752600202010ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-sqr_classical.c000066400000000000000000000010421414523752600216220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-sub.c000066400000000000000000000010301414523752600175650ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-sub_series.c000066400000000000000000000010371414523752600211460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/test/t-xgcd_euclidean.c000066400000000000000000000010431414523752600217360ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/test/t-xgcd_euclidean_f.c000066400000000000000000000010451414523752600222450ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_poly/tree.c000066400000000000000000000010221414523752600165140ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/tree.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/truncate.c000066400000000000000000000010261414523752600174060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/truncate.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/xgcd_euclidean.c000066400000000000000000000010341414523752600205160ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/xgcd_euclidean.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly/xgcd_euclidean_f.c000066400000000000000000000010361414523752600210250ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_templates/xgcd_euclidean_f.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor.h000066400000000000000000000024451414523752600171320ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #define FQ_ZECH_POLY_FACTOR_INLINE FLINT_DLL #else #define FQ_POLY_FACTOR_TEMPLATES_INLINE static __inline__ #define FQ_ZECH_POLY_FACTOR_INLINE static __inline__ #endif FQ_ZECH_POLY_FACTOR_INLINE int FQ_ZECH_POLY_ITERATED_FROBENIUS_CUTOFF(const fq_zech_ctx_t ctx, slong length) { int result; fmpz_t q; fmpz_init(q); fq_zech_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; } #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 FLINT_DLL 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 flint2-2.8.4/fq_zech_poly_factor/000077500000000000000000000000001414523752600167545ustar00rootroot00000000000000flint2-2.8.4/fq_zech_poly_factor/clear.c000066400000000000000000000010321414523752600202020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/concat.c000066400000000000000000000010331414523752600203640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/concat.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/factor.c000066400000000000000000000010331414523752600203730ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/factor.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/factor_berlekamp.c000066400000000000000000000010451414523752600224200ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/factor_berlekamp.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/factor_cantor_zassenhaus.c000066400000000000000000000010551414523752600242110ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/factor_cantor_zassenhaus.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/factor_distinct_deg.c000066400000000000000000000010501414523752600231120ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/factor_distinct_deg.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/factor_equal_deg.c000066400000000000000000000010451414523752600224040ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/factor_equal_deg.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/factor_equal_deg_prob.c000066400000000000000000000010521414523752600234240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/factor_equal_deg_prob.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/factor_kaltofen_shoup.c000066400000000000000000000010521414523752600234750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/factor_kaltofen_shoup.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/factor_split_single.c000066400000000000000000000010551414523752600231530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/factor_split_single.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/factor_squarefree.c000066400000000000000000000010461414523752600226210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/factor_squarefree.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/fit_length.c000066400000000000000000000010371414523752600212440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/fit_length.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/init.c000066400000000000000000000010311414523752600200560ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/init.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/inlines.c000066400000000000000000000014651414523752600205670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_ZECH_POLY_FACTOR_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #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); } flint2-2.8.4/fq_zech_poly_factor/insert.c000066400000000000000000000010331414523752600204210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/insert.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/is_irreducible.c000066400000000000000000000010431414523752600221020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/is_irreducible.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/is_irreducible_ben_or.c000066400000000000000000000010521414523752600234260ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/is_irreducible_ben_or.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/is_irreducible_ddf.c000066400000000000000000000010471414523752600227230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/is_irreducible_ddf.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/is_squarefree.c000066400000000000000000000010421414523752600217520ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/is_squarefree.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/iterated_frobenius_preinv.c000066400000000000000000000010561414523752600243620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/iterated_frobenius_preinv.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/pow.c000066400000000000000000000010301414523752600177170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/pow.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/print.c000066400000000000000000000010321414523752600202500ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/print.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/print_pretty.c000066400000000000000000000010411414523752600216570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/print_pretty.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/realloc.c000066400000000000000000000010341414523752600205370ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/realloc.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/roots.c000066400000000000000000000010351414523752600202650ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/roots.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/set.c000066400000000000000000000010301414523752600177050ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_poly_factor_templates/set.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_poly_factor/test/000077500000000000000000000000001414523752600177335ustar00rootroot00000000000000flint2-2.8.4/fq_zech_poly_factor/test/t-factor.c000066400000000000000000000010421414523752600216130ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-factor_berlekamp.c000066400000000000000000000010541414523752600236400ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-factor_cantor_zassenhaus.c000066400000000000000000000010641414523752600254310ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-factor_distinct_deg.c000066400000000000000000000010571414523752600243410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-factor_equal_deg_prob.c000066400000000000000000000010611414523752600246440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-factor_kaltofen_shoup.c000066400000000000000000000010611414523752600247150ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-factor_split_single.c000066400000000000000000000010641414523752600243730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-factor_squarefree.c000066400000000000000000000010551414523752600240410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-is_irreducible.c000066400000000000000000000010521414523752600233220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-is_irreducible_ben_or.c000066400000000000000000000010611414523752600246460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-is_irreducible_ddf.c000066400000000000000000000010561414523752600241430ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-is_squarefree.c000066400000000000000000000010511414523752600231720ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-iterated_frobenius_preinv.c000066400000000000000000000010651414523752600256020ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_poly_factor/test/t-roots.c000066400000000000000000000010441414523752600215050ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_poly.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 flint2-2.8.4/fq_zech_vec.h000066400000000000000000000027441414523752600153700ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #define FQ_ZECH_VEC_INLINE FLINT_DLL #else #define FQ_VEC_TEMPLATES_INLINE static __inline__ #define FQ_ZECH_VEC_INLINE static __inline__ #endif #include "fq_zech.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 flint2-2.8.4/fq_zech_vec/000077500000000000000000000000001414523752600152105ustar00rootroot00000000000000flint2-2.8.4/fq_zech_vec/add.c000066400000000000000000000010171414523752600161030ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/clear.c000066400000000000000000000010211414523752600164340ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/clear.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/dot.c000066400000000000000000000010171414523752600161410ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/dot.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/equal.c000066400000000000000000000010211414523752600164550ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/equal.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/fprint.c000066400000000000000000000010221414523752600166510ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/fprint.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/init.c000066400000000000000000000010201414523752600163100ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/init.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/inlines.c000066400000000000000000000010661414523752600170200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FQ_ZECH_VEC_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "fq_zech_vec.h" flint2-2.8.4/fq_zech_vec/is_zero.c000066400000000000000000000010231414523752600170220ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/is_zero.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/neg.c000066400000000000000000000010171414523752600161240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/neg.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/randtest.c000066400000000000000000000010241414523752600171750ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/randtest.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/scalar_addmul_fq.c000066400000000000000000000010341414523752600206330ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/scalar_addmul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/scalar_mul_fq.c000066400000000000000000000010311414523752600201570ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/scalar_mul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/scalar_submul_fq.c000066400000000000000000000010341414523752600206740ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/scalar_submul_fq.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/set.c000066400000000000000000000010171414523752600161460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/set.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/sub.c000066400000000000000000000010171414523752600161440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/sub.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/swap.c000066400000000000000000000010201414523752600163170ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/swap.c" #undef CAP_T #undef T flint2-2.8.4/fq_zech_vec/test/000077500000000000000000000000001414523752600161675ustar00rootroot00000000000000flint2-2.8.4/fq_zech_vec/test/t-add.c000066400000000000000000000010261414523752600173230ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_vec/test/t-is_zero.c000066400000000000000000000010321414523752600202420ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_vec/test/t-neg.c000066400000000000000000000010261414523752600173440ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_vec/test/t-sub.c000066400000000000000000000010261414523752600173640ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_vec/test/t-swap.c000066400000000000000000000010271414523752600175460ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_vec/test/t-zero.c000066400000000000000000000010271414523752600175530ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 flint2-2.8.4/fq_zech_vec/zero.c000066400000000000000000000010201414523752600163240ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_zech_vec.h" #ifdef T #undef T #endif #define T fq_zech #define CAP_T FQ_ZECH #include "fq_vec_templates/zero.c" #undef CAP_T #undef T flint2-2.8.4/fscanf.c000066400000000000000000000063001414523752600143370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/gettimeofday.c000066400000000000000000000013741414523752600155660ustar00rootroot00000000000000 #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; } flint2-2.8.4/gettimeofday.h000066400000000000000000000010371414523752600155670ustar00rootroot00000000000000/* * 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 */ }; FLINT_DLL int gettimeofday(struct timeval *tv, struct timezone *tz); #if defined(__cplusplus) } #endif #endif /* _TIMEVAL_H */ flint2-2.8.4/gmpcompat.h000066400000000000000000000656571414523752600151170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #ifndef GMP_COMPAT_H #define GMP_COMPAT_H #define FLINT_MPZ_REALLOC(z, len) \ ((len) > ((z)->_mp_alloc) \ ? (mp_ptr) _mpz_realloc(z, len) \ : ((z)->_mp_d)) #define FLINT_MPZ_PTR_SWAP(a, b) \ do { \ mpz_ptr __tmp = (a); \ (a) = (b); \ (b) = __tmp; \ } while (0) /* 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. */ /* 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 static __inline__ 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 */ count_leading_zeros (lshift, 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; } } #if WORD_MAX != LONG_MAX && !defined(__MPIR_VERSION) #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)) { printf("Exception (flint_mpz_pow_ui). Power too large.\n"); flint_abort(); } 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)) { printf("Exception (flint_mpz_fac_ui). Value n too large.\n"); flint_abort(); } 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)) { printf("Exception (flint_mpz_bin_uiui). Value n too large.\n"); flint_abort(); } if (k >= (UWORD(1) << 32)) { printf("Exception (flint_mpz_bin_uiui). Value k too large.\n"); flint_abort(); } 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)) { printf("Exception (flint_mpz_fib_ui). Value n too large.\n"); flint_abort(); } 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); } #else #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 #endif #if WORD_MAX == LONG_MAX #define flint_mpf_get_d_2exp mpf_get_d_2exp #else /* 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. */ /* This function is only required for MPIR >= 3.0.0 and for GMP, but we include unconditionally when sizeof(ulong) != sizeof(unsigned long) */ 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); count_leading_zeros (cnt, 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 #endif flint2-2.8.4/gpl-2.0.txt000066400000000000000000000432541414523752600145640ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) 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 this service 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 make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. 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. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the 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 a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE 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. 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 convey 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This 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. flint2-2.8.4/hashmap.c000066400000000000000000000061771414523752600145340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "hashmap.h" void hashmap1_init(hashmap1_t h) { h->data = (hashmap1_elem_s *) flint_calloc(HASHMAP_START_SIZE, sizeof(hashmap1_elem_s)); h->alloc = HASHMAP_START_SIZE; h->mask = HASHMAP_START_MASK; h->num_used = 0; } void hashmap1_init2(hashmap1_t h, slong size) { slong bits = 10; if (2*size >= 0) size *= 2; while ((WORD(1) << bits) < size) bits++; h->alloc = (WORD(1) << bits); h->mask = h->alloc - 1; h->num_used = 0; h->data = (hashmap1_elem_s *) flint_calloc(h->alloc, sizeof(hashmap1_elem_s)); } void hashmap1_clear(hashmap1_t h) { flint_free(h->data); } /* find location in data to store value with 1 word key */ slong hashmap1_hash(ulong key, hashmap1_t h) { slong loc, i; if (h->num_used == h->alloc/2) return -WORD(1); /* hashmap is full */ loc = (slong) hashmap1_hash_key(key, h); for (i = 0; i < h->alloc; i++) { if (h->data[loc].in_use == 0 || h->data[loc].key == key) return loc; loc++; if (loc == h->alloc) loc = 0; } return -WORD(1); /* map needs rehashing */ } /* rehash a full hashmap to twice current size */ void hashmap1_rehash(hashmap1_t h) { slong i; hashmap1_elem_s * tmp; tmp = h->data; h->data = (hashmap1_elem_s *) flint_calloc(2*h->alloc, sizeof(hashmap1_elem_s)); h->alloc = 2*h->alloc; h->mask = h->alloc - 1; h->num_used = 0; for (i = 0; i < h->alloc/2; i++) { if (tmp[i].in_use == 1) hashmap1_insert(tmp[i].key, tmp[i].value, h); } flint_free(tmp); } /* insert key, value pair into hashmap */ void hashmap1_insert(ulong key, void * value, hashmap1_t h) { slong loc; loc = hashmap1_hash(key, h); if (loc == -WORD(1)) { hashmap1_rehash(h); loc = hashmap1_hash(key, h); if (loc == -WORD(1)) { /* should never be reached */ flint_printf("Rehashing unsuccessful\n"); flint_abort(); } } h->data[loc].value = value; h->data[loc].key = key; h->data[loc].in_use = 1; h->num_used += 1; } /* set *ptr to location of value corresponding to key in hashmap return 1 if found, otherwise return 0 (in which case *ptr = NULL) */ int hashmap1_find(void ** ptr, ulong key, hashmap1_t h) { slong i, loc; loc = hashmap1_hash_key(key, h); for (i = 0; i < h->alloc; i++) { if (h->data[loc].in_use == 0) { (*ptr) = NULL; return 0; } if (h->data[loc].key == key) { (*ptr) = h->data[loc].value; return 1; } loc++; if (loc == h->alloc) loc = 0; } (*ptr) = NULL; return 0; } flint2-2.8.4/hashmap.h000066400000000000000000000050771414523752600145370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef HASHMAP_H #define HASHMAP_H #include "flint.h" #define HASHMAP_START_SIZE 1024 #define HASHMAP_START_MASK (HASHMAP_START_SIZE - 1) /****************************************************************************** Hashmap types with one word key ******************************************************************************/ typedef struct hashmap1_elem_s { ulong key; void * value; int in_use; } hashmap1_elem_s; typedef struct hashmap1_s { slong alloc; slong num_used; ulong mask; hashmap1_elem_s * data; } hashmap1_s; typedef hashmap1_s hashmap1_t[1]; /****************************************************************************** Hash functions ******************************************************************************/ /* from lookup3.c, by Bob Jenkins, May 2006, Public Domain. */ #define hash_rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) #define hash_mix(a,b,c) \ { \ c ^= b; c -= hash_rot(b, 14); \ a ^= c; a -= hash_rot(c, 11); \ b ^= a; b -= hash_rot(a, 25); \ c ^= b; c -= hash_rot(b, 16); \ a ^= c; a -= hash_rot(c, 4); \ b ^= a; b -= hash_rot(a, 14); \ c ^= b; c -= hash_rot(b, 24); \ } /* End of Public Domain code. */ #if FLINT64 static __inline__ ulong hash_word(ulong val) { int * ptr = (int * ) &val; int a = ptr[0], b = ptr[1], c = 0; hash_mix(a, b, c); ptr[0] = b; ptr[1] = c; return val; } #else static __inline__ ulong hash_word(ulong a) { int b = 0, c = 0; hash_mix(a, b, c); return c; } #endif /****************************************************************************** Hashmap functions with one word key ******************************************************************************/ FLINT_DLL void hashmap1_init(hashmap1_t h); FLINT_DLL void hashmap1_init2(hashmap1_t h, slong size); FLINT_DLL void hashmap1_clear(hashmap1_t h); static __inline__ ulong hashmap1_hash_key(ulong key, hashmap1_t h) { return hash_word(key) & h->mask; } FLINT_DLL slong hashmap1_hash(ulong key, hashmap1_t h); FLINT_DLL void hashmap1_rehash(hashmap1_t h); FLINT_DLL void hashmap1_insert(ulong key, void * value, hashmap1_t h); FLINT_DLL int hashmap1_find(void ** ptr, ulong key, hashmap1_t h); #endif flint2-2.8.4/inlines.c000066400000000000000000000006711414523752600145450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define FLINT_INLINES_C #include #include "flint.h" flint2-2.8.4/interfaces/000077500000000000000000000000001414523752600150575ustar00rootroot00000000000000flint2-2.8.4/interfaces/NTL-interface.cpp000066400000000000000000000210271414523752600201600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "NTL-interface.h" #define ZZ_SIZE(p) (((slong *) (p))[1]) #define ZZ_DATA(p) ((mp_limb_t *) (((slong *) (p)) + 2)) NTL_CLIENT static void fmpz_set_limbs(fmpz_t f, mp_srcptr x, mp_size_t limbs) { if (limbs == 0) fmpz_zero(f); else if (limbs == 1) fmpz_set_ui(f, x[0]); else { __mpz_struct *mpz_ptr = _fmpz_promote(f); mpz_import(mpz_ptr, limbs, -1, sizeof(mp_limb_t), 0, 0, x); } } 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 = ZZ_DATA(x); fmpz_set_limbs(rop, xp, lw); if (op < WORD(0)) fmpz_neg(rop, rop); } } void fmpz_set_ZZ_p(fmpz_t rop, const ZZ_p& op) { fmpz_set_ZZ(rop, rep(op)); } void fmpz_set_zz_p(fmpz_t rop, const zz_p& op) { fmpz_set_si(rop, rep(op)); } void fmpz_get_ZZ(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) ZZ_SIZE(*x) = 0; return; } _ntl_gsetlength(x, lw); xp = ZZ_DATA(*x); 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) ZZ_SIZE(*x) = -lw; else ZZ_SIZE(*x) = lw; } void fmpz_get_ZZ_p(ZZ_p& rop, const fmpz_t op) { ZZ a; fmpz_get_ZZ(a, op); conv(rop, a); } void fmpz_get_zz_p(zz_p& rop, const fmpz_t op) { conv(rop, fmpz_get_si(op)); } void fmpz_poly_get_ZZX(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); } } } void fmpz_poly_set_ZZX(fmpz_poly_t rop, const 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); } } } void fmpz_mod_poly_get_ZZ_pX(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); } } } void fmpz_mod_poly_set_ZZ_pX(fmpz_mod_poly_t rop, const 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); } } } void fmpz_mod_poly_get_zz_pX(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); } } } void fmpz_mod_poly_set_zz_pX(fmpz_mod_poly_t rop, const 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); } } } void fq_get_ZZ_pE(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); } } void fq_set_ZZ_pE(fq_t rop, const 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); } } void fq_poly_get_ZZ_pEX(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); } } } void fq_poly_set_ZZ_pEX(fq_poly_t rop, const 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); } } /* ----------------------------------------- */ void fq_get_zz_pE(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); } } void fq_set_zz_pE(fq_t rop, const 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); } } void fq_poly_get_zz_pEX(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); } } } void fq_poly_set_zz_pEX(fq_poly_t rop, const 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); } } #undef ZZ_SIZE #undef ZZ_DATA flint2-2.8.4/interfaces/doc/000077500000000000000000000000001414523752600156245ustar00rootroot00000000000000flint2-2.8.4/interfaces/doc/interfaces.txt000066400000000000000000000070601414523752600205130ustar00rootroot00000000000000/* 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 2.1 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. The interface is built using C$++$ and is not built as a part of the FLINT library library by default. To build the NTL interface one must specify the location of NTL with the \code{--with-ntl=path} option to configure. 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}. flint2-2.8.4/interfaces/test/000077500000000000000000000000001414523752600160365ustar00rootroot00000000000000flint2-2.8.4/interfaces/test/t-NTL-interface.cpp000066400000000000000000000325001414523752600213760ustar00rootroot00000000000000/* Copyright (C) 2011 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "fmpz_mod_poly.h" #include "ulong_extras.h" #include "NTL-interface.h" NTL_CLIENT int test_ZZ_to_fmpz() { int i, result; mp_bitcnt_t bits, randbits; fmpz_t int1, int2; ZZ z; FLINT_TEST_INIT(state); flint_printf("ZZ_to_fmpz...."); fflush(stdout); /* Check conversion */ for (i = 0; i < 10000; 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"); return 0; } fmpz_clear(int1); fmpz_clear(int2); } FLINT_TEST_CLEANUP(state); return 1; } int test_ZZX_to_fmpz_poly() { fmpz_poly_t f_poly1, f_poly2; slong length; mp_bitcnt_t bits; int i, result; FLINT_TEST_INIT(state); flint_printf("ZZX_to_fmpz_poly...."); fflush(stdout); /* Check aliasing of a and c */ for (i = 0; i < 10000; 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"); return 0; } fmpz_poly_clear(f_poly1); fmpz_poly_clear(f_poly2); } FLINT_TEST_CLEANUP(state); return 1; } int test_ZZ_pX_to_fmpz_mod_poly() { fmpz_t p; fmpz_mod_poly_t f_poly1, f_poly2; fmpz_mod_ctx_t ctx; slong length; int i, result; FLINT_TEST_INIT(state); flint_printf("ZZ_pX_to_fmpz_mod_poly...."); fflush(stdout); fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of a and c */ for (i = 0; i < 10000; 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"); return 0; } fmpz_clear(p); fmpz_mod_poly_clear(f_poly1, ctx); fmpz_mod_poly_clear(f_poly2, ctx); } fmpz_mod_ctx_clear(ctx); FLINT_TEST_CLEANUP(state); return 1; } int test_zz_pX_to_fmpz_mod_poly() { fmpz_mod_poly_t f_poly1, f_poly2; fmpz_mod_ctx_t ctx; slong length; int i, result; FLINT_TEST_INIT(state); flint_printf("zz_pX_to_fmpz_mod_poly...."); fflush(stdout); fmpz_mod_ctx_init_ui(ctx, 2); /* Check aliasing of a and c */ for (i = 0; i < 10000; 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"); return 0; } fmpz_mod_poly_clear(f_poly1, ctx); fmpz_mod_poly_clear(f_poly2, ctx); } fmpz_mod_ctx_clear(ctx); FLINT_TEST_CLEANUP(state); return 1; } int test_ZZ_pE_to_fq() { fq_t f1, f2; int i, result; fmpz_mod_ctx_t ctxp; fq_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("ZZ_pE_to_fq...."); fflush(stdout); fmpz_mod_ctx_init_ui(ctxp, 2); /* Check aliasing of a and c */ for (i = 0; i < 10000; 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"); return 0; } fq_clear(f1, ctx); fq_clear(f2, ctx); fq_ctx_clear(ctx); fmpz_mod_poly_clear(fmod, ctxp); } fmpz_mod_ctx_clear(ctxp); FLINT_TEST_CLEANUP(state); return 1; } int test_ZZ_pEX_to_fq_poly() { fq_poly_t f1, f2; slong length; int i, result; fmpz_mod_ctx_t ctxp; fq_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("ZZ_pEX_to_fq_poly...."); fflush(stdout); fmpz_mod_ctx_init_ui(ctxp, 2); for (i = 0; i < 10000; 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"); return 0; } 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); FLINT_TEST_CLEANUP(state); return 1; } int test_zz_pE_to_fq() { fq_t f1, f2; int i, result; fmpz_mod_ctx_t ctxp; fq_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("zz_pE_to_fq...."); fflush(stdout); fmpz_mod_ctx_init_ui(ctxp, 2); /* Check aliasing of a and c */ for (i = 0; i < 10000; 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"); return 0; } fq_clear(f1, ctx); fq_clear(f2, ctx); fq_ctx_clear(ctx); fmpz_mod_poly_clear(fmod, ctxp); } fmpz_mod_ctx_clear(ctxp); FLINT_TEST_CLEANUP(state); return 1; } int test_zz_pEX_to_fq_poly() { fq_poly_t f1, f2; slong length; int i, result; fmpz_mod_ctx_t ctxp; fq_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("zz_pEX_to_fq_poly...."); fflush(stdout); fmpz_mod_ctx_init_ui(ctxp, 2); for (i = 0; i < 10000; 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"); return 0; } 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); FLINT_TEST_CLEANUP(state); return 1; } int main(void) { int r = 1; if ((r &= test_ZZ_to_fmpz())) flint_printf("PASS\n"); if ((r &= test_ZZX_to_fmpz_poly())) flint_printf("PASS\n"); if ((r &= test_ZZ_pX_to_fmpz_mod_poly())) flint_printf("PASS\n"); if ((r &= test_ZZ_pE_to_fq())) flint_printf("PASS\n"); if ((r &= test_ZZ_pEX_to_fq_poly())) flint_printf("PASS\n"); if ((r &= test_zz_pX_to_fmpz_mod_poly())) flint_printf("PASS\n"); if ((r &= test_zz_pE_to_fq())) flint_printf("PASS\n"); if ((r &= test_zz_pEX_to_fq_poly())) flint_printf("PASS\n"); if (!r) abort(); return 0; } flint2-2.8.4/long_extras.h000066400000000000000000000037121414523752600154350ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define LONG_EXTRAS_INLINE static __inline__ #endif #include #include "flint.h" #include "longlong.h" #ifdef __cplusplus extern "C" { #endif /* Properties ****************************************************************/ FLINT_DLL 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 ************************************************************/ FLINT_DLL mp_limb_signed_t z_randtest(flint_rand_t state); FLINT_DLL mp_limb_signed_t z_randtest_not_zero(flint_rand_t state); FLINT_DLL mp_limb_signed_t z_randint(flint_rand_t state, mp_limb_t limit); /*****************************************************************************/ FLINT_DLL int z_kronecker(slong a, slong n); #ifdef __cplusplus } #endif #endif flint2-2.8.4/long_extras/000077500000000000000000000000001414523752600152615ustar00rootroot00000000000000flint2-2.8.4/long_extras/inlines.c000066400000000000000000000010661414523752600170710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define LONG_EXTRAS_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "long_extras.h" flint2-2.8.4/long_extras/kronecker.c000066400000000000000000000020611414523752600174070ustar00rootroot00000000000000/* 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 2.1 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; count_trailing_zeros(en, 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); } flint2-2.8.4/long_extras/randint.c000066400000000000000000000014141414523752600170640ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/long_extras/randtest.c000066400000000000000000000024341414523752600172540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/long_extras/sizeinbase.c000066400000000000000000000016741414523752600175710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/long_extras/test/000077500000000000000000000000001414523752600162405ustar00rootroot00000000000000flint2-2.8.4/long_extras/test/t-kronecker.c000066400000000000000000000024421414523752600206320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { slong i; mpz_t aa, nn; FLINT_TEST_INIT(state); flint_printf("kronecker...."); fflush(stdout); 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)) { flint_printf("FAIL:\n"); flint_printf("a = %wd, n = %wd\n", a, n); flint_abort(); } } mpz_clear(aa); mpz_clear(nn); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/long_extras/test/t-sizeinbase.c000066400000000000000000000026401414523752600210030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "fmpz.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sizeinbase...."); fflush(stdout); 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) { 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); abort(); } mpz_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/longlong.h000066400000000000000000001156511414523752600147350ustar00rootroot00000000000000/* 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 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 /* Undefine to make the ifndef logic below for the fallback work even if the symbols are already defined (e.g. by givaro). */ #undef count_leading_zeros #undef count_trailing_zeros /* 1 if we know that the hardware is strongly-ordered */ #define FLINT_KNOW_STRONG_ORDER 0 /* x86 : 64 bit */ #if (GMP_LIMB_BITS == 64 && defined (__amd64__)) #undef FLINT_KNOW_STRONG_ORDER #define FLINT_KNOW_STRONG_ORDER 1 #define add_ssssaaaaaaaa(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \ __asm__ ("addq %11,%q3\n\tadcq %9,%q2\n\tadcq %7,%q1\n\tadcq %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 add_sssaaaaaa(sh, sm, sl, ah, am, al, bh, bm, bl) \ __asm__ ("addq %8,%q2\n\tadcq %6,%q1\n\tadcq %4,%q0" \ : "=r" (sh), "=&r" (sm), "=&r" (sl) \ : "0" ((mp_limb_t)(ah)), "rme" ((mp_limb_t)(bh)), \ "1" ((mp_limb_t)(am)), "rme" ((mp_limb_t)(bm)), \ "2" ((mp_limb_t)(al)), "rme" ((mp_limb_t)(bl))) \ #define sub_dddmmmsss(dh, dm, dl, mh, mm, ml, sh, sm, sl) \ __asm__ ("subq %8,%q2\n\tsbbq %6,%q1\n\tsbbq %4,%q0" \ : "=r" (dh), "=&r" (dm), "=&r" (dl) \ : "0" ((mp_limb_t)(mh)), "rme" ((mp_limb_t)(sh)), \ "1" ((mp_limb_t)(mm)), "rme" ((mp_limb_t)(sm)), \ "2" ((mp_limb_t)(ml)), "rme" ((mp_limb_t)(sl))) \ #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addq %5,%q1\n\tadcq %3,%q0" \ : "=r" (sh), "=&r" (sl) \ : "0" ((mp_limb_t)(ah)), "rme" ((mp_limb_t)(bh)), \ "%1" ((mp_limb_t)(al)), "rme" ((mp_limb_t)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subq %5,%q1\n\tsbbq %3,%q0" \ : "=r" (sh), "=&r" (sl) \ : "0" ((mp_limb_t)(ah)), "rme" ((mp_limb_t)(bh)), \ "1" ((mp_limb_t)(al)), "rme" ((mp_limb_t)(bl))) #define umul_ppmm(w1, w0, u, v) \ __asm__ ("mulq %3" \ : "=a" (w0), "=d" (w1) \ : "%0" ((mp_limb_t)(u)), "rm" ((mp_limb_t)(v))) #define smul_ppmm(w1, w0, u, v) \ __asm__ ("imulq %3" \ : "=a" (w0), "=d" (w1) \ : "%0" ((mp_limb_t)(u)), "rm" ((mp_limb_t)(v))) #define udiv_qrnnd(q, r, n1, n0, dx) \ __asm__ volatile ("divq %4" \ : "=a" (q), "=d" (r) \ : "0" ((mp_limb_t)(n0)), "1" ((mp_limb_t)(n1)), "rm" ((mp_limb_t)(dx))) #define sdiv_qrnnd(q, r, n1, n0, dx) \ __asm__ volatile ("idivq %4" \ : "=a" (q), "=d" (r) \ : "0" ((mp_limb_t)(n0)), "1" ((mp_limb_t)(n1)), "rm" ((mp_limb_t)(dx))) /* bsrq destination must be a 64-bit register, hence mp_limb_t for __cbtmp. */ #define count_leading_zeros(count, x) \ do { \ mp_limb_t __cbtmp; \ FLINT_ASSERT ((x) != 0); \ __asm__ ("bsrq %1,%0" : "=r" (__cbtmp) : "rm" ((mp_limb_t)(x))); \ (count) = __cbtmp ^ (mp_limb_t) 63; \ } while (0) /* bsfq destination must be a 64-bit register, "%q0" forces this in case count is only an int. */ #define count_trailing_zeros(count, x) \ do { \ FLINT_ASSERT ((x) != 0); \ __asm__ ("bsfq %1,%q0" : "=r" (count) : "rm" ((mp_limb_t)(x))); \ } while (0) #define byte_swap(x) \ do { \ __asm__("bswapq %q0" : "=r"(x) : "0"(x)); \ } while (0) #endif /* x86_64 */ /* x86 : 32 bit */ #if (GMP_LIMB_BITS == 32 && (defined (__i386__) \ || defined (__i486__) || defined(__amd64__))) #undef FLINT_KNOW_STRONG_ORDER #define FLINT_KNOW_STRONG_ORDER 1 #define add_ssssaaaaaaaa(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \ __asm__ ("addl %11,%k3\n\tadcl %9,%k2\n\tadcl %7,%k1\n\tadcl %5,%k0" \ : "=r" (s3), "=&r" (s2), "=&r" (s1), "=&r" (s0) \ : "0" ((mp_limb_t)(a3)), "g" ((mp_limb_t)(b3)), \ "1" ((mp_limb_t)(a2)), "g" ((mp_limb_t)(b2)), \ "2" ((mp_limb_t)(a1)), "g" ((mp_limb_t)(b1)), \ "3" ((mp_limb_t)(a0)), "g" ((mp_limb_t)(b0))) \ #define add_sssaaaaaa(sh, sm, sl, ah, am, al, bh, bm, bl) \ __asm__ ("addl %8,%k2\n\tadcl %6,%k1\n\tadcl %4,%k0" \ : "=r" (sh), "=r" (sm), "=&r" (sl) \ : "0" ((mp_limb_t)(ah)), "g" ((mp_limb_t)(bh)), \ "1" ((mp_limb_t)(am)), "g" ((mp_limb_t)(bm)), \ "2" ((mp_limb_t)(al)), "g" ((mp_limb_t)(bl))) \ #define sub_dddmmmsss(dh, dm, dl, mh, mm, ml, sh, sm, sl) \ __asm__ ("subl %8,%k2\n\tsbbl %6,%k1\n\tsbbl %4,%k0" \ : "=r" (dh), "=r" (dm), "=&r" (dl) \ : "0" ((mp_limb_t)(mh)), "g" ((mp_limb_t)(sh)), \ "1" ((mp_limb_t)(mm)), "g" ((mp_limb_t)(sm)), \ "2" ((mp_limb_t)(ml)), "g" ((mp_limb_t)(sl))) \ #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addl %5,%k1\n\tadcl %3,%k0" \ : "=r" (sh), "=&r" (sl) \ : "0" ((mp_limb_t)(ah)), "g" ((mp_limb_t)(bh)), \ "%1" ((mp_limb_t)(al)), "g" ((mp_limb_t)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subl %5,%k1\n\tsbbl %3,%k0" \ : "=r" (sh), "=&r" (sl) \ : "0" ((mp_limb_t)(ah)), "g" ((mp_limb_t)(bh)), \ "1" ((mp_limb_t)(al)), "g" ((mp_limb_t)(bl))) #define umul_ppmm(w1, w0, u, v) \ __asm__ ("mull %3" \ : "=a" (w0), "=d" (w1) \ : "%0" ((mp_limb_t)(u)), "rm" ((mp_limb_t)(v))) #define smul_ppmm(w1, w0, u, v) \ __asm__ ("imull %3" \ : "=a" (w0), "=d" (w1) \ : "%0" ((mp_limb_t)(u)), "rm" ((mp_limb_t)(v))) #define udiv_qrnnd(q, r, n1, n0, dx) \ __asm__ volatile ("divl %4" \ : "=a" (q), "=d" (r) \ : "0" ((mp_limb_t)(n0)), "1" ((mp_limb_t)(n1)), "rm" ((mp_limb_t)(dx))) #define sdiv_qrnnd(q, r, n1, n0, dx) \ __asm__ volatile ("idivl %4" \ : "=a" (q), "=d" (r) \ : "0" ((mp_limb_t)(n0)), "1" ((mp_limb_t)(n1)), "rm" ((mp_limb_t)(dx))) #define count_leading_zeros(count, x) \ do { \ mp_limb_t __cbtmp; \ FLINT_ASSERT ((x) != 0); \ __asm__ ("bsrl %1,%0" : "=r" (__cbtmp) : "rm" ((mp_limb_t)(x))); \ (count) = __cbtmp ^ (mp_limb_t) 31; \ } while (0) #define count_trailing_zeros(count, x) \ do { \ FLINT_ASSERT ((x) != 0); \ __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((mp_limb_t)(x))); \ } while (0) #define byte_swap(x) \ do { \ __asm__("bswap %0" : "=r"(x) : "0"(x)); \ } while (0) #endif /* x86 */ /* Itanium */ #if (GMP_LIMB_BITS == 64 && defined (__ia64)) /* This form encourages gcc (pre-release 3.4 at least) to emit predicated "sub r=r,r" and "sub r=r,r,1", giving a 2 cycle latency. The generic code using "al> (GMP_LIMB_BITS / 2)) #define __highbit (~(mp_limb_t)0 ^ ((~(mp_limb_t)0) >> 1)) #ifndef NEED_CLZ_TAB #define NEED_CLZ_TAB #endif #if !(GMP_LIMB_BITS == 32 && defined (__arm__)) #if !(GMP_LIMB_BITS == 64 && defined (__ia64)) #if !defined(__arm64__) #define umul_ppmm(w1, w0, u, v) \ do { \ mp_limb_t __x0, __x1, __x2, __x3; \ mp_limb_t __ul, __vl, __uh, __vh; \ mp_limb_t __u = (u), __v = (v); \ \ __ul = __ll_lowpart (__u); \ __uh = __ll_highpart (__u); \ __vl = __ll_lowpart (__v); \ __vh = __ll_highpart (__v); \ \ __x0 = (mp_limb_t) __ul * __vl; \ __x1 = (mp_limb_t) __ul * __vh; \ __x2 = (mp_limb_t) __uh * __vl; \ __x3 = (mp_limb_t) __uh * __vh; \ \ __x1 += __ll_highpart (__x0);/* this can't give carry */ \ __x1 += __x2; /* but this indeed can */ \ if (__x1 < __x2) /* did we get it? */ \ __x3 += __ll_B; /* yes, add it in the proper pos. */ \ \ (w1) = __x3 + __ll_highpart (__x1); \ (w0) = (__x1 << GMP_LIMB_BITS/2) + __ll_lowpart (__x0); \ } while (0) #endif #endif #endif #if !(GMP_LIMB_BITS == 32 && defined (__arm__)) #if !defined(__arm64__) #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ do { \ mp_limb_t __x; \ __x = (al) + (bl); \ (sh) = (ah) + (bh) + (__x < (al)); \ (sl) = __x; \ } while (0) #endif #endif #if !defined(__arm64__) #define add_sssaaaaaa(sh, sm, sl, ah, am, al, bh, bm, bl) \ do { \ mp_limb_t __t, __u; \ add_ssaaaa(__t, sl, (mp_limb_t) 0, al, (mp_limb_t) 0, bl); \ add_ssaaaa(__u, sm, (mp_limb_t) 0, am, (mp_limb_t) 0, bm); \ add_ssaaaa(sh, sm, ah + bh, sm, __u, __t); \ } while (0) #define add_ssssaaaaaaaa(s3, s2, s1, s0, a3, a2, a1, a0, b3, b2, b1, b0) \ do { \ mp_limb_t __tt; \ add_sssaaaaaa(__tt, 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, __tt); \ } while (0) #endif #if !((GMP_LIMB_BITS == 64 && defined (__ia64)) || \ (GMP_LIMB_BITS == 32 && defined (__arm__))) #if !defined(__arm64__) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ do { \ mp_limb_t __x; \ __x = (al) - (bl); \ (sh) = (ah) - (bh) - ((al) < (bl)); \ (sl) = __x; \ } while (0) #endif #endif #if !defined(__arm64__) #define sub_dddmmmsss(dh, dm, dl, mh, mm, ml, sh, sm, sl) \ do { \ mp_limb_t __t, __u; \ sub_ddmmss(__t, dl, (mp_limb_t) 0, ml, (mp_limb_t) 0, sl); \ sub_ddmmss(__u, dm, (mp_limb_t) 0, mm, (mp_limb_t) 0, sm); \ sub_ddmmss(dh, dm, (mh) - (sh), dm, -__u, -__t); \ } while (0) #endif /* MIPS and ARM - Use clz builtins */ /* NOTE: Apple clang version 12.0.5 miscompiles the count_leading_zeros fallback */ #if (defined (__mips__) || defined (__arm__) || defined (__arm64__)) #ifdef _LONG_LONG_LIMB #define count_leading_zeros(count,x) \ do { \ FLINT_ASSERT ((x) != 0); \ (count) = __builtin_clzll (x); \ } while (0) #else #define count_leading_zeros(count,x) \ do { \ FLINT_ASSERT ((x) != 0); \ (count) = __builtin_clzl (x); \ } while (0) #endif #ifdef _LONG_LONG_LIMB #define count_trailing_zeros(count,x) \ do { \ FLINT_ASSERT ((x) != 0); \ (count) = __builtin_ctzll (x); \ } while (0) #else #define count_trailing_zeros(count,x) \ do { \ FLINT_ASSERT ((x) != 0); \ (count) = __builtin_ctzl (x); \ } while (0) #endif #endif /* MIPS, ARM */ #define udiv_qrnnd_int(q, r, n1, n0, d) \ do { \ mp_limb_t __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) #ifndef count_leading_zeros #define count_leading_zeros(count, x) \ do { \ mp_limb_t __xr = (x); \ mp_limb_t __a; \ \ if (GMP_LIMB_BITS == 32) \ { \ __a = __xr < ((mp_limb_t) 1 << 2*__BITS4) \ ? (__xr < ((mp_limb_t) 1 << __BITS4) ? 1 : __BITS4 + 1) \ : (__xr < ((mp_limb_t) 1 << 3*__BITS4) ? 2*__BITS4 + 1 \ : 3*__BITS4 + 1); \ } \ else \ { \ for (__a = GMP_LIMB_BITS - 8; __a > 0; __a -= 8) \ if (((__xr >> __a) & 0xff) != 0) \ break; \ ++__a; \ } \ \ (count) = GMP_LIMB_BITS + 1 - __a - __flint_clz_tab[__xr >> __a]; \ } while (0) #endif #if !(GMP_LIMB_BITS == 64 && defined (__ia64)) #ifndef count_trailing_zeros #define count_trailing_zeros(count, x) \ do { \ mp_limb_t __ctz_x = (x); \ mp_limb_t __ctz_c; \ FLINT_ASSERT (__ctz_x != 0); \ count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ (count) = GMP_LIMB_BITS - 1 - __ctz_c; \ } while (0) #endif #endif #define udiv_qrnnd(q, r, n1, n0, d) \ do { \ mp_limb_t __norm; \ count_leading_zeros(__norm, (d)); \ if (__norm) \ { \ udiv_qrnnd_int((q), (r), ((n1) << __norm) + ((n0) >> (GMP_LIMB_BITS - __norm)), (n0) << __norm, (d) << __norm); \ (r) = ((mp_limb_t) (r) >> __norm); \ } else \ udiv_qrnnd_int((q), (r), (n1), (n0), (d)); \ } while (0) #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) #if GMP_LIMB_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 /* 64 bits */ #endif /* non x86 fallback code */ /* smul_ppm is defined previously for 32bit arm and for all x86 */ #if !( (GMP_LIMB_BITS == 32 && defined (__arm__)) \ || defined (__i386__) || defined (__i486__) || defined(__amd64__)) #if !defined(__arm64__) #define smul_ppmm(w1, w0, u, v) \ do { \ mp_limb_t __w1; \ mp_limb_t __xm0 = (u), __xm1 = (v); \ umul_ppmm (__w1, w0, __xm0, __xm1); \ (w1) = __w1 - (-(__xm0 >> (FLINT_BITS-1)) & __xm1) \ - (-(__xm1 >> (FLINT_BITS-1)) & __xm0); \ } while (0) #endif #endif #if GMP_LIMB_BITS == 32 /* rec_word_tab[i] = div(2^24 - 2^14 + 2^9, 2^9 + i) */ static const int 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)<<(GMP_LIMB_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 int 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)<<(GMP_LIMB_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 */ /* Branch free variant */ #if 1 #define udiv_qrnnd_preinv(q, r, nh, nl, d, di) \ do { \ mp_limb_t _n2, _n10, _nmask, _nadj, _q1; \ mp_limb_t _xh, _xl; \ _n2 = (nh); \ _n10 = (nl); \ _nmask = (mp_limb_signed_t) (_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) /* Branched variant, slower on K10 for general inputs */ #else #define udiv_qrnnd_preinv(q, r, nh, nl, d, di) \ do { \ mp_limb_t _q, _ql, _r; \ mp_limb_t _xh, _xl; \ FLINT_ASSERT ((d) != 0); \ umul_ppmm (_q, _ql, (nh), (di)); \ _q += (nh); /* Compensate, di is 2^64 too small */ \ umul_ppmm (_xh, _xl, _q, (d)); \ sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl); \ if (_xh != 0) \ { \ sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ _q += 1; \ if (_xh != 0) \ { \ _r -= (d); \ _q += 1; \ } \ } \ if (_r >= (d)) \ { \ _r -= (d); \ _q += 1; \ } \ (r) = _r; \ (q) = _q; \ } while (0) #endif #ifdef __cplusplus } #endif #endif flint2-2.8.4/memory_manager.c000066400000000000000000000121111414523752600160760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson Copyright (C) 2016 Claus Fieker 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "thread_pool.h" #if FLINT_USES_GC #include "gc.h" #endif 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_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 FLINT_REENTRANT && !FLINT_USES_TLS #include 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() { pthread_mutex_init(&alloc_func_lock, NULL); } #endif static void flint_memory_error(size_t size) { flint_printf("Exception (FLINT memory_manager). Unable to allocate memory (%ld).\n", size); fflush(stdout); flint_abort(); } 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 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; #if FLINT_REENTRANT && !FLINT_USES_TLS pthread_mutex_unlock(&alloc_func_lock); #endif } 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); } 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 void register_init() { pthread_mutex_init(®ister_lock, NULL); } #endif void flint_register_cleanup_function(flint_cleanup_function_t cleanup_function) { #if FLINT_REENTRANT && !FLINT_USES_TLS 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 pthread_mutex_unlock(®ister_lock); #endif } void _fmpz_cleanup(); void _flint_cleanup() { size_t i; #if FLINT_REENTRANT && !FLINT_USES_TLS 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 pthread_mutex_unlock(®ister_lock); #endif } void flint_cleanup() { #if !FLINT_REENTRANT || FLINT_USES_TLS _flint_cleanup(); #endif } void flint_cleanup_master() { if (global_thread_pool_initialized) { thread_pool_clear(global_thread_pool); global_thread_pool_initialized = 0; } _flint_cleanup(); } flint2-2.8.4/mpf_mat.h000066400000000000000000000061161414523752600145340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef MPF_MAT_H #define MPF_MAT_H #ifdef MPF_MAT_INLINES_C #define MPF_MAT_INLINE FLINT_DLL #else #define MPF_MAT_INLINE static __inline__ #endif #include #include #include "mpf_vec.h" #ifdef __cplusplus extern "C" { #endif 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_MAT_INLINE mpf * mpf_mat_entry(const mpf_mat_t mat, slong i, slong j) { return mat->rows[i] + j; } MPF_MAT_INLINE slong mpf_mat_nrows(const mpf_mat_t mat) { return mat->r; } MPF_MAT_INLINE slong mpf_mat_ncols(const mpf_mat_t mat) { return mat->c; } /* Memory management ********************************************************/ FLINT_DLL void mpf_mat_init(mpf_mat_t mat, slong rows, slong cols, flint_bitcnt_t prec); FLINT_DLL void mpf_mat_swap(mpf_mat_t mat1, mpf_mat_t mat2); MPF_MAT_INLINE void mpf_mat_swap_entrywise(mpf_mat_t mat1, mpf_mat_t mat2) { slong i, j; for (i = 0; i < mpf_mat_nrows(mat1); i++) for (j = 0; j < mpf_mat_ncols(mat1); j++) mpf_swap(mpf_mat_entry(mat2, i, j), mpf_mat_entry(mat1, i, j)); } FLINT_DLL void mpf_mat_set(mpf_mat_t mat1, const mpf_mat_t mat2); FLINT_DLL void mpf_mat_clear(mpf_mat_t mat); FLINT_DLL int mpf_mat_equal(const mpf_mat_t mat1, const mpf_mat_t mat2); FLINT_DLL int mpf_mat_approx_equal(const mpf_mat_t mat1, const mpf_mat_t mat2, flint_bitcnt_t bits); FLINT_DLL int mpf_mat_is_zero(const mpf_mat_t mat); MPF_MAT_INLINE int mpf_mat_is_empty(const mpf_mat_t mat) { return (mat->r == 0) || (mat->c == 0); } MPF_MAT_INLINE int mpf_mat_is_square(const mpf_mat_t mat) { return (mat->r == mat->c); } FLINT_DLL void mpf_mat_zero(mpf_mat_t mat); FLINT_DLL void mpf_mat_one(mpf_mat_t mat); /* Input and output *********************************************************/ FLINT_DLL void mpf_mat_print(const mpf_mat_t mat); /* Random matrix generation *************************************************/ FLINT_DLL void mpf_mat_randtest(mpf_mat_t mat, flint_rand_t state, flint_bitcnt_t bits); /* Multiplication */ FLINT_DLL void mpf_mat_mul(mpf_mat_t C, const mpf_mat_t A, const mpf_mat_t B); /* Permutations */ MPF_MAT_INLINE void mpf_mat_swap_rows(mpf_mat_t mat, slong r, slong s) { if (r != s) { mpf * u; u = mat->rows[s]; mat->rows[s] = mat->rows[r]; mat->rows[r] = u; } } /* Gram-Schmidt Orthogonalisation and QR Decomposition ********************************************************/ FLINT_DLL void mpf_mat_gso(mpf_mat_t B, const mpf_mat_t A); FLINT_DLL void mpf_mat_qr(mpf_mat_t Q, mpf_mat_t R, const mpf_mat_t A); #ifdef __cplusplus } #endif #endif flint2-2.8.4/mpf_mat/000077500000000000000000000000001414523752600143575ustar00rootroot00000000000000flint2-2.8.4/mpf_mat/approx_equal.c000066400000000000000000000016131414523752600172240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" int mpf_mat_approx_equal(const mpf_mat_t mat1, const mpf_mat_t mat2, flint_bitcnt_t bits) { 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 (!_mpf_vec_approx_equal (mat1->rows[j], mat2->rows[j], mat1->c, bits)) { return 0; } } return 1; } flint2-2.8.4/mpf_mat/clear.c000066400000000000000000000014731414523752600156160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "mpf_mat.h" 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); /* Clear all coefficients */ flint_free(mat->entries); /* Clean up array of entries */ flint_free(mat->rows); /* Clean up row array */ } } flint2-2.8.4/mpf_mat/equal.c000066400000000000000000000015001414523752600156260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" int mpf_mat_equal(const mpf_mat_t mat1, const mpf_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 (!_mpf_vec_equal(mat1->rows[j], mat2->rows[j], mat1->c)) { return 0; } } return 1; } flint2-2.8.4/mpf_mat/gso.c000066400000000000000000000053641414523752600153230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" void mpf_mat_gso(mpf_mat_t B, const mpf_mat_t A) { slong i, j, k; int flag; mpf_t t, s, tmp, eps; flint_bitcnt_t exp; if (B->r != A->r || B->c != A->c) { flint_printf("Exception (mpf_mat_gso). Incompatible dimensions.\n"); flint_abort(); } if (B == A) { mpf_mat_t T; mpf_mat_init(T, A->r, A->c, B->prec); mpf_mat_gso(T, A); mpf_mat_swap_entrywise(B, T); mpf_mat_clear(T); return; } if (A->r == 0) { return; } mpf_init2(t, B->prec); mpf_init2(s, B->prec); mpf_init2(tmp, B->prec); mpf_init2(eps, B->prec); exp = ceil((A->prec) / 64.0) * 64; flint_mpf_set_ui(eps, 1); mpf_div_2exp(eps, eps, exp); for (k = 0; k < A->c; k++) { for (j = 0; j < A->r; j++) { mpf_set(mpf_mat_entry(B, j, k), mpf_mat_entry(A, j, k)); } flag = 1; while (flag) { flint_mpf_set_ui(t, 0); for (i = 0; i < k; i++) { flint_mpf_set_ui(s, 0); for (j = 0; j < A->r; j++) { mpf_mul(tmp, mpf_mat_entry(B, j, i), mpf_mat_entry(B, j, k)); mpf_add(s, s, tmp); } mpf_mul(tmp, s, s); mpf_add(t, t, tmp); for (j = 0; j < A->r; j++) { mpf_mul(tmp, s, mpf_mat_entry(B, j, i)); mpf_sub(mpf_mat_entry(B, j, k), mpf_mat_entry(B, j, k), tmp); } } flint_mpf_set_ui(s, 0); for (j = 0; j < A->r; j++) { mpf_mul(tmp, mpf_mat_entry(B, j, k), mpf_mat_entry(B, j, k)); mpf_add(s, s, tmp); } mpf_add(t, t, s); flag = 0; if (mpf_cmp(s, t) < 0) { if (mpf_cmp(s, eps) < 0) flint_mpf_set_ui(s, 0); else flag = 1; } } mpf_sqrt(s, s); if (flint_mpf_cmp_ui(s, 0) != 0) mpf_ui_div(s, 1, s); for (j = 0; j < A->r; j++) { mpf_mul(mpf_mat_entry(B, j, k), mpf_mat_entry(B, j, k), s); } } mpf_clears(t, s, tmp, eps, NULL); } flint2-2.8.4/mpf_mat/init.c000066400000000000000000000022311414523752600154640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "mpf_mat.h" void mpf_mat_init(mpf_mat_t mat, slong rows, slong cols, flint_bitcnt_t prec) { if (rows != 0 && cols != 0) /* Allocate space for r*c small entries */ { slong i; mat->entries = (mpf *) flint_malloc(flint_mul_sizes(rows, cols) * sizeof(mpf)); mat->rows = (mpf **) flint_malloc(rows * sizeof(mpf *)); /* Initialise rows */ 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; } flint2-2.8.4/mpf_mat/inlines.c000066400000000000000000000010561414523752600161660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define MPF_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "mpf_mat.h" flint2-2.8.4/mpf_mat/is_zero.c000066400000000000000000000012641414523752600162000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" int mpf_mat_is_zero(const mpf_mat_t mat) { slong j; if (mat->r == 0 || mat->c == 0) return 1; for (j = 0; j < mat->r; j++) { if (!_mpf_vec_is_zero(mat->rows[j], mat->c)) return 0; } return 1; } flint2-2.8.4/mpf_mat/mul.c000066400000000000000000000027751414523752600153330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" void mpf_mat_mul(mpf_mat_t C, const mpf_mat_t A, const mpf_mat_t B) { slong ar, bc, br; slong i, j, k; mpf_t tmp; ar = A->r; br = B->r; bc = B->c; if (C == A || C == B) { mpf_mat_t t; mpf_mat_init(t, ar, bc, C->prec); mpf_mat_mul(t, A, B); mpf_mat_swap_entrywise(C, t); mpf_mat_clear(t); return; } if (C->r != ar || C->c != bc) { flint_printf("Exception (mpf_mat_mul). Incompatible dimensions.\n"); flint_abort(); } if (br == 0) { mpf_mat_zero(C); return; } mpf_init2(tmp, C->prec); for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { mpf_mul(mpf_mat_entry(C, i, j), mpf_mat_entry(A, i, 0), mpf_mat_entry(B, 0, j)); for (k = 1; k < br; k++) { mpf_mul(tmp, mpf_mat_entry(A, i, k), mpf_mat_entry(B, k, j)); mpf_add(mpf_mat_entry(C, i, j), mpf_mat_entry(C, i, j), tmp); } } } mpf_clear(tmp); } flint2-2.8.4/mpf_mat/one.c000066400000000000000000000011761414523752600153110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" void mpf_mat_one(mpf_mat_t mat) { slong i, n; mpf_mat_zero(mat); n = FLINT_MIN(mat->r, mat->c); for (i = 0; i < n; i++) flint_mpf_set_ui(mpf_mat_entry(mat, i, i), 1); } flint2-2.8.4/mpf_mat/print.c000066400000000000000000000015061414523752600156610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" void mpf_mat_print(const mpf_mat_t mat) { slong i, j; flint_printf("["); for (i = 0; i < mat->r; i++) { flint_printf("["); for (j = 0; j < mat->c; j++) { mpf_out_str(stdout, 10, 0, mpf_mat_entry(mat, i, j)); if (j < mat->c - 1) flint_printf(" "); } flint_printf("]\n"); } flint_printf("]\n"); } flint2-2.8.4/mpf_mat/qr.c000066400000000000000000000061631414523752600151530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" void mpf_mat_qr(mpf_mat_t Q, mpf_mat_t R, const mpf_mat_t A) { slong i, j, k; int flag, orig; mpf_t t, s, tmp, eps; flint_bitcnt_t exp; if (Q->r != A->r || Q->c != A->c || R->r != A->c || R->c != A->c) { flint_printf("Exception (mpf_mat_qr). Incompatible dimensions.\n"); flint_abort(); } if (Q == A) { mpf_mat_t T; mpf_mat_init(T, A->r, A->c, Q->prec); mpf_mat_qr(T, R, A); mpf_mat_swap_entrywise(Q, T); mpf_mat_clear(T); return; } if (A->r == 0) { return; } mpf_init2(t, Q->prec); mpf_init2(s, Q->prec); mpf_init2(tmp, Q->prec); mpf_init2(eps, Q->prec); exp = ceil((A->prec) / 64.0) * 64; flint_mpf_set_ui(eps, 1); mpf_div_2exp(eps, eps, exp); for (k = 0; k < A->c; k++) { for (j = 0; j < A->r; j++) { mpf_set(mpf_mat_entry(Q, j, k), mpf_mat_entry(A, j, k)); } orig = flag = 1; while (flag) { flint_mpf_set_ui(t, 0); for (i = 0; i < k; i++) { flint_mpf_set_ui(s, 0); for (j = 0; j < A->r; j++) { mpf_mul(tmp, mpf_mat_entry(Q, j, i), mpf_mat_entry(Q, j, k)); mpf_add(s, s, tmp); } if (orig) { mpf_set(mpf_mat_entry(R, i, k), s); } else { mpf_add(mpf_mat_entry(R, i, k), mpf_mat_entry(R, i, k), s); } mpf_mul(tmp, s, s); mpf_add(t, t, tmp); for (j = 0; j < A->r; j++) { mpf_mul(tmp, s, mpf_mat_entry(Q, j, i)); mpf_sub(mpf_mat_entry(Q, j, k), mpf_mat_entry(Q, j, k), tmp); } } flint_mpf_set_ui(s, 0); for (j = 0; j < A->r; j++) { mpf_mul(tmp, mpf_mat_entry(Q, j, k), mpf_mat_entry(Q, j, k)); mpf_add(s, s, tmp); } mpf_add(t, t, s); flag = 0; if (mpf_cmp(s, t) < 0) { orig = 0; if (mpf_cmp(s, eps) < 0) flint_mpf_set_ui(s, 0); else flag = 1; } } mpf_sqrt(s, s); mpf_set(mpf_mat_entry(R, k, k), s); if (flint_mpf_cmp_ui(s, 0) != 0) mpf_ui_div(s, 1, s); for (j = 0; j < A->r; j++) { mpf_mul(mpf_mat_entry(Q, j, k), mpf_mat_entry(Q, j, k), s); } } mpf_clears(t, s, tmp, eps, NULL); } flint2-2.8.4/mpf_mat/randtest.c000066400000000000000000000013521414523752600163500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" void mpf_mat_randtest(mpf_mat_t mat, flint_rand_t state, flint_bitcnt_t bits) { 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++) mpf_urandomb(mpf_mat_entry(mat, i, j), state->gmp_state, bits); } flint2-2.8.4/mpf_mat/set.c000066400000000000000000000013421414523752600153160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" void mpf_mat_set(mpf_mat_t mat1, const mpf_mat_t mat2) { if (mat1 != mat2) { slong i; if (mat2->r && mat2->c) for (i = 0; i < mat2->r; i++) _mpf_vec_set(mat1->rows[i], mat2->rows[i], mat2->c); } } flint2-2.8.4/mpf_mat/swap.c000066400000000000000000000011611414523752600154740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" void mpf_mat_swap(mpf_mat_t mat1, mpf_mat_t mat2) { if (mat1 != mat2) { mpf_mat_struct tmp; tmp = *mat1; *mat1 = *mat2; *mat2 = tmp; } } flint2-2.8.4/mpf_mat/test/000077500000000000000000000000001414523752600153365ustar00rootroot00000000000000flint2-2.8.4/mpf_mat/test/t-entry.c000066400000000000000000000030451414523752600171060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("entry...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf_mat_t A; slong j, k; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); mpf_mat_init(A, rows, cols, 200); for (j = 0; j < rows; j++) { for (k = 0; k < cols; k++) { flint_mpf_set_si(mpf_mat_entry(A, j, k), 3 * j + 7 * k); } } for (j = 0; j < rows; j++) { for (k = 0; k < cols; k++) { if (flint_mpf_cmp_ui(mpf_mat_entry(A, j, k), 3 * j + 7 * k) != 0) { flint_printf("FAIL: get/set entry %wd,%wd\n", j, k); abort(); } } } mpf_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_mat/test/t-equal.c000066400000000000000000000035251414523752600170570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("equal...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf_mat_t A, B, D, E; slong m, n, j; m = n_randint(state, 20); n = n_randint(state, 20); mpf_mat_init(A, m, n, 200); mpf_mat_init(B, m, n, 200); mpf_mat_init(D, m + 1, n, 200); mpf_mat_init(E, m, n + 1, 200); if (mpf_mat_equal(A, D) || mpf_mat_equal(A, E)) { flint_printf("FAIL: different dimensions should not be equal\n"); abort(); } mpf_mat_randtest(A, state, 200); mpf_mat_set(B, A); if (!mpf_mat_equal(A, B)) { flint_printf("FAIL: copied matrices should be equal\n"); abort(); } if (m && n) { j = n_randint(state, m * n); mpf_add_ui(A->entries + j, A->entries + j, 1); if (mpf_mat_equal(A, B)) { flint_printf("FAIL: modified matrices should not be equal\n"); abort(); } } mpf_mat_clear(A); mpf_mat_clear(B); mpf_mat_clear(D); mpf_mat_clear(E); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_mat/test/t-gso.c000066400000000000000000000062301414523752600165340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("gso...."); fflush(stdout); for (i = 0; i < 100 * flint_test_multiplier(); i++) { mpf_t dot, tmp; int j, k, l; mpf_mat_t A, B; flint_bitcnt_t prec; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); prec = n_randint(state, 200) + 3; mpf_mat_init(A, m, n, prec); mpf_mat_init(B, m, n, prec); mpf_init2(dot, prec); mpf_init2(tmp, prec); mpf_mat_randtest(A, state, prec); mpf_mat_set(B, A); mpf_mat_gso(A, A); for (j = 0; j < n; j++) { mpf_t norm; mpf_init2(norm, prec); for (l = 0; l < m; l++) { mpf_mul(tmp, mpf_mat_entry(A, l, j), mpf_mat_entry(A, l, j)); mpf_add(norm, norm, tmp); } mpf_sub_ui(dot, norm, 1); mpf_abs(dot, dot); flint_mpf_set_ui(tmp, 1); mpf_div_2exp(tmp, tmp, prec - 3); if (flint_mpf_cmp_ui(norm, 0) != 0 && mpf_cmp(dot, tmp) > 0) { flint_printf("FAIL:\n"); flint_printf("A:\n"); mpf_mat_print(A); mpf_out_str(stdout, 10, 0, norm); flint_printf("\n"); mpf_out_str(stdout, 10, 0, dot); flint_printf("\n"); mpf_out_str(stdout, 10, 0, tmp); flint_printf("\n"); flint_printf("%d\n", prec); flint_printf("%d\n", j); abort(); } mpf_clear(norm); for (k = j + 1; k < n; k++) { flint_mpf_set_ui(dot, 0); for (l = 0; l < m; l++) { mpf_mul(tmp, mpf_mat_entry(A, l, j), mpf_mat_entry(A, l, k)); mpf_add(dot, dot, tmp); } flint_mpf_set_ui(tmp, 1); mpf_div_2exp(tmp, tmp, prec); mpf_abs(dot, dot); if (mpf_cmp(dot, tmp) > 0) { flint_printf("FAIL:\n"); flint_printf("A:\n"); mpf_mat_print(A); flint_printf("B:\n"); mpf_mat_print(B); mpf_out_str(stdout, 10, 0, dot); flint_printf("\n"); flint_printf("%d %d\n", j, k); abort(); } } } mpf_mat_clear(A); mpf_mat_clear(B); mpf_clears(dot, tmp, NULL); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/mpf_mat/test/t-init_clear.c000066400000000000000000000022001414523752600200460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); for (i = 0; i < 1000; i++) { mpf_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) + 2; mpf_mat_init(a, rows, cols, prec); for (j = 0; j < rows; j++) for (k = 0; k < cols; k++) flint_mpf_set_ui(a->rows[j] + k, 0); mpf_mat_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_mat/test/t-is_empty.c000066400000000000000000000021401414523752600175710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_empty...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf_mat_t A; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); mpf_mat_init(A, rows, cols, 200); if (mpf_mat_is_empty(A) != (rows == 0 || cols == 0)) { flint_printf("FAIL!\n"); abort(); } mpf_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_mat/test/t-is_square.c000066400000000000000000000021301414523752600177320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("is_square...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf_mat_t A; slong rows = n_randint(state, 10); slong cols = n_randint(state, 10); mpf_mat_init(A, rows, cols, 200); if (mpf_mat_is_square(A) != (rows == cols)) { flint_printf("FAIL!\n"); abort(); } mpf_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_mat/test/t-mul.c000066400000000000000000000041371414523752600165450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_mat.h" #include "ulong_extras.h" #define MPF_MAT_MUL_BITS (40) int main(void) { mpf_mat_t A, B, C, D, E, F, G; slong i; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); for (i = 0; i < 100 * flint_test_multiplier(); i++) { slong m, n, k, l; m = n_randint(state, 10); n = n_randint(state, 10); k = n_randint(state, 10); l = n_randint(state, 10); mpf_mat_init(A, m, n, 200); mpf_mat_init(B, n, k, 200); mpf_mat_init(C, k, l, 200); mpf_mat_init(D, n, l, 200); mpf_mat_init(E, m, k, 200); mpf_mat_init(F, m, l, 200); mpf_mat_init(G, m, l, 200); mpf_mat_randtest(A, state, 200); mpf_mat_randtest(B, state, 200); mpf_mat_randtest(C, state, 200); mpf_mat_mul(D, B, C); mpf_mat_mul(E, A, B); mpf_mat_mul(F, A, D); mpf_mat_mul(G, E, C); if (!mpf_mat_approx_equal(F, G, MPF_MAT_MUL_BITS)) { flint_printf("FAIL: results not equal\n"); mpf_mat_print(F); mpf_mat_print(G); abort(); } if (n == k) { mpf_mat_mul(A, A, B); if (!mpf_mat_equal(A, E)) { flint_printf("FAIL: aliasing failed\n"); abort(); } } mpf_mat_clear(A); mpf_mat_clear(B); mpf_mat_clear(C); mpf_mat_clear(D); mpf_mat_clear(E); mpf_mat_clear(F); mpf_mat_clear(G); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_mat/test/t-one.c000066400000000000000000000025211414523752600165240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, i, j, rep; FLINT_TEST_INIT(state); flint_printf("one...."); fflush(stdout); for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { mpf_mat_t A; m = n_randint(state, 20); n = n_randint(state, 20); mpf_mat_init(A, m, n, 200); mpf_mat_randtest(A, state, 200); mpf_mat_one(A); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { if (i == j && flint_mpf_cmp_ui(mpf_mat_entry(A, i, j), 1) != 0) { flint_printf("FAIL: entry not one\n"); abort(); } } } mpf_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_mat/test/t-qr.c000066400000000000000000000076221414523752600163740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("qr...."); fflush(stdout); for (i = 0; i < 100 * flint_test_multiplier(); i++) { mpf_t dot, tmp; int j, k, l; mpf_mat_t A, Q, R, B; flint_bitcnt_t prec; slong m, n; m = n_randint(state, 10); n = n_randint(state, 10); prec = n_randint(state, 200) + 3; mpf_mat_init(A, m, n, prec); mpf_mat_init(Q, m, n, prec); mpf_mat_init(R, n, n, prec); mpf_mat_init(B, m, n, prec); mpf_init2(dot, prec); mpf_init2(tmp, prec); mpf_mat_randtest(A, state, prec); mpf_mat_qr(Q, R, A); mpf_mat_mul(B, Q, R); flint_mpf_set_ui(tmp, 1); mpf_div_2exp(tmp, tmp, prec - 2); for (j = 0; j < m; j++) { for (k = 0; k < n; k++) { mpf_sub(dot, mpf_mat_entry(A, j, k), mpf_mat_entry(B, j, k)); mpf_abs(dot, dot); if (mpf_cmp(dot, tmp) > 0) { flint_printf("FAIL:\n"); flint_printf("A:\n"); mpf_mat_print(A); flint_printf("Q:\n"); mpf_mat_print(Q); flint_printf("R:\n"); mpf_mat_print(R); flint_printf("B:\n"); mpf_mat_print(B); mpf_out_str(stdout, 10, 0, dot); flint_printf("\n"); flint_printf("%d\n", prec); abort(); } } } for (j = 0; j < n; j++) { mpf_t norm; mpf_init2(norm, prec); for (l = 0; l < m; l++) { mpf_mul(tmp, mpf_mat_entry(Q, l, j), mpf_mat_entry(Q, l, j)); mpf_add(norm, norm, tmp); } mpf_sub_ui(dot, norm, 1); mpf_abs(dot, dot); flint_mpf_set_ui(tmp, 1); mpf_div_2exp(tmp, tmp, prec - 3); if (flint_mpf_cmp_ui(norm, 0) != 0 && mpf_cmp(dot, tmp) > 0) { flint_printf("FAIL:\n"); flint_printf("Q:\n"); mpf_mat_print(Q); mpf_out_str(stdout, 10, 0, norm); flint_printf("\n"); flint_printf("%d\n", j); abort(); } mpf_clear(norm); for (k = j + 1; k < n; k++) { flint_mpf_set_ui(dot, 0); for (l = 0; l < m; l++) { mpf_mul(tmp, mpf_mat_entry(Q, l, j), mpf_mat_entry(Q, l, k)); mpf_add(dot, dot, tmp); } flint_mpf_set_ui(tmp, 1); mpf_div_2exp(tmp, tmp, prec); mpf_abs(dot, dot); if (mpf_cmp(dot, tmp) > 0) { flint_printf("FAIL:\n"); flint_printf("Q:\n"); mpf_mat_print(Q); mpf_out_str(stdout, 10, 0, dot); flint_printf("\n"); flint_printf("%d %d\n", j, k); abort(); } } } mpf_mat_clear(A); mpf_mat_clear(Q); mpf_mat_clear(R); mpf_mat_clear(B); mpf_clears(dot, tmp, NULL); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/mpf_mat/test/t-zero.c000066400000000000000000000025111414523752600167210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, i, j, rep; FLINT_TEST_INIT(state); flint_printf("zero...."); fflush(stdout); for (rep = 0; rep < 100 * flint_test_multiplier(); rep++) { mpf_mat_t A; m = n_randint(state, 20); n = n_randint(state, 20); mpf_mat_init(A, m, n, 200); mpf_mat_randtest(A, state, 200); mpf_mat_zero(A); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { if (flint_mpf_cmp_ui(mpf_mat_entry(A, i, j), 0) != 0) { flint_printf("FAIL: nonzero entry\n"); abort(); } } } mpf_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_mat/zero.c000066400000000000000000000011411414523752600154770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_mat.h" void mpf_mat_zero(mpf_mat_t mat) { slong i; if (mat->c < 1) return; for (i = 0; i < mat->r; i++) _mpf_vec_zero(mat->rows[i], mat->c); } flint2-2.8.4/mpf_vec.h000066400000000000000000000050111414523752600145210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef MPF_VEC_H #define MPF_VEC_H #ifdef MPF_VEC_INLINES_C #define MPF_VEC_INLINE FLINT_DLL #else #define MPF_VEC_INLINE static __inline__ #endif #include "flint.h" typedef __mpf_struct mpf; #ifdef __cplusplus extern "C" { #endif /* Memory management *******************************************************/ FLINT_DLL mpf * _mpf_vec_init(slong len, flint_bitcnt_t prec); FLINT_DLL void _mpf_vec_clear(mpf * vec, slong len); /* Randomisation ***********************************************************/ FLINT_DLL void _mpf_vec_randtest(mpf * f, flint_rand_t state, slong len, flint_bitcnt_t bits); /* Assignment and basic manipulation ***************************************/ FLINT_DLL void _mpf_vec_zero(mpf * vec, slong len); FLINT_DLL void _mpf_vec_set(mpf * vec1, const mpf * vec2, slong len2); /* Comparison **************************************************************/ FLINT_DLL int _mpf_vec_equal(const mpf * vec1, const mpf * vec2, slong len); FLINT_DLL int _mpf_vec_approx_equal(const mpf * vec1, const mpf * vec2, slong len, flint_bitcnt_t bits); FLINT_DLL int _mpf_vec_is_zero(const mpf * vec, slong len); /* Addition ****************************************************************/ FLINT_DLL void _mpf_vec_add(mpf * res, const mpf * vec1, const mpf * vec2, slong len2); FLINT_DLL void _mpf_vec_sub(mpf * res, const mpf * vec1, const mpf * vec2, slong len2); /* Scalar multiplication **************************************/ FLINT_DLL void _mpf_vec_scalar_mul_2exp(mpf * res, const mpf * vec, slong len, flint_bitcnt_t exp); FLINT_DLL void _mpf_vec_scalar_mul_mpf(mpf * res, const mpf * vec, slong len, mpf_t c); /* Dot product and norm **************************************/ FLINT_DLL void _mpf_vec_dot(mpf_t res, const mpf * vec1, const mpf * vec2, slong len2); FLINT_DLL void _mpf_vec_norm(mpf_t res, const mpf * vec, slong len); FLINT_DLL int _mpf_vec_dot2(mpf_t res, const mpf * vec1, const mpf * vec2, slong len2, flint_bitcnt_t prec); FLINT_DLL void _mpf_vec_norm2(mpf_t res, const mpf * vec, slong len, flint_bitcnt_t prec); #ifdef __cplusplus } #endif #endif flint2-2.8.4/mpf_vec/000077500000000000000000000000001414523752600143535ustar00rootroot00000000000000flint2-2.8.4/mpf_vec/add.c000066400000000000000000000011411414523752600152440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" void _mpf_vec_add(mpf * res, const mpf * vec1, const mpf * vec2, slong len2) { slong i; for (i = 0; i < len2; i++) mpf_add(res + i, vec1 + i, vec2 + i); } flint2-2.8.4/mpf_vec/approx_equal.c000066400000000000000000000014031414523752600172150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" int _mpf_vec_approx_equal(const mpf * vec1, const mpf * vec2, slong len, flint_bitcnt_t bits) { slong i; if (vec1 == vec2) return 1; for (i = 0; i < len; i++) if (mpf_eq(vec1 + i, vec2 + i, bits) == 0) return 0; return 1; } flint2-2.8.4/mpf_vec/clear.c000066400000000000000000000011001414523752600155750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" void _mpf_vec_clear(mpf * vec, slong len) { slong i; for (i = 0; i < len; i++) mpf_clear(vec + i); flint_free(vec); } flint2-2.8.4/mpf_vec/dot.c000066400000000000000000000013371414523752600153110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" void _mpf_vec_dot(mpf_t res, const mpf * vec1, const mpf * vec2, slong len2) { slong i; mpf_t tmp; mpf_init(tmp); 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_clear(tmp); } flint2-2.8.4/mpf_vec/dot2.c000066400000000000000000000020631414523752600153700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" 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; } flint2-2.8.4/mpf_vec/equal.c000066400000000000000000000012571414523752600156330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" int _mpf_vec_equal(const mpf * vec1, const mpf * vec2, slong len) { slong i; if (vec1 == vec2) return 1; for (i = 0; i < len; i++) if (mpf_cmp(vec1 + i, vec2 + i) != 0) return 0; return 1; } flint2-2.8.4/mpf_vec/init.c000066400000000000000000000012061414523752600154610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" mpf * _mpf_vec_init(slong len, flint_bitcnt_t prec) { slong i; mpf *vec = (mpf *) flint_malloc(len * sizeof(mpf)); for (i = 0; i < len; i++) mpf_init2(vec + i, prec); return vec; } flint2-2.8.4/mpf_vec/is_zero.c000066400000000000000000000011571414523752600161750ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" int _mpf_vec_is_zero(const mpf * vec, slong len) { slong i; for (i = 0; i < len; i++) if (flint_mpf_cmp_ui(vec + i, 0) != 0) return 0; return 1; } flint2-2.8.4/mpf_vec/norm.c000066400000000000000000000013621414523752600154740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" 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); } flint2-2.8.4/mpf_vec/norm2.c000066400000000000000000000014171414523752600155570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" 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); } flint2-2.8.4/mpf_vec/randtest.c000066400000000000000000000011551414523752600163450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" void _mpf_vec_randtest(mpf * f, flint_rand_t state, slong len, flint_bitcnt_t bits) { slong i; _flint_rand_init_gmp(state); for (i = 0; i < len; i++) mpf_urandomb(f + i, state->gmp_state, bits); } flint2-2.8.4/mpf_vec/scalar_mul_2exp.c000066400000000000000000000012041414523752600175740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" void _mpf_vec_scalar_mul_2exp(mpf * res, const mpf * vec, slong len, flint_bitcnt_t exp) { slong i; for (i = 0; i < len; i++) mpf_mul_2exp(res + i, vec + i, exp); } flint2-2.8.4/mpf_vec/scalar_mul_mpf.c000066400000000000000000000011301414523752600174760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" void _mpf_vec_scalar_mul_mpf(mpf * res, const mpf * vec, slong len, mpf_t c) { slong i; for (i = 0; i < len; i++) mpf_mul(res + i, vec + i, c); } flint2-2.8.4/mpf_vec/set.c000066400000000000000000000011631414523752600153130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" void _mpf_vec_set(mpf * vec1, const mpf * vec2, slong len) { if (vec1 != vec2) { slong i; for (i = 0; i < len; i++) mpf_set(vec1 + i, vec2 + i); } } flint2-2.8.4/mpf_vec/sub.c000066400000000000000000000011411414523752600153050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" void _mpf_vec_sub(mpf * res, const mpf * vec1, const mpf * vec2, slong len2) { slong i; for (i = 0; i < len2; i++) mpf_sub(res + i, vec1 + i, vec2 + i); } flint2-2.8.4/mpf_vec/test/000077500000000000000000000000001414523752600153325ustar00rootroot00000000000000flint2-2.8.4/mpf_vec/test/t-add.c000066400000000000000000000041201414523752600164640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a, *b, *c; slong len = n_randint(state, 100); a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); c = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_randtest(b, state, len, 200); _mpf_vec_add(c, a, b, len); _mpf_vec_add(a, a, b, len); result = (_mpf_vec_equal(a, c, len)); if (!result) { flint_printf("FAIL:\n"); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); _mpf_vec_clear(c, len); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a, *b, *c; slong len = n_randint(state, 100); a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); c = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_randtest(b, state, len, 200); _mpf_vec_add(c, a, b, len); _mpf_vec_add(b, a, b, len); result = (_mpf_vec_equal(b, c, len)); if (!result) { flint_printf("FAIL:\n"); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); _mpf_vec_clear(c, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_vec/test/t-dot.c000066400000000000000000000033011414523752600165220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("dot...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mpf *a, *b; mpf_t res1, res2, res3; slong len = n_randint(state, 100); if (!len) continue; a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_randtest(b, state, len, 200); mpf_inits(res1, res2, res3, NULL); _mpf_vec_dot(res1, a, b, len - 1); _mpf_vec_dot(res2, a + len - 1, b + len - 1, 1); _mpf_vec_dot(res3, a, b, len); mpf_add(res1, res1, res2); result = mpf_cmp(res1, res3); if (result) { flint_printf("FAIL:\n"); flint_printf("%d\n", len); mpf_out_str(stdout, 10, 0, res1); flint_printf("\n"); mpf_out_str(stdout, 10, 0, res3); flint_printf("\n"); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); mpf_clears(res1, res2, res3, NULL); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_vec/test/t-dot2.c000066400000000000000000000033241414523752600166110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("dot2...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mpf *a, *b; mpf_t res1, res2, res3; slong len = n_randint(state, 100); if (!len) continue; a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_randtest(b, state, len, 200); mpf_inits(res1, res2, res3, NULL); _mpf_vec_dot2(res1, a, b, len - 1, 200); _mpf_vec_dot2(res2, a + len - 1, b + len - 1, 1, 200); _mpf_vec_dot2(res3, a, b, len, 200); mpf_add(res1, res1, res2); result = mpf_cmp(res1, res3); if (result) { flint_printf("FAIL:\n"); flint_printf("%d\n", len); mpf_out_str(stdout, 10, 0, res1); flint_printf("\n"); mpf_out_str(stdout, 10, 0, res3); flint_printf("\n"); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); mpf_clears(res1, res2, res3, NULL); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_vec/test/t-init_clear.c000066400000000000000000000020301414523752600200430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); for (i = 0; i < 10000; i++) { mpf *a; slong j, length = n_randint(state, 100); mp_prec_t prec = n_randint(state, 200) + 2; a = _mpf_vec_init(length, prec); for (j = 0; j < length; j++) flint_mpf_set_ui(a + j, 0); _mpf_vec_clear(a, length); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_vec/test/t-norm.c000066400000000000000000000030711414523752600167130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("norm...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a; mpf_t res1, res2, res3; slong len = n_randint(state, 100); if (!len) continue; a = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); mpf_inits(res1, res2, res3, NULL); _mpf_vec_norm(res1, a, len - 1); _mpf_vec_norm(res2, a + len - 1, 1); _mpf_vec_norm(res3, a, len); mpf_add(res1, res1, res2); result = mpf_cmp(res1, res3); if (result) { flint_printf("FAIL:\n"); flint_printf("%d\n", len); mpf_out_str(stdout, 10, 0, res1); flint_printf("\n"); mpf_out_str(stdout, 10, 0, res3); flint_printf("\n"); abort(); } _mpf_vec_clear(a, len); mpf_clears(res1, res2, res3, NULL); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_vec/test/t-norm2.c000066400000000000000000000031141414523752600167730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("norm2...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a; mpf_t res1, res2, res3; slong len = n_randint(state, 100); if (!len) continue; a = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); mpf_inits(res1, res2, res3, NULL); _mpf_vec_norm2(res1, a, len - 1, 200); _mpf_vec_norm2(res2, a + len - 1, 1, 200); _mpf_vec_norm2(res3, a, len, 200); mpf_add(res1, res1, res2); result = mpf_cmp(res1, res3); if (result) { flint_printf("FAIL:\n"); flint_printf("%d\n", len); mpf_out_str(stdout, 10, 0, res1); flint_printf("\n"); mpf_out_str(stdout, 10, 0, res3); flint_printf("\n"); abort(); } _mpf_vec_clear(a, len); mpf_clears(res1, res2, res3, NULL); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_vec/test/t-scalar_mul_2exp.c000066400000000000000000000043301414523752600210170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_2exp...."); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a, *b; slong len = n_randint(state, 100); ulong exp = n_randint(state, 200); a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_scalar_mul_2exp(b, a, len, exp); _mpf_vec_scalar_mul_2exp(a, a, len, exp); result = (_mpf_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); flint_printf("exp = %wu\n", exp); abort(); } _mpf_vec_clear(a, len); _mpf_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++) { mpf *a, *b; slong len = n_randint(state, 100); ulong e1 = n_randint(state, 200); ulong e2 = n_randint(state, 200); a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_scalar_mul_2exp(b, a, len, e1); _mpf_vec_scalar_mul_2exp(b, b, len, e2); _mpf_vec_scalar_mul_2exp(a, a, len, e1 + e2); result = (_mpf_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); flint_printf("e1 = %wu, e2 = %wu\n", e1, e2); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_vec/test/t-scalar_mul_mpf.c000066400000000000000000000103171414523752600207250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_vec.h" #include "ulong_extras.h" #define MPF_VEC_SMM_ASSOC_BITS (65) int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_mpf...."); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a, *b; mpf_t n; slong len = n_randint(state, 100); mpf_init(n); _flint_rand_init_gmp(state); mpf_urandomb(n, state->gmp_state, 100); if (n_randint(state, 2)) mpf_neg(n, n); a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_scalar_mul_mpf(b, a, len, n); _mpf_vec_scalar_mul_mpf(a, a, len, n); result = (_mpf_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); flint_printf("aliasing failed\n"); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); mpf_clear(n); } /* Check that n (a + b) == na + nb */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a, *b, *lhs, *rhs; mpf_t n; slong len = n_randint(state, 100); mpf_init(n); _flint_rand_init_gmp(state); mpf_urandomb(n, state->gmp_state, 100); if (n_randint(state, 2)) mpf_neg(n, n); a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); lhs = _mpf_vec_init(len, 300); rhs = _mpf_vec_init(len, 300); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_randtest(b, state, len, 200); _mpf_vec_scalar_mul_mpf(lhs, a, len, n); _mpf_vec_scalar_mul_mpf(rhs, b, len, n); _mpf_vec_add(rhs, lhs, rhs, len); _mpf_vec_add(lhs, a, b, len); _mpf_vec_scalar_mul_mpf(lhs, lhs, len, n); result = (_mpf_vec_equal(lhs, rhs, len)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n ( a + b ) test failed\n"); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); _mpf_vec_clear(lhs, len); _mpf_vec_clear(rhs, len); mpf_clear(n); } /* Check that n2 * (n1 a) == (n1 * n2) a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a, *b; mpf_t n1, n2, n; slong len = n_randint(state, 100); mpf_init(n1); mpf_init(n2); mpf_init(n); _flint_rand_init_gmp(state); mpf_urandomb(n1, state->gmp_state, 100); mpf_urandomb(n2, state->gmp_state, 100); if (n_randint(state, 2)) mpf_neg(n1, n1); if (n_randint(state, 2)) mpf_neg(n2, n2); a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_scalar_mul_mpf(b, a, len, n1); _mpf_vec_scalar_mul_mpf(b, b, len, n2); mpf_mul(n, n1, n2); _mpf_vec_scalar_mul_mpf(a, a, len, n); result = (_mpf_vec_approx_equal(a, b, len, MPF_VEC_SMM_ASSOC_BITS)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n2 * (n1 a) test failed\n"); mpf_out_str(stdout, 10, 0, n1); flint_printf("\n"); mpf_out_str(stdout, 10, 0, n2); flint_printf("\n"); mpf_out_str(stdout, 10, 0, n); flint_printf("\n"); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); mpf_clear(n1); mpf_clear(n2); mpf_clear(n); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_vec/test/t-set_equal.c000066400000000000000000000045201414523752600177220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set/equal...."); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a; slong len = n_randint(state, 100); a = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_set(a, a, len); result = (_mpf_vec_equal(a, a, len)); if (!result) { flint_printf("FAIL:\n"); abort(); } _mpf_vec_clear(a, len); } /* Compare copied vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a, *b; slong len = n_randint(state, 100); a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_set(b, a, len); result = (_mpf_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); } /* Compare unequal vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a, *b; slong len = n_randint(state, 100) + 1; slong coeff; a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_set(b, a, len); coeff = n_randint(state, len); mpf_add_ui(b + coeff, b + coeff, 1); result = (!_mpf_vec_equal(a, b, len)); if (!result) { flint_printf("FAIL:\n"); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_vec/test/t-sub.c000066400000000000000000000055131414523752600165340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); /* Check aliasing of a and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a, *b, *c; slong len = n_randint(state, 100); a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); c = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_randtest(b, state, len, 200); _mpf_vec_sub(c, a, b, len); _mpf_vec_sub(a, a, b, len); result = (_mpf_vec_equal(a, c, len)); if (!result) { flint_printf("FAIL:\n"); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); _mpf_vec_clear(c, len); } /* Check aliasing of b and c */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a, *b, *c; slong len = n_randint(state, 100); a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); c = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_randtest(b, state, len, 200); _mpf_vec_sub(c, a, b, len); _mpf_vec_sub(b, a, b, len); result = (_mpf_vec_equal(b, c, len)); if (!result) { flint_printf("FAIL:\n"); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); _mpf_vec_clear(c, len); } /* Check a + b - b = a */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mpf *a, *b, *c, *d; slong len = n_randint(state, 100); a = _mpf_vec_init(len, 200); b = _mpf_vec_init(len, 200); c = _mpf_vec_init(len, 200); d = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_randtest(b, state, len, 200); _mpf_vec_add(c, a, b, len); _mpf_vec_sub(d, c, b, len); result = (_mpf_vec_equal(d, a, len)); if (!result) { flint_printf("FAIL:\n"); abort(); } _mpf_vec_clear(a, len); _mpf_vec_clear(b, len); _mpf_vec_clear(c, len); _mpf_vec_clear(d, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_vec/test/t-zero.c000066400000000000000000000023331414523752600167170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpf_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("zero...."); fflush(stdout); /* Check it's zero */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { int result; mpf *a; slong len = n_randint(state, 100); a = _mpf_vec_init(len, 200); _mpf_vec_randtest(a, state, len, 200); _mpf_vec_zero(a, len); result = (_mpf_vec_is_zero(a, len)); if (!result) { flint_printf("FAIL:\n"); abort(); } _mpf_vec_clear(a, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpf_vec/zero.c000066400000000000000000000010641414523752600154770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpf_vec.h" void _mpf_vec_zero(mpf * vec, slong len) { slong i; for (i = 0; i < len; i++) flint_mpf_set_ui(vec + i, 0); } flint2-2.8.4/mpfr_mat.h000066400000000000000000000041431414523752600147140ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define MPFR_MAT_INLINE static __inline__ #endif #include #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; } FLINT_DLL void mpfr_mat_init(mpfr_mat_t mat, slong rows, slong cols, mpfr_prec_t prec); FLINT_DLL 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)); } FLINT_DLL void mpfr_mat_set(mpfr_mat_t mat1, const mpfr_mat_t mat2); FLINT_DLL void mpfr_mat_clear(mpfr_mat_t mat); FLINT_DLL int mpfr_mat_equal(const mpfr_mat_t mat1, const mpfr_mat_t mat2); FLINT_DLL void mpfr_mat_zero(mpfr_mat_t mat); /* Random matrix generation *************************************************/ FLINT_DLL void mpfr_mat_randtest(mpfr_mat_t mat, flint_rand_t state); /* Multiplication */ FLINT_DLL 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 flint2-2.8.4/mpfr_mat/000077500000000000000000000000001414523752600145415ustar00rootroot00000000000000flint2-2.8.4/mpfr_mat/clear.c000066400000000000000000000014641414523752600160000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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 */ } } flint2-2.8.4/mpfr_mat/equal.c000066400000000000000000000015561414523752600160230ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/mpfr_mat/init.c000066400000000000000000000022261414523752600156520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/mpfr_mat/mul_classical.c000066400000000000000000000033021414523752600175160ustar00rootroot00000000000000/* 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 2.1 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_printf ("Exception (mpfr_mat_mul_classical). Incompatible dimensions.\n"); flint_abort(); } 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); } flint2-2.8.4/mpfr_mat/randtest.c000066400000000000000000000013471414523752600165360ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/mpfr_mat/set.c000066400000000000000000000014201414523752600154750ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/mpfr_mat/swap.c000066400000000000000000000012111414523752600156520ustar00rootroot00000000000000/* 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 2.1 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) { if (mat1 != mat2) { mpfr_mat_struct tmp; tmp = *mat1; *mat1 = *mat2; *mat2 = tmp; } } flint2-2.8.4/mpfr_mat/test/000077500000000000000000000000001414523752600155205ustar00rootroot00000000000000flint2-2.8.4/mpfr_mat/test/t-entry.c000066400000000000000000000030551414523752600172710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("entry...."); fflush(stdout); 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) { flint_printf("FAIL: get/set entry %wd, %wd\n", j, k); abort(); } } } mpfr_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpfr_mat/test/t-equal.c000066400000000000000000000035541414523752600172430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("equal...."); fflush(stdout); 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)) { flint_printf("FAIL: different dimensions should not be equal\n"); abort(); } mpfr_mat_randtest(A, state); mpfr_mat_set(B, A); if (!mpfr_mat_equal(A, B)) { flint_printf("FAIL: copied matrices should be equal\n"); abort(); } 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)) { flint_printf("FAIL: modified matrices should not be equal\n"); abort(); } } mpfr_mat_clear(A); mpfr_mat_clear(B); mpfr_mat_clear(D); mpfr_mat_clear(E); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpfr_mat/test/t-init_clear.c000066400000000000000000000022131414523752600202340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "mpfr_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpfr_mat/test/t-mul_classical.c000066400000000000000000000043241414523752600207430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mul_classical...."); fflush(stdout); /* 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)) { flint_printf("FAIL: aliasing failed\n"); abort(); } 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)) { flint_printf("FAIL: aliasing failed\n"); abort(); } mpfr_mat_clear(A); mpfr_mat_clear(B); mpfr_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpfr_mat/test/t-zero.c000066400000000000000000000024771414523752600171160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, i, j, rep; FLINT_TEST_INIT(state); flint_printf("zero...."); fflush(stdout); 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))) { flint_printf("FAIL: nonzero entry\n"); abort(); } } } mpfr_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpfr_mat/zero.c000066400000000000000000000012161414523752600156640ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/mpfr_vec.h000066400000000000000000000030571414523752600147130ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define MPFR_VEC_INLINE static __inline__ #endif #include #include #ifdef __cplusplus extern "C" { #endif FLINT_DLL flint_mpfr * _mpfr_vec_init(slong length, flint_bitcnt_t prec); FLINT_DLL void _mpfr_vec_clear(flint_mpfr * vec, slong length); FLINT_DLL void _mpfr_vec_randtest(flint_mpfr * f, flint_rand_t state, slong len); FLINT_DLL void _mpfr_vec_zero(flint_mpfr * vec, slong length); FLINT_DLL void _mpfr_vec_set(flint_mpfr * vec1, const flint_mpfr * vec2, slong length); FLINT_DLL int _mpfr_vec_equal(const flint_mpfr * vec1, const flint_mpfr * vec2, slong len); FLINT_DLL void _mpfr_vec_add(flint_mpfr * res, const flint_mpfr * vec1, const flint_mpfr * vec2, slong length); FLINT_DLL void _mpfr_vec_scalar_mul_2exp(flint_mpfr * res, const flint_mpfr * vec, slong length, flint_bitcnt_t exp); FLINT_DLL void _mpfr_vec_scalar_mul_mpfr(flint_mpfr * res, const flint_mpfr * vec, slong length, mpfr_t c); FLINT_DLL void _mpfr_vec_scalar_product(mpfr_t res, const flint_mpfr * vec1, const flint_mpfr * vec2, slong length); #ifdef __cplusplus } #endif #endif flint2-2.8.4/mpfr_vec/000077500000000000000000000000001414523752600145355ustar00rootroot00000000000000flint2-2.8.4/mpfr_vec/add.c000066400000000000000000000012551414523752600154340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_add(flint_mpfr * res, const flint_mpfr * vec1, const flint_mpfr * vec2, slong length) { slong i; for (i = 0; i < length; i++) mpfr_add(res + i, vec1 + i, vec2 + i, GMP_RNDN); } flint2-2.8.4/mpfr_vec/clear.c000066400000000000000000000011661414523752600157730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_clear(flint_mpfr * vec, slong length) { slong i; for (i = 0; i < length; i++) mpfr_clear(vec + i); flint_free(vec); } flint2-2.8.4/mpfr_vec/equal.c000066400000000000000000000013231414523752600160070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpfr_vec.h" int _mpfr_vec_equal(const flint_mpfr * vec1, const flint_mpfr * 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; } flint2-2.8.4/mpfr_vec/init.c000066400000000000000000000013451414523752600156470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_vec.h" flint_mpfr * _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; } flint2-2.8.4/mpfr_vec/randtest.c000066400000000000000000000011571414523752600165310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_randtest(flint_mpfr * 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); } flint2-2.8.4/mpfr_vec/scalar_mul_2exp.c000066400000000000000000000012621414523752600177620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_scalar_mul_2exp(flint_mpfr * res, const flint_mpfr * 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); } flint2-2.8.4/mpfr_vec/scalar_mul_mpfr.c000066400000000000000000000012411414523752600200450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_scalar_mul_mpfr(flint_mpfr * res, const flint_mpfr * vec, slong length, mpfr_t c) { slong i; for (i = 0; i < length; i++) mpfr_mul(res + i, vec + i, c, GMP_RNDN); } flint2-2.8.4/mpfr_vec/scalar_product.c000066400000000000000000000015421414523752600177100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_scalar_product(mpfr_t res, const flint_mpfr * vec1, const flint_mpfr * 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); } flint2-2.8.4/mpfr_vec/set.c000066400000000000000000000012141414523752600154720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_set(flint_mpfr * vec1, const flint_mpfr * vec2, slong length) { slong i; for (i = 0; i < length; i++) mpfr_set(vec1 + i, vec2 + i, GMP_RNDN); } flint2-2.8.4/mpfr_vec/test/000077500000000000000000000000001414523752600155145ustar00rootroot00000000000000flint2-2.8.4/mpfr_vec/test/t-init_clear.c000066400000000000000000000020541414523752600202330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "mpfr_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpfr_vec/test/t-set_equal.c000066400000000000000000000045661414523752600201160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set/equal...."); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { flint_mpfr *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) { flint_printf("FAIL:\n"); abort(); } _mpfr_vec_clear(a, len); } /* Compare copied vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { flint_mpfr *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) { flint_printf("FAIL:\n"); abort(); } _mpfr_vec_clear(a, len); _mpfr_vec_clear(b, len); } /* Compare unequal vectors */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { flint_mpfr *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) { flint_printf("FAIL:\n"); abort(); } _mpfr_vec_clear(a, len); _mpfr_vec_clear(b, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpfr_vec/zero.c000066400000000000000000000011561414523752600156630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpfr_vec.h" void _mpfr_vec_zero(flint_mpfr * vec, slong length) { slong i; for (i = 0; i < length; i++) mpfr_set_ui(vec + i, 0, GMP_RNDN); } flint2-2.8.4/mpn_extras.h000066400000000000000000000306431414523752600152730ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define MPN_EXTRAS_INLINE static __inline__ #endif #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.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) /* 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)) /* Not defined in gmp.h mp_limb_t __gmpn_modexact_1_odd(mp_srcptr src, mp_size_t size, mp_limb_t divisor); #define mpn_modexact_1_odd __gmpn_modexact_1_odd */ #ifdef mpn_modexact_1_odd #define flint_mpn_divisible_1_p(x, xsize, d) (mpn_modexact_1_odd(x, xsize, d) == 0) #else MPN_EXTRAS_INLINE int flint_mpn_divisible_1_p(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 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; } FLINT_DLL void flint_mpn_debug(mp_srcptr x, mp_size_t xsize); FLINT_DLL mp_size_t flint_mpn_remove_2exp(mp_ptr x, mp_size_t xsize, flint_bitcnt_t *bits); FLINT_DLL mp_size_t flint_mpn_remove_power_ascending(mp_ptr x, mp_size_t xsize, mp_ptr p, mp_size_t psize, ulong *exp); FLINT_DLL int flint_mpn_factor_trial(mp_srcptr x, mp_size_t xsize, slong start, slong stop); FLINT_DLL int flint_mpn_factor_trial_tree(slong * factors, mp_srcptr x, mp_size_t xsize, slong num_primes); FLINT_DLL 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); FLINT_DLL int flint_mpn_divides(mp_ptr q, mp_srcptr array1, mp_size_t limbs1, mp_srcptr arrayg, mp_size_t limbsg, mp_ptr temp); FLINT_DLL 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); FLINT_DLL mp_size_t flint_mpn_gcd_full(mp_ptr arrayg, mp_srcptr array1, mp_size_t limbs1, mp_srcptr array2, mp_size_t limbs2); FLINT_DLL mp_limb_t flint_mpn_preinv1(mp_limb_t d, mp_limb_t d2); FLINT_DLL 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) FLINT_DLL 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); FLINT_DLL void flint_mpn_preinvn(mp_ptr dinv, mp_srcptr d, mp_size_t n); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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; \ \ count_leading_zeros(t##ncnt, t##r1); \ count_leading_zeros(t##dcnt, 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 flint2-2.8.4/mpn_extras/000077500000000000000000000000001414523752600151145ustar00rootroot00000000000000flint2-2.8.4/mpn_extras/debug.c000066400000000000000000000016341414523752600163520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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 #include #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); } flint2-2.8.4/mpn_extras/divrem_preinv1.c000066400000000000000000000024501414523752600202130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "longlong.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 flint2-2.8.4/mpn_extras/divrem_preinvn.c000066400000000000000000000043421414523752600203120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "longlong.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) { mpn_mul_n(t, dinv, r + n, n); cy = mpn_add_n(q, t + n, r + n, n); 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); mpn_mul(t, dinv, n, rp + n, size); cy = mpn_add_n(qp, t + n, rp + n, size); 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; } flint2-2.8.4/mpn_extras/factor_trial.c000066400000000000000000000015201414523752600177270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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_p(x, xsize, primes[i])) return i; } return 0; } flint2-2.8.4/mpn_extras/factor_trial_tree.c000066400000000000000000000147031414523752600207550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "mpn_extras.h" #include "ulong_extras.h" #if FLINT_REENTRANT && !FLINT_USES_TLS #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 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 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)) { 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 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_p(x, xsize, primes[(FLINT_BITS/16)*i + j])) factors[numfacs++] = (FLINT_BITS/16)*i + j; } } } flint_free(gtemp); return numfacs; } flint2-2.8.4/mpn_extras/fmms1.c000066400000000000000000000020251414523752600163020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/mpn_extras/gcd_full.c000066400000000000000000000047171414523752600170500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); } flint2-2.8.4/mpn_extras/mod_preinvn.c000066400000000000000000000037111414523752600176020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "longlong.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) { mpn_mul_n(t, dinv, r + n, n); cy = mpn_add_n(t + 2*n, t + n, r + n, n); 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); mpn_mul(t, dinv, n, rp + n, size); cy = mpn_add_n(t + 2*n, t + n, rp + n, size); 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; } flint2-2.8.4/mpn_extras/mulmod_2expp1_basecase.c000066400000000000000000000044431414523752600216070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "gmp.h" #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; 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_n(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_n(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; } flint2-2.8.4/mpn_extras/mulmod_preinv1.c000066400000000000000000000026431414523752600202260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "longlong.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) mpn_sqr(t, a, n); else 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 flint2-2.8.4/mpn_extras/mulmod_preinvn.c000066400000000000000000000060241414523752600203200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "longlong.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) mpn_sqr(t, a, n); else mpn_mul_n(t, a, b, n); if (norm) mpn_rshift(t, t, 2*n, norm); mpn_mul_n(t + 3*n, t + n, dinv, n); mpn_add_n(t + 4*n, t + 4*n, t + n, n); 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; } flint2-2.8.4/mpn_extras/preinv1.c000066400000000000000000000017571414523752600166560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "longlong.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; } flint2-2.8.4/mpn_extras/preinvn.c000066400000000000000000000017641414523752600167510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "longlong.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); } flint2-2.8.4/mpn_extras/profile/000077500000000000000000000000001414523752600165545ustar00rootroot00000000000000flint2-2.8.4/mpn_extras/profile/p-mulmod_preinvn.c000066400000000000000000000102051414523752600222110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "profiler.h" #include "flint.h" #include "longlong.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; FLINT_TEST_INIT(state); mp_ptr dinv; flint_bitcnt_t norm; 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 */ count_leading_zeros(norm, 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; } flint2-2.8.4/mpn_extras/remove_2exp.c000066400000000000000000000020521414523752600175120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/mpn_extras/remove_power.c000066400000000000000000000047641414523752600200040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); 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; } flint2-2.8.4/mpn_extras/test/000077500000000000000000000000001414523752600160735ustar00rootroot00000000000000flint2-2.8.4/mpn_extras/test/t-divides.c000066400000000000000000000061721414523752600201350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpn_extras.h" #include "ulong_extras.h" int main(void) { int i, result; mpz_t a, b, c, g, s; mp_ptr temp; gmp_randstate_t st; FLINT_TEST_INIT(state); flint_printf("divides...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); gmp_printf("%Zd\n", c); gmp_printf("%Zd\n", a); gmp_printf("%Zd\n", b); abort(); } 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) { flint_printf("FAIL:\n"); gmp_printf("%Zd\n", c); gmp_printf("%Zd\n", a); gmp_printf("%Zd\n", b); gmp_printf("%Zd\n", s); abort(); } 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpn_extras/test/t-divrem_preinv1.c000066400000000000000000000047031414523752600214360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpn_extras.h" #include "ulong_extras.h" int main(void) { int i, result; mpz_t a, a2, b, q, r, q2; gmp_randstate_t st; mp_limb_t d1, d2, inv; slong s1, s2; FLINT_TEST_INIT(state); flint_printf("divrem_preinv1...."); fflush(stdout); mpz_init(a); mpz_init(a2); mpz_init(b); mpz_init(q); mpz_init(r); gmp_randinit_default(st); for (i = 0; i < 10000; 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) { flint_printf("FAIL:\n"); gmp_printf("%Zd\n", a); gmp_printf("%Zd\n", b); gmp_printf("%Zd\n", q); gmp_printf("%Zd\n", r); gmp_printf("%Zd\n", q2); gmp_printf("%Zd\n", a2); abort(); } 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpn_extras/test/t-divrem_preinvn.c000066400000000000000000000110331414523752600215250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "longlong.h" #include "mpn_extras.h" #include "ulong_extras.h" int main(void) { 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; FLINT_TEST_INIT(state); flint_printf("divrem_preinvn...."); fflush(stdout); 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 < 10000; 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 */ count_leading_zeros(norm, 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) { flint_printf("FAIL:\n"); gmp_printf("%Zd\n", a); gmp_printf("%Zd\n", d); gmp_printf("%Zd\n", r1); gmp_printf("%Zd\n", q1); gmp_printf("%Zd\n", q2); flint_printf("size = %wd\n", size); flint_printf("size2 = %wd\n", size2); abort(); } flint_free(dinv); flint_free(q2->_mp_d); } /* test flint_mpn_divrem_preinvn */ for (i = 0; i < 10000; 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 */ count_leading_zeros(norm, 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) { flint_printf("FAIL:\n"); gmp_printf("%Zd\n", a); gmp_printf("%Zd\n", d); gmp_printf("%Zd\n", r1); gmp_printf("%Zd\n", r2); gmp_printf("%Zd\n", q1); gmp_printf("%Zd\n", q2); flint_printf("size = %wd\n", size); flint_printf("size2 = %wd\n", size2); abort(); } 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpn_extras/test/t-fmms1.c000066400000000000000000000047071414523752600175330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpn_extras.h" int main(void) { slong i, j; fmpz_t X1, X2, Y, T; mp_limb_t * y, a1, * x1, a2, * x2; mp_size_t yn, n; FLINT_TEST_INIT(state); flint_printf("fmms1...."); fflush(stdout); 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)) { flint_printf("FAIL\n"); flint_printf("check positive answer, i = %wd\n", i); flint_abort(); } } else if (yn == 0) { if (!fmpz_is_zero(Y)) { flint_printf("FAIL\n"); flint_printf("check zero answer, i = %wd\n", i); flint_abort(); } } else { if (fmpz_sgn(Y) >= 0 && fmpz_size(Y) <= n) { flint_printf("FAIL\n"); flint_printf("check failed answer, i = %wd\n", i); flint_abort(); } } flint_free(x1); flint_free(x2); flint_free(y); } fmpz_clear(X1); fmpz_clear(X2); fmpz_clear(Y); fmpz_clear(T); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpn_extras/test/t-gcd_full.c000066400000000000000000000037341414523752600202660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpn_extras.h" #include "ulong_extras.h" int main(void) { int i, result; mpz_t a, b, c, g; gmp_randstate_t st; slong s1, s2; FLINT_TEST_INIT(state); flint_printf("gcd_full...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); gmp_printf("%Zd\n", g); gmp_printf("%Zd\n", c); abort(); } flint_free(g->_mp_d); } mpz_clear(a); mpz_clear(b); mpz_clear(c); /* don't clear g */ gmp_randclear(st); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpn_extras/test/t-mod_preinvn.c000066400000000000000000000071351414523752600210260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "longlong.h" #include "mpn_extras.h" #include "ulong_extras.h" int main(void) { 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; FLINT_TEST_INIT(state); flint_printf("mod_preinvn...."); fflush(stdout); 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 < 10000; 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 */ count_leading_zeros(norm, 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) { flint_printf("FAIL:\n"); gmp_printf("%Zd\n", a); gmp_printf("%Zd\n", d); gmp_printf("%Zd\n", r1); flint_printf("size = %wd\n", size); flint_printf("size2 = %wd\n", size2); abort(); } flint_free(dinv); flint_free(r2->_mp_d); } /* test flint_mpn_mod_preinvn alias r and a */ for (i = 0; i < 10000; 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 */ count_leading_zeros(norm, 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) { flint_printf("FAIL:\n"); gmp_printf("%Zd\n", a); gmp_printf("%Zd\n", d); gmp_printf("%Zd\n", r1); flint_printf("size = %wd\n", size); flint_printf("size2 = %wd\n", size2); abort(); } flint_free(dinv); } mpz_clear(a); mpz_clear(d); mpz_clear(r1); /* don't clear r2 */ gmp_randclear(st); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpn_extras/test/t-mulmod_2expp1.c000066400000000000000000000140341414523752600211760ustar00rootroot00000000000000/* Copyright 2009 Jason Moxham Copyright 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "longlong.h" #include "mpn_extras.h" #include "ulong_extras.h" int main(void) { 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; FLINT_TEST_INIT(state); gmp_randinit_default(rands); flint_printf("mulmod_2expp1_basecase...."); fflush(stdout); 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_n(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) { flint_printf("FAIL:\n"); flint_printf("b = %wd\n", b); abort(); } } } 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_n(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) { flint_printf("FAIL:\n"); flint_printf("b = %wd\n", b); abort(); } } } 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_n(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) { flint_printf("FAIL\n"); flint_printf("b = %wd\n", b); abort(); } } } 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_n(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) { flint_printf("FAIL\n"); flint_printf("b = %wd\n", b); abort(); } } } gmp_randclear(rands); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpn_extras/test/t-mulmod_preinv1.c000066400000000000000000000046501414523752600214460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "longlong.h" #include "mpn_extras.h" #include "ulong_extras.h" int main(void) { 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; FLINT_TEST_INIT(state); flint_printf("mulmod_preinv1...."); fflush(stdout); mpz_init(a); mpz_init(b); mpz_init(d); mpz_init(r1); /* don't init r2 */ gmp_randinit_default(st); for (i = 0; i < 10000; 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 */ count_leading_zeros(norm, 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) { flint_printf("FAIL:\n"); gmp_printf("%Zd\n", a); gmp_printf("%Zd\n", b); gmp_printf("%Zd\n", d); gmp_printf("%Zd\n", r1); gmp_printf("%Zd\n", r2); abort(); } flint_free(r2->_mp_d); } mpz_clear(a); mpz_clear(b); mpz_clear(d); mpz_clear(r1); /* don't init r2 */ gmp_randclear(st); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpn_extras/test/t-mulmod_preinvn.c000066400000000000000000000052301414523752600215360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "longlong.h" #include "mpn_extras.h" #include "ulong_extras.h" int main(void) { 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; FLINT_TEST_INIT(state); flint_printf("mulmod_preinvn...."); fflush(stdout); mpz_init(a); mpz_init(b); mpz_init(d); mpz_init(r1); /* don't init r2 */ gmp_randinit_default(st); for (i = 0; i < 10000; 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 */ count_leading_zeros(norm, 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) { flint_printf("FAIL:\n"); gmp_printf("%Zd\n", a); gmp_printf("%Zd\n", b); gmp_printf("%Zd\n", d); gmp_printf("%Zd\n", r1); gmp_printf("%Zd\n", r2); flint_printf("size_d = %wd\n", size_d); abort(); } 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpn_extras/test/t-remove_2exp.c000066400000000000000000000024551414523752600207410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpn_extras.h" #include "ulong_extras.h" int main(void) { int zero, nonzero; flint_bitcnt_t check; mpz_t a; mpz_t b; FLINT_TEST_INIT(state); flint_printf("remove_2exp...."); fflush(stdout); 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)) { gmp_printf("%d %d \n", zero, nonzero); abort(); } } } mpz_clear(a); mpz_clear(b); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpn_extras/test/t-remove_power.c000066400000000000000000000031471414523752600212160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpn_extras.h" #include "ulong_extras.h" void test_exact(int d) { 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); abort(); } } } mpz_clear(a); mpz_clear(a2); mpz_clear(b); mpz_clear(c); } int main(void) { FLINT_TEST_INIT(state); flint_printf("remove_power...."); fflush(stdout); test_exact(3); test_exact(10); test_exact(7429); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpoly.h000066400000000000000000001505751414523752600142620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef MPOLY_H #define MPOLY_H #ifdef MPOLY_INLINES_C #define MPOLY_INLINE FLINT_DLL #else #define MPOLY_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "string.h" #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq.h" #include "ulong_extras.h" #include "thread_pool.h" #ifdef __cplusplus extern "C" { #endif #define MPOLY_MIN_BITS (UWORD(8)) /* minimum number of bits to pack into */ /* choose m so that (m + 1)/(n - m) ~= la/lb, i.e. m = (n*la - lb)/(la + lb) */ MPOLY_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; } typedef enum { ORD_LEX, ORD_DEGLEX, ORD_DEGREVLEX } ordering_t; #define MPOLY_NUM_ORDERINGS 3 /* context *******************************************************************/ 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]; FLINT_DLL void mpoly_ctx_init(mpoly_ctx_t ctx, slong nvars, const ordering_t ord); FLINT_DLL void mpoly_ctx_init_rand(mpoly_ctx_t mctx, flint_rand_t state, slong max_nvars); FLINT_DLL void mpoly_monomial_randbits_fmpz(fmpz * exp, flint_rand_t state, flint_bitcnt_t exp_bits, const mpoly_ctx_t mctx); FLINT_DLL 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 */ MPOLY_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]; } MPOLY_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; } MPOLY_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. */ MPOLY_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]; FLINT_DLL void mpoly_rbtree_ui_init(mpoly_rbtree_ui_t T, slong data_size); FLINT_DLL void mpoly_rbtree_ui_clear(mpoly_rbtree_ui_t T); FLINT_DLL void * mpoly_rbtree_ui_lookup(mpoly_rbtree_ui_t T, int * its_new, ulong key); MPOLY_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]; FLINT_DLL void mpoly_rbtree_fmpz_init(mpoly_rbtree_fmpz_t T, slong data_size); FLINT_DLL void mpoly_rbtree_fmpz_clear(mpoly_rbtree_fmpz_t T); FLINT_DLL void * mpoly_rbtree_fmpz_lookup(mpoly_rbtree_fmpz_t T, int * its_new, const fmpz_t key); MPOLY_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; } MPOLY_INLINE 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."); } } /* Monomials ****************************************************************/ MPOLY_INLINE void mpoly_monomial_zero(ulong * exp_ptr, slong N) { slong i; for (i = 0; i < N; i++) exp_ptr[i] = 0; } MPOLY_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]; } MPOLY_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); } MPOLY_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]; } MPOLY_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); } MPOLY_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]; } MPOLY_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); } MPOLY_INLINE void mpoly_monomial_madd_inplace_mp(ulong * exp12, ulong scalar, const ulong * exp3, slong N) { mpn_addmul_1(exp12, exp3, N, scalar); } MPOLY_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]; } MPOLY_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); } MPOLY_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]); } } MPOLY_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]); } MPOLY_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); } } MPOLY_INLINE ulong mpoly_overflow_mask_sp(flint_bitcnt_t bits) { slong i; ulong mask = 0; FLINT_ASSERT(bits <= FLINT_BITS); for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); return mask; } MPOLY_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; } MPOLY_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); } } MPOLY_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; } MPOLY_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); } } MPOLY_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]; } } } MPOLY_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]; } } } MPOLY_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; } MPOLY_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; } MPOLY_INLINE int mpoly_monomial_overflows1(ulong exp, ulong mask) { return (exp & mask) != 0; } MPOLY_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; } MPOLY_INLINE int mpoly_monomial_halves(ulong * exp_ptr, const ulong * exp2, slong N, ulong mask) { slong i; ulong bw; bw = mpn_rshift(exp_ptr, exp2, N, 1); if (bw != 0) return 0; for (i = 0; i < N; i++) { if ((exp_ptr[i] & mask) != 0) return 0; } return 1; } MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_INLINE void mpoly_monomial_set(ulong * exp2, const ulong * exp3, slong N) { slong i; for (i = 0; i < N; i++) exp2[i] = exp3[i]; } MPOLY_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); } } MPOLY_INLINE void mpoly_copy_monomials(ulong * exp1, const ulong * exp2, slong len, slong N) { memcpy(exp1, exp2, N*len*sizeof(ulong)); } MPOLY_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; } } MPOLY_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; } MPOLY_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); } FLINT_DLL void mpoly_monomial_mul_fmpz(ulong * exp2, const ulong * exp3, slong N, const fmpz_t c); MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_INLINE int mpoly_monomial_gt1(ulong a, ulong b, ulong cmpmask) { return (a^cmpmask) > (b^cmpmask); } MPOLY_INLINE int mpoly_monomial_ge1(ulong a, ulong b, ulong cmpmask) { return (a^cmpmask) >= (b^cmpmask); } MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_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; } MPOLY_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 */ MPOLY_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 ******************************************************/ MPOLY_INLINE ulong pack_exp2(ulong e0, ulong e1) { return (e0 << (1*(FLINT_BITS/2))) + (e1 << (0*(FLINT_BITS/2))); } MPOLY_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))); } MPOLY_INLINE ulong extract_exp(ulong e, int idx, int nvars) { return (e >> (idx*(FLINT_BITS/nvars))) & ((-UWORD(1)) >> (FLINT_BITS - FLINT_BITS/nvars)); } FLINT_DLL ulong _mpoly_bidegree(const ulong * Aexps, flint_bitcnt_t Abits, const mpoly_ctx_t mctx); /* generators ****************************************************************/ FLINT_DLL void mpoly_gen_fields_ui(ulong * exp, slong var, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_gen_fields_fmpz(fmpz * exp, slong var, const mpoly_ctx_t mctx); FLINT_DLL 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 */ MPOLY_INLINE slong mpoly_gen_index(slong v, const mpoly_ctx_t mctx) { return mctx->rev ? v : mctx->nvars - 1 - v; } FLINT_DLL void mpoly_gen_offset_shift_sp(slong * offset, slong * shift, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_gen_monomial_offset_shift_sp(ulong * mexp, slong * offset, slong * shift, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_gen_monomial_sp(ulong * oneexp, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL slong mpoly_gen_offset_mp(slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL slong mpoly_gen_monomial_offset_mp(ulong * mexp, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void fmpz_mat_mul_vec(fmpz * v, const fmpz_mat_t M, fmpz * u); FLINT_DLL void mpoly_compose_mat_gen(fmpz_mat_t M, const slong * c, const mpoly_ctx_t mctxB, const mpoly_ctx_t mctxAC); FLINT_DLL 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 ***********************************************************/ FLINT_DLL void mpoly_get_cmpmask(ulong * cmpmask, slong N, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_get_ovfmask(ulong * ovfmask, slong N, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL 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_DLL flint_bitcnt_t mpoly_exp_bits_required_ui(const ulong * user_exp, const mpoly_ctx_t mctx); FLINT_DLL flint_bitcnt_t mpoly_exp_bits_required_ffmpz(const fmpz * user_exp, const mpoly_ctx_t mctx); FLINT_DLL flint_bitcnt_t mpoly_exp_bits_required_pfmpz(fmpz * const * user_exp, const mpoly_ctx_t mctx); MPOLY_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 */ } FLINT_DLL int mpoly_is_poly(const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, slong var, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_pack_vec_ui(ulong * exp1, const ulong * exp2, flint_bitcnt_t bits, slong nfields, slong len); FLINT_DLL void mpoly_pack_vec_fmpz(ulong * exp1, const fmpz * exp2, flint_bitcnt_t bits, slong nfields, slong len); FLINT_DLL void mpoly_unpack_vec_ui(ulong * exp1, const ulong * exp2, flint_bitcnt_t bits, slong nfields, slong len); FLINT_DLL void mpoly_unpack_vec_fmpz(fmpz * exp1, const ulong * exp2, flint_bitcnt_t bits, slong nfields, slong len); FLINT_DLL void mpoly_get_monomial_ui_unpacked_ffmpz(ulong * user_exps, const fmpz * poly_exps, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_get_monomial_ffmpz_unpacked_ffmpz(fmpz * user_exps, const fmpz * poly_exps, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_get_monomial_pfmpz_unpacked_ffmpz(fmpz ** user_exps, const fmpz * poly_exps, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_get_monomial_ui_unpacked_ui(ulong * user_exps, const ulong * poly_exps, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_get_monomial_ui_sp(ulong * user_exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_get_monomial_ui_mp(ulong * user_exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL 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); } FLINT_DLL ulong mpoly_get_monomial_var_exp_ui_sp(const ulong * poly_exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL ulong mpoly_get_monomial_var_exp_ui_mp(const ulong * poly_exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL 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); } FLINT_DLL void mpoly_get_monomial_ffmpz(fmpz * exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_get_monomial_pfmpz(fmpz ** exps, const ulong * poly_exps, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_set_monomial_ui(ulong * exp1, const ulong * exp2, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_set_monomial_ffmpz(ulong * exp1, const fmpz * exp2, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_set_monomial_pfmpz(ulong * exp1, fmpz * const * exp2, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL int mpoly_repack_monomials(ulong * exps1, flint_bitcnt_t bits1, const ulong * exps2, flint_bitcnt_t bits2, slong len, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_pack_monomials_tight(ulong * exp1, const ulong * exp2, slong len, const slong * mults, slong num, slong bits); FLINT_DLL void mpoly_unpack_monomials_tight(ulong * e1, ulong * e2, slong len, slong * mults, slong num, slong bits); FLINT_DLL int mpoly_monomial_exists(slong * index, const ulong * poly_exps, const ulong * exp, slong len, slong N, const ulong * cmpmask); FLINT_DLL slong mpoly_monomial_index1_nomask(ulong * Aexps, slong Alen, ulong e); FLINT_DLL slong mpoly_monomial_index_ui(const ulong * Aexp, flint_bitcnt_t Abits, slong Alength, const ulong * exp, const mpoly_ctx_t mctx); FLINT_DLL slong mpoly_monomial_index_pfmpz(const ulong * Aexp, flint_bitcnt_t Abits, slong Alength, fmpz * const * exp, const mpoly_ctx_t mctx); FLINT_DLL 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); FLINT_DLL void mpoly_min_fields_ui_sp(ulong * min_fields, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_min_fields_fmpz(fmpz * min_fields, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_max_fields_ui_sp(ulong * max_fields, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_max_fields_fmpz(fmpz * max_fields, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL int mpoly_degrees_fit_si(const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_degrees_si(slong * user_degs, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL 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); FLINT_DLL void mpoly_degrees_ffmpz(fmpz * user_degs, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_degrees_pfmpz(fmpz ** user_degs, const ulong * poly_exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL slong mpoly_degree_si(const ulong * poly_exps, slong len, flint_bitcnt_t bits, slong var, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_degree_fmpz(fmpz_t deg, const ulong * poly_exps, slong len, flint_bitcnt_t bits, slong var, const mpoly_ctx_t mctx); FLINT_DLL int mpoly_total_degree_fits_si(const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL slong mpoly_total_degree_si(const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_total_degree_fmpz(fmpz_t totdeg, const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_total_degree_fmpz_ref(fmpz_t totdeg, const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_used_vars_or(int * used, const ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL int mpoly_monomial_cmp_general(ulong * Aexp, flint_bitcnt_t Abits, ulong * Bexp, flint_bitcnt_t Bbits, const mpoly_ctx_t mctx); FLINT_DLL 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); FLINT_DLL void mpoly_main_variable_split_LEX(slong * ind, ulong * pexp, const ulong * Aexp, slong l1, slong Alen, const ulong * mults, slong num, slong Abits); FLINT_DLL void mpoly_main_variable_split_DEG(slong * ind, ulong * pexp, const ulong * Aexp, slong l1, slong Alen, ulong deg, slong num, slong Abits); FLINT_DLL int mpoly_term_exp_fits_si(ulong * exps, flint_bitcnt_t bits, slong n, const mpoly_ctx_t mctx); FLINT_DLL int mpoly_term_exp_fits_ui(ulong * exps, flint_bitcnt_t bits, slong n, const mpoly_ctx_t mctx); FLINT_DLL int mpoly_is_gen(ulong * exps, slong var, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL int mpoly_monomials_valid_test(ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL int mpoly_monomials_overflow_test(ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL int mpoly_monomials_inorder_test(ulong * exps, slong len, flint_bitcnt_t bits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_reverse(ulong * Aexp, const ulong * Bexp, slong len, slong N); FLINT_DLL void mpoly_monomials_deflation(fmpz * shift, fmpz * stride, const ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const mpoly_ctx_t mctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _mpoly_gen_shift_right(ulong * Aexp, flint_bitcnt_t Abits, slong Alength, slong var, ulong amount, const mpoly_ctx_t mctx); FLINT_DLL 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); FLINT_DLL void _mpoly_gen_shift_left(ulong * Aexp, flint_bitcnt_t Abits, slong Alength, slong var, ulong amount, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_monomials_shift_right_ui(ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const ulong * user_exps, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_monomials_shift_right_ffmpz(ulong * Aexps, flint_bitcnt_t Abits, slong Alength, const fmpz * user_exps, const mpoly_ctx_t mctx); FLINT_DLL void mpoly1_fill_marks(ulong ** Dcoeffs, slong * Dlen, slong * Dalloc, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx); FLINT_DLL void mpoly2_fill_marks(ulong ** Dcoeffs, slong * Dlen, slong * Dalloc, const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, const mpoly_ctx_t mctx); FLINT_DLL 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); FLINT_DLL 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 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]; FLINT_DLL void mpoly_gcd_info_init(mpoly_gcd_info_t I, slong nvars); FLINT_DLL void mpoly_gcd_info_clear(mpoly_gcd_info_t I); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void mpoly_gcd_info_set_perm(mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx); FLINT_DLL slong mpoly_gcd_info_get_brown_upper_limit(const mpoly_gcd_info_t I, slong var, slong bound); FLINT_DLL void mpoly_gcd_info_measure_hensel(mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_gcd_info_measure_brown(mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_gcd_info_measure_bma(mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_gcd_info_measure_zippel(mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_gcd_info_measure_zippel2(mpoly_gcd_info_t I, slong Alength, slong Blength, const mpoly_ctx_t mctx); FLINT_DLL 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 FLINT_DLL int mpoly_is_proved_not_square(const ulong * Aexps, slong Alen, flint_bitcnt_t Abits, slong N, ulong * t); FLINT_DLL void mpoly_remove_var_powers(fmpz * var_powers, ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mpoly_ctx_t mctx); FLINT_DLL slong _mpoly_compress_exps(slong * V, slong * D, slong * deg, slong * S, slong n, slong l); FLINT_DLL int mpoly_test_irreducible(ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mpoly_ctx_t ctx); FLINT_DLL int _mpoly_test_irreducible(slong * Aexps, slong stride, slong Alen, slong nvars, flint_rand_t state, slong tries_left); 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]; FLINT_DLL void mpoly_compression_init(mpoly_compression_t M); FLINT_DLL void mpoly_compression_clear(mpoly_compression_t M); FLINT_DLL void mpoly_compression_set(mpoly_compression_t M, const ulong * Aexps, flint_bitcnt_t Abits, slong Alen, const mpoly_ctx_t mctx); FLINT_DLL void mpoly_bivar_cld_bounds(slong * l, slong n); MPOLY_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) MPOLY_INLINE 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; } MPOLY_INLINE 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); } MPOLY_INLINE 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; } MPOLY_INLINE 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; } /* generic parsing ***********************************************************/ typedef struct { char * coeffs; fmpz * exps; slong length; slong alloc; } mpoly_univar_struct; typedef mpoly_univar_struct mpoly_univar_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]; FLINT_DLL void * mpoly_void_ring_elem_init(mpoly_void_ring_t R); FLINT_DLL void mpoly_void_ring_elem_clear(void * a, mpoly_void_ring_t R); FLINT_DLL void mpoly_univar_init(mpoly_univar_t A, mpoly_void_ring_t R); FLINT_DLL void mpoly_univar_clear(mpoly_univar_t A, mpoly_void_ring_t R); FLINT_DLL void mpoly_univar_swap(mpoly_univar_t A, mpoly_univar_t B); FLINT_DLL void mpoly_univar_fit_length(mpoly_univar_t A, slong len, mpoly_void_ring_t R); FLINT_DLL void mpoly_univar_init2(mpoly_univar_t A, slong len, mpoly_void_ring_t R); FLINT_DLL int mpoly_univar_pseudo_gcd_ducos(mpoly_univar_t G, mpoly_univar_t B, mpoly_univar_t A, mpoly_void_ring_t R); FLINT_DLL int mpoly_univar_resultant(void * r, mpoly_univar_t fx, mpoly_univar_t gx, mpoly_void_ring_t R); FLINT_DLL 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]; FLINT_DLL void mpoly_parse_init(mpoly_parse_t E); FLINT_DLL void mpoly_parse_clear(mpoly_parse_t E); FLINT_DLL void mpoly_parse_add_terminal(mpoly_parse_t E, const char * s, const void * v); FLINT_DLL 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 flint2-2.8.4/mpoly/000077500000000000000000000000001414523752600140745ustar00rootroot00000000000000flint2-2.8.4/mpoly/bidegree.c000066400000000000000000000016531414523752600160130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/mpoly/bivar_cld_bounds.c000066400000000000000000000040031414523752600175340ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/mpoly/cmp_general.c000066400000000000000000000064121414523752600165170ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } } flint2-2.8.4/mpoly/compose_mat.c000066400000000000000000000050761414523752600165560ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* unfortunate function missing from fmpz_mat */ void fmpz_mat_mul_vec(fmpz * v, const fmpz_mat_t M, fmpz * u) { slong i; slong r = fmpz_mat_nrows(M); slong c = fmpz_mat_ncols(M); for (i = 0; i < r; i++) _fmpz_vec_dot(v + i, M->rows[i], u, c); } /* 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); } flint2-2.8.4/mpoly/compression.c000066400000000000000000000212701414523752600166030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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--) SLONG_SWAP(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); } flint2-2.8.4/mpoly/ctx_clear.c000066400000000000000000000007111414523752600162030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpoly.h" void mpoly_ctx_clear(mpoly_ctx_t mctx) { return; } flint2-2.8.4/mpoly/ctx_init.c000066400000000000000000000030421414523752600160600ustar00rootroot00000000000000/* 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 2.1 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->nvars = nvars; mctx->ord = ord; 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"); } 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; } } flint2-2.8.4/mpoly/ctx_init_rand.c000066400000000000000000000012111414523752600170600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "mpoly.h" 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); } flint2-2.8.4/mpoly/degree.c000066400000000000000000000036431414523752600155010ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/degrees.c000066400000000000000000000111701414523752600156560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "mpoly.h" /* 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; } flint2-2.8.4/mpoly/degrees_fit_si.c000066400000000000000000000023741414523752600172210ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "mpoly.h" 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; } flint2-2.8.4/mpoly/doc/000077500000000000000000000000001414523752600146415ustar00rootroot00000000000000flint2-2.8.4/mpoly/doc/MPolyAlgorithms.tex000066400000000000000000001524461414523752600204710ustar00rootroot00000000000000\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{} \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 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 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} \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., 1974. Sparse polynomial arithmetic. ACM SIGSAM Bulletin 8 (3), pp. 63--71. \bibitem{FPS} Monagan M., Pearce R.: Sparse polynomial powering using heaps. “Computer Algebra in Scientific Computing”, Springer, 2012, s.236-247. \bibitem{ZIPPEL} Zippel, Richard, Probabilistic algorithms for sparse polynomials. Lecture Notes in Computer Science. 72. pp. 216--226, 1979 \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. \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}. \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 $A(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 described as below. \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} flint2-2.8.4/mpoly/exp_bits_required.c000066400000000000000000000055231414523752600177620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; max = user_exp[0]; if (mctx->deg) { for (i = 1; i < nfields - 1; i++) { max += user_exp[i]; if (max < user_exp[i]) return 2*FLINT_BITS; } } else { for (i = 1; 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_set(deg, user_exp + 0); for (i = 1; i < nvars; i++) { fmpz_add(deg, deg, user_exp + i); } exp_bits = 1 + fmpz_bits(deg); fmpz_clear(deg); } else { exp_bits = fmpz_bits(user_exp + 0); for (i = 1; i < nvars; i++) { exp_bits = FLINT_MAX(exp_bits, fmpz_bits(user_exp + i)); } 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_set(deg, user_exp[0]); for (i = 1; i < nvars; i++) { fmpz_add(deg, deg, user_exp[i]); } exp_bits = 1 + fmpz_bits(deg); fmpz_clear(deg); } else { exp_bits = fmpz_bits(user_exp[0]); for (i = 1; i < nvars; i++) { exp_bits = FLINT_MAX(exp_bits, fmpz_bits(user_exp[i])); } exp_bits += 1; } return exp_bits; } flint2-2.8.4/mpoly/fill_marks.c000066400000000000000000000066111414523752600163670ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/mpoly/gcd_info.c000066400000000000000000000472451414523752600160240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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--) SLONG_SWAP(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--) SLONG_SWAP(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; } flint2-2.8.4/mpoly/gen_bits_required.c000066400000000000000000000012261414523752600177330ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 */ } flint2-2.8.4/mpoly/gen_fields.c000066400000000000000000000023551414523752600163440ustar00rootroot00000000000000/* 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 2.1 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 (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); } flint2-2.8.4/mpoly/gen_monomial_offset_shift.c000066400000000000000000000063251414523752600214550ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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(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(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(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(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(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; } flint2-2.8.4/mpoly/gen_shift_left_right.c000066400000000000000000000063601414523752600204220ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/get_cmpmask.c000066400000000000000000000023531414523752600165350ustar00rootroot00000000000000/* 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 2.1 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->ord == ORD_DEGREVLEX) { /* 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); } } flint2-2.8.4/mpoly/get_monomial.c000066400000000000000000000145631414523752600167230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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); } 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; } flint2-2.8.4/mpoly/get_monomial_var.c000066400000000000000000000035031414523752600175630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/mpoly/inlines.c000066400000000000000000000011271414523752600157020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define MPOLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "mpoly.h" flint2-2.8.4/mpoly/is_gen.c000066400000000000000000000031231414523752600155030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/is_poly.c000066400000000000000000000023231414523752600157160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/is_proved_not_square.c000066400000000000000000000023461414523752600204770ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/mpoly/main_variable_split.c000066400000000000000000000030331414523752600202430ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/mpoly/max_fields.c000066400000000000000000000040551414523752600163570ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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 = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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; } flint2-2.8.4/mpoly/min_fields.c000066400000000000000000000044531414523752600163570ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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); } mpoly_unpack_vec_ui(min_fields, pmin, bits, mctx->nfields, 1); 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 = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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); } } mpoly_unpack_vec_fmpz(min_fields, pmin, bits, mctx->nfields, 1); TMP_END; } flint2-2.8.4/mpoly/monomial_cofactors.c000066400000000000000000000052561414523752600201260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/monomial_exists.c000066400000000000000000000044431414523752600174570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } } flint2-2.8.4/mpoly/monomial_index.c000066400000000000000000000073731414523752600172540ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/mpoly/monomial_mul_fmpz.c000066400000000000000000000031771414523752600177740ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "mpoly.h" 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; } } } flint2-2.8.4/mpoly/monomials_cmp.c000066400000000000000000000063251414523752600171030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/mpoly/monomials_deflate.c000066400000000000000000000031461414523752600177260ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/monomials_deflation.c000066400000000000000000000032041414523752600202620ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/monomials_inflate.c000066400000000000000000000026421414523752600177440ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/monomials_inorder_test.c000066400000000000000000000016751414523752600210300ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/mpoly/monomials_overflow_test.c000066400000000000000000000020711414523752600212200ustar00rootroot00000000000000/* 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 2.1 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 = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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; } flint2-2.8.4/mpoly/monomials_shift_right_ui.c000066400000000000000000000043741414523752600213350ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/mpoly/monomials_valid_test.c000066400000000000000000000024331414523752600204560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/pack_monomials_tight.c000066400000000000000000000017341414523752600204400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } } flint2-2.8.4/mpoly/pack_vec.c000066400000000000000000000063421414523752600160200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } } } flint2-2.8.4/mpoly/parse_pretty.c000066400000000000000000000336501414523752600167700ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); } #define PTR_SWAP(T, a, b) \ do { \ T * _tmp_ = a; \ a = b; \ b = _tmp_; \ } while (0); 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) { PTR_SWAP(char, E->terminal_strings[n-1].str, E->terminal_strings[n].str); SLONG_SWAP(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) { SLONG_SWAP(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; } flint2-2.8.4/mpoly/profile/000077500000000000000000000000001414523752600155345ustar00rootroot00000000000000flint2-2.8.4/mpoly/profile/p-test_irreducible.c000066400000000000000000000067731414523752600215020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.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; } flint2-2.8.4/mpoly/randbits_fmpz.c000066400000000000000000000022211414523752600170770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/mpoly/rbtree.c000066400000000000000000000247401414523752600155320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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: SLONG_SWAP(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: SLONG_SWAP(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; } flint2-2.8.4/mpoly/remove_var_powers.c000066400000000000000000000031761414523752600200130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/repack_monomials.c000066400000000000000000000067601414523752600175740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/reverse.c000066400000000000000000000014421414523752600157140ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } } flint2-2.8.4/mpoly/search_monomials.c000066400000000000000000000162511414523752600175700ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/mpoly/set_monomial.c000066400000000000000000000062711414523752600167340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/term_exp_fits.c000066400000000000000000000033271414523752600171150ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/test/000077500000000000000000000000001414523752600150535ustar00rootroot00000000000000flint2-2.8.4/mpoly/test/t-max_degrees_tight.c000066400000000000000000000060571414523752600211520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpoly.h" #include "ulong_extras.h" int main(void) { slong k, i, j, length, nfields, bits1, bits2; slong * bases, * max, * max2, * prods; ulong * a, * b, * c, * t; ulong max_length, max_fields; FLINT_TEST_INIT(state); flint_printf("max_degrees_tight...."); fflush(stdout); 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"); 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); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpoly/test/t-max_fields.c000066400000000000000000000047241414523752600176020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpoly.h" #include "ulong_extras.h" int main(void) { slong k, i, j, length, nfields, bits; ulong * a, * b, * max, * max2; ulong max_length, max_fields; FLINT_TEST_INIT(state); flint_printf("max_fields...."); fflush(stdout); 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); flint_abort(); } } } flint_free(max2); flint_free(max); flint_free(b); flint_free(a); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpoly/test/t-pack_unpack.c000066400000000000000000000065331414523752600177460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpoly.h" #include "ulong_extras.h" int main(void) { slong k, i, length, nfields, bits1, bits2; ulong * a, * b, * c, * d; ulong max_length, max_fields; FLINT_TEST_INIT(state); flint_printf("pack_unpack...."); fflush(stdout); 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); 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); flint_abort(); } } mpoly_ctx_clear(mctx); } } } flint_free(d); flint_free(c); flint_free(b); flint_free(a); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpoly/test/t-pack_unpack_tight.c000066400000000000000000000051771414523752600211500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "mpoly.h" #include "ulong_extras.h" int main(void) { slong k, i, j, length, nfields, bits1, bits2; slong * bases; ulong * a, * b, * c, * d, * t; ulong max_length, max_fields; FLINT_TEST_INIT(state); flint_printf("pack_unpack_tight...."); fflush(stdout); 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); flint_abort(); } } } flint_free(bases); flint_free(t); flint_free(d); flint_free(c); flint_free(b); flint_free(a); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/mpoly/test/t-search_monomials.c000066400000000000000000000140321414523752600210030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" #include "profiler.h" #include "ulong_extras.h" int main(void) { int i, j, k; FLINT_TEST_INIT(state); flint_printf("search_monomial...."); fflush(stdout); /* 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"); 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"); 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"); flint_abort(); } new_error = score < lower ? lower - score : score - upper; if (new_error < returned_error) { printf("returned score is not closest possible\n"); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/mpoly/test/t-test_irreducible.c000066400000000000000000000076421414523752600210210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "mpoly.h" #include "fmpz_mpoly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("test_irreducible...."); fflush(stdout); { 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"); 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"); 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"); 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"); flint_abort(); } fmpz_mpoly_clear(f, ctx); fmpz_mpoly_clear(g, ctx); fmpz_mpoly_clear(h, ctx); fmpz_mpoly_ctx_clear(ctx); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/mpoly/test_irreducible.c000066400000000000000000000524251414523752600176000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "mpoly.h" #include "long_extras.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) { SLONG_SWAP(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^(FLINT_BITS - 2) 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 useage */ 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; } flint2-2.8.4/mpoly/to_from_mpolyl.c000066400000000000000000000062061414523752600173050ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/mpoly/total_degree.c000066400000000000000000000062121414523752600166770ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/univar.c000066400000000000000000000617701414523752600155570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/mpoly/unpack_monomials_tight.c000066400000000000000000000020011414523752600207670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/mpoly/unpack_vec.c000066400000000000000000000065151414523752600163650ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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++; } } } flint2-2.8.4/mpoly/used_vars.c000066400000000000000000000072701414523752600162410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/n_poly.h000066400000000000000000001445321414523752600144160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef N_POLY_H #define N_POLY_H #ifdef N_POLY_INLINES_C #define N_POLY_INLINE FLINT_DLL #else #define N_POLY_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "nmod_poly.h" #include "fq_nmod_poly.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]; /* 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]; /*****************************************************************************/ N_POLY_INLINE void n_poly_init(n_poly_t A) { A->length = 0; A->alloc = 0; A->coeffs = NULL; } N_POLY_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)); } N_POLY_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); } FLINT_DLL int n_poly_is_canonical(const n_poly_t A); FLINT_DLL void n_poly_realloc(n_poly_t A, slong len); FLINT_DLL void n_poly_print_pretty(const n_poly_t A, const char * x); N_POLY_INLINE void n_poly_fit_length(n_poly_t A, slong len) { if (len > A->alloc) n_poly_realloc(A, len); } N_POLY_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; } N_POLY_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; } N_POLY_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; } N_POLY_INLINE void n_poly_swap(n_poly_t A, n_poly_t B) { n_poly_struct t = *B; *B = *A; *A = t; } N_POLY_INLINE void _n_poly_normalise(n_poly_t A) { while (A->length > 0 && A->coeffs[A->length - 1] == 0) A->length--; } N_POLY_INLINE slong n_poly_degree(const n_poly_t A) { FLINT_ASSERT(A->length >= 0); return A->length - 1; } N_POLY_INLINE int n_poly_is_one(const n_poly_t A) { return A->length == 1 && A->coeffs[0] == 1; } N_POLY_INLINE mp_limb_t n_poly_lead(const n_poly_t A) { FLINT_ASSERT(A->length > 0); return A->coeffs[A->length - 1]; } N_POLY_INLINE void n_poly_one(n_poly_t A) { n_poly_fit_length(A, 1); A->length = 1; A->coeffs[0] = 1; } N_POLY_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); } N_POLY_INLINE int n_poly_is_zero(const n_poly_t poly) { return poly->length == 0; } N_POLY_INLINE void n_poly_zero(n_poly_t res) { res->length = 0; } N_POLY_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; } /*****************************************************************************/ FLINT_DLL int n_poly_mod_is_canonical(const n_poly_t A, nmod_t mod); N_POLY_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); } N_POLY_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); } N_POLY_INLINE ulong n_poly_get_coeff(const n_poly_t poly, slong j) { return (j >= poly->length) ? 0 : poly->coeffs[j]; } N_POLY_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; } FLINT_DLL void n_poly_set_coeff(n_poly_t A, slong e, ulong c); FLINT_DLL void n_poly_mod_set_coeff_ui(n_poly_t A, slong j, ulong c, nmod_t mod); N_POLY_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; } N_POLY_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; } N_POLY_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; } N_POLY_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; } } N_POLY_INLINE void n_poly_truncate(n_poly_t poly, slong len) { if (poly->length > len) { poly->length = len; _n_poly_normalise(poly); } } N_POLY_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; } N_POLY_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); } FLINT_DLL void n_poly_mod_scalar_mul_ui(n_poly_t A, const n_poly_t B, mp_limb_t c, nmod_t ctx); FLINT_DLL mp_limb_t n_poly_mod_eval_step2(n_poly_t Acur, const n_poly_t Ainc, nmod_t mod); N_POLY_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); } N_POLY_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; } N_POLY_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); } FLINT_DLL void n_poly_mod_add_ui(n_poly_t res, const n_poly_t poly, ulong c, nmod_t ctx); N_POLY_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); } N_POLY_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); } FLINT_DLL void n_poly_mod_shift_left_scalar_addmul(n_poly_t A, slong k, mp_limb_t c, nmod_t mod); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL mp_limb_t _n_poly_eval_pow(n_poly_t P, n_poly_t alphapow, int nlimbs, nmod_t ctx); FLINT_DLL mp_limb_t n_poly_mod_eval_pow(n_poly_t P, n_poly_t alphapow, nmod_t ctx); FLINT_DLL 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); FLINT_DLL mp_limb_t n_poly_mod_div_root(n_poly_t Q, const n_poly_t A, mp_limb_t c, nmod_t ctx); N_POLY_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); } N_POLY_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; } N_POLY_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); } N_POLY_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); } FLINT_DLL ulong n_poly_mod_remove(n_poly_t f, const n_poly_t p, nmod_t ctx); FLINT_DLL void n_poly_mod_pow(n_poly_t res, const n_poly_t poly, ulong e, nmod_t ctx); FLINT_DLL void n_poly_mod_mul(n_poly_t A, const n_poly_t B, const n_poly_t C, nmod_t mod); FLINT_DLL void n_poly_mod_mullow(n_poly_t A, const n_poly_t B, const n_poly_t C, slong n, nmod_t mod); FLINT_DLL void n_poly_mod_div(n_poly_t Q, const n_poly_t A, const n_poly_t B, nmod_t mod); FLINT_DLL void n_poly_mod_rem(n_poly_t R, const n_poly_t A, const n_poly_t B, nmod_t mod); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int n_poly_mod_invmod(n_poly_t A, const n_poly_t B, const n_poly_t P, nmod_t mod); FLINT_DLL void n_poly_mod_gcd(n_poly_t G, const n_poly_t A, const n_poly_t B, nmod_t mod); FLINT_DLL 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); FLINT_DLL void n_poly_mod_inv_series(n_poly_t Qinv, const n_poly_t Q, slong n, nmod_t mod); FLINT_DLL 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); FLINT_DLL void n_poly_reverse(n_poly_t output, const n_poly_t input, slong m); FLINT_DLL 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); /*****************************************************************************/ N_POLY_INLINE nmod_t fq_nmod_ctx_mod(const fq_nmod_ctx_t ctx) { return ctx->modulus->mod; } N_POLY_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; } N_POLY_INLINE void _n_fq_zero(mp_limb_t * a, slong d) { slong i; for (i = 0; i < d; i++) a[i] = 0; } N_POLY_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; } N_POLY_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; } N_POLY_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)); } N_POLY_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; } N_POLY_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; } FLINT_DLL void n_fq_gen( mp_limb_t * a, const fq_nmod_ctx_t ctx); N_POLY_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); } N_POLY_INLINE void _n_fq_swap( mp_limb_t * a, /* length d */ mp_limb_t * b, /* length d */ slong d) { slong i = 0; do { MP_LIMB_SWAP(a[i], b[i]); i++; } while (i < d); } N_POLY_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; } FLINT_DLL int n_fq_equal_fq_nmod( const mp_limb_t * a, const fq_nmod_t b, const fq_nmod_ctx_t ctx); FLINT_DLL int n_fq_is_canonical( const mp_limb_t * a, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_randtest_not_zero( mp_limb_t * a, flint_rand_t state, const fq_nmod_ctx_t ctx); FLINT_DLL char * n_fq_get_str_pretty( const mp_limb_t * a, const fq_nmod_ctx_t ctx); FLINT_DLL int n_fq_fprint_pretty( FILE * file, const mp_limb_t * a, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_print_pretty( const mp_limb_t * a, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_get_fq_nmod( fq_nmod_t a, const mp_limb_t * b, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_set_fq_nmod( mp_limb_t * a, const fq_nmod_t b, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_get_n_poly( n_poly_t a, const mp_limb_t * b, const fq_nmod_ctx_t ctx); FLINT_DLL void _n_fq_set_n_poly( mp_limb_t * a, const mp_limb_t * bcoeffs, slong blen, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_add_si( mp_limb_t * a, const mp_limb_t * b, slong c, const fq_nmod_ctx_t ctx); N_POLY_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); N_POLY_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); } N_POLY_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); } N_POLY_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); } N_POLY_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); } N_POLY_INLINE 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); } FLINT_DLL 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 */ FLINT_DLL 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 FLINT_DLL 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 */ N_POLY_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 N_POLY_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); } N_POLY_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 FLINT_DLL int _n_fq_dot_lazy_size(slong len, const fq_nmod_ctx_t ctx); FLINT_DLL void _n_fq_reduce2_lazy1( mp_limb_t * a, /* length 6d, 2d used */ slong d, nmod_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _n_fq_reduce2_lazy2( mp_limb_t * a, /* length 6d, 4d used */ slong d, nmod_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _n_fq_reduce2_lazy3( mp_limb_t * a, /* length 6d */ slong d, nmod_t ctx); FLINT_DLL 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); FLINT_DLL 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 FLINT_DLL 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) FLINT_DLL void _n_fq_pow_ui( mp_limb_t * a, const mp_limb_t * b, ulong e, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_pow_fmpz( mp_limb_t * a, const mp_limb_t * b, const fmpz_t e, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_mul( mp_limb_t * a, const mp_limb_t * b, const mp_limb_t * c, const fq_nmod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void n_fq_inv( mp_limb_t * a, const mp_limb_t * b, const fq_nmod_ctx_t ctx); FLINT_DLL 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 FLINT_DLL void n_fq_poly_init2(n_fq_poly_t A, slong alloc, const fq_nmod_ctx_t ctx); FLINT_DLL void _n_fq_poly_one(n_fq_poly_t A, slong d); N_POLY_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)); } FLINT_DLL int n_fq_poly_is_one(n_fq_poly_t A, const fq_nmod_ctx_t ctx); FLINT_DLL int n_fq_poly_is_canonical( const n_fq_poly_t a, const fq_nmod_ctx_t ctx); N_POLY_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--; } FLINT_DLL void n_fq_poly_print_pretty( const n_fq_poly_t A, const char * x, const fq_nmod_ctx_t ctx); FLINT_DLL int n_fq_poly_equal( const n_fq_poly_t A, const n_fq_poly_t B, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_poly_set( n_fq_poly_t A, const n_fq_poly_t B, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_poly_randtest( n_fq_poly_t A, flint_rand_t state, slong len, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_poly_make_monic( n_fq_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void n_fq_poly_scalar_mul_ui( n_poly_t A, const n_poly_t B, ulong c, const fq_nmod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void n_fq_poly_get_fq_nmod_poly( fq_nmod_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_poly_set_fq_nmod_poly( n_poly_t A, const fq_nmod_poly_t B, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_poly_set_n_fq( n_poly_t A, const mp_limb_t * c, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_poly_set_fq_nmod( n_poly_t A, const fq_nmod_t c, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_poly_shift_right( n_poly_t A, const n_poly_t B, slong n, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_poly_shift_left( n_poly_t A, const n_poly_t B, slong n, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_poly_truncate( n_poly_t A, slong len, const fq_nmod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void n_fq_poly_neg( n_poly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_poly_add_si( n_poly_t A, const n_poly_t B, slong c, const fq_nmod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void n_fq_poly_pow( n_poly_t A, const n_poly_t B, ulong e, const fq_nmod_ctx_t ctx); FLINT_DLL ulong n_fq_poly_remove( n_poly_t f, const n_poly_t g, const fq_nmod_ctx_t ctx); FLINT_DLL 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); N_POLY_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); } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void n_fq_poly_inv_series( n_poly_t A, const n_poly_t B, slong order, const fq_nmod_ctx_t ctx); FLINT_DLL 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); /*****************************************************************************/ N_POLY_INLINE void n_bpoly_init(n_bpoly_t A) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } FLINT_DLL void n_bpoly_clear(n_bpoly_t A); N_POLY_INLINE void n_bpoly_swap(n_bpoly_t A, n_bpoly_t B) { n_bpoly_struct t = *A; *A = *B; *B = t; } FLINT_DLL void n_bpoly_print_pretty(const n_bpoly_t A, const char * xvar, const char * yvar); N_POLY_INLINE void n_bpoly_normalise(n_bpoly_t A) { while (A->length > 0 && n_poly_is_zero(A->coeffs + A->length - 1)) A->length--; } FLINT_DLL void n_bpoly_realloc(n_bpoly_t A, slong len); N_POLY_INLINE void n_bpoly_fit_length(n_bpoly_t A, slong len) { if (len > A->alloc) n_bpoly_realloc(A, len); } N_POLY_INLINE void n_bpoly_zero(n_bpoly_t A) { A->length = 0; } N_POLY_INLINE int n_bpoly_is_zero(const n_bpoly_t A) { return A->length == 0; } FLINT_DLL void _n_bpoly_set(n_bpoly_t A, const n_bpoly_t B); N_POLY_INLINE void n_bpoly_set(n_bpoly_t A, const n_bpoly_t B) { if (A != B) _n_bpoly_set(A, B); } FLINT_DLL void n_bpoly_one(n_bpoly_t A); FLINT_DLL int n_bpoly_equal(const n_bpoly_t A, const n_bpoly_t B); FLINT_DLL void n_bpoly_set_coeff(n_bpoly_t A, slong e0, slong e1, mp_limb_t c); FLINT_DLL void n_bpoly_set_coeff_nonzero(n_bpoly_t A, slong e0, slong e1, mp_limb_t c); FLINT_DLL void n_bpoly_mod_derivative_gen0(n_bpoly_t A, const n_bpoly_t B, nmod_t ctx); N_POLY_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); } N_POLY_INLINE slong n_bpoly_degree0(const n_bpoly_t A) { return A->length - 1; } FLINT_DLL slong n_bpoly_degree1(const n_bpoly_t A); FLINT_DLL void n_bpoly_set_poly_gen1(n_bpoly_t A, const n_poly_t B); FLINT_DLL void n_bpoly_set_poly_gen0(n_bpoly_t A, const n_poly_t B); /*****************************************************************************/ FLINT_DLL int n_bpoly_mod_is_canonical(const n_bpoly_t A, nmod_t mod); N_POLY_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; } FLINT_DLL void n_bpoly_scalar_mul_nmod(n_bpoly_t A, mp_limb_t c, nmod_t ctx); FLINT_DLL void n_bpoly_mod_content_last(n_poly_t g, const n_bpoly_t A, nmod_t ctx); FLINT_DLL void n_bpoly_mod_divexact_last(n_bpoly_t A, const n_poly_t b, nmod_t ctx); FLINT_DLL void n_bpoly_mod_mul_last(n_bpoly_t A, const n_poly_t b, nmod_t ctx); FLINT_DLL void n_bpoly_mod_taylor_shift_gen1(n_bpoly_t A, const n_bpoly_t B, mp_limb_t c, nmod_t ctx); FLINT_DLL void n_bpoly_mod_taylor_shift_gen0(n_bpoly_t A, mp_limb_t c, nmod_t ctx); FLINT_DLL void n_bpoly_mod_add(n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, nmod_t ctx); FLINT_DLL void n_bpoly_mod_sub(n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, nmod_t ctx); FLINT_DLL void n_bpoly_mod_make_primitive(n_poly_t g, n_bpoly_t A, nmod_t ctx); FLINT_DLL void n_bpoly_mod_mul(n_bpoly_t A, const n_bpoly_t B, const n_bpoly_t C, nmod_t ctx); FLINT_DLL int n_bpoly_mod_divides(n_bpoly_t Q, const n_bpoly_t A, const n_bpoly_t B, nmod_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL int n_fq_bpoly_equal( const n_bpoly_t A, const n_bpoly_t B, const fq_nmod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void n_fq_bpoly_set_n_fq_poly_gen0( n_bpoly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_bpoly_set_n_fq_poly_gen1( n_bpoly_t A, const n_poly_t B, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_bpoly_derivative_gen0( n_bpoly_t A, const n_bpoly_t B, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_bpoly_scalar_mul_n_fq( n_fq_bpoly_t A, const mp_limb_t * c, const fq_nmod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void n_fq_bpoly_taylor_shift_gen0_fq_nmod( n_bpoly_t A, const fq_nmod_t alpha, const fq_nmod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void n_fq_bpoly_print_pretty( const n_fq_bpoly_t A, const char * xvar, const char * yvar, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_bpoly_one(n_fq_bpoly_t A, const fq_nmod_ctx_t ctx); FLINT_DLL void n_fq_bpoly_set(n_fq_bpoly_t A, const n_fq_bpoly_t B, const fq_nmod_ctx_t ctx); FLINT_DLL int n_fq_bpoly_is_canonical(const n_fq_bpoly_t A, const fq_nmod_ctx_t ctx); /*****************************************************************************/ N_POLY_INLINE void n_tpoly_init(n_tpoly_t A) { A->coeffs = NULL; A->alloc = 0; A->length = 0; } N_POLY_INLINE void n_tpoly_swap(n_tpoly_t A, n_tpoly_t B) { n_tpoly_struct t = *A; *A = *B; *B = t; } FLINT_DLL void n_tpoly_fit_length(n_tpoly_t A, slong len); FLINT_DLL void n_tpoly_clear(n_tpoly_t A); /*****************************************************************************/ N_POLY_INLINE void n_polyu_init(n_polyu_t A) { A->coeffs = NULL; A->exps = NULL; A->length = 0; A->alloc = 0; } FLINT_DLL void n_polyu_clear(n_polyu_t A); FLINT_DLL void n_polyu_realloc(n_polyu_t A, slong len); N_POLY_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); } N_POLY_INLINE void n_polyu_swap(n_polyu_t A, n_polyu_t B) { n_polyu_struct T = *B; *B = *A; *A = T; } FLINT_DLL void n_polyu3_print_pretty(const n_polyu_t A, const char * gen0, const char * gen1, const char * var2); FLINT_DLL void n_polyu3_degrees(slong * deg0, slong * deg1, slong * deg2, const n_polyu_t A); /*****************************************************************************/ FLINT_DLL void nmod_pow_cache_start(mp_limb_t b, n_poly_t pos_direct, n_poly_t pos_bin, n_poly_t neg_direct); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ 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]; FLINT_DLL void nmod_eval_interp_init(nmod_eval_interp_t E); FLINT_DLL void nmod_eval_interp_clear(nmod_eval_interp_t E); FLINT_DLL int nmod_eval_interp_set_degree_modulus( nmod_eval_interp_t E, slong deg, nmod_t ctx); N_POLY_INLINE slong nmod_eval_interp_eval_length(nmod_eval_interp_t E) { return 1 + E->radix*E->d; } FLINT_DLL void nmod_eval_interp_to_coeffs_poly( n_poly_t a, const n_poly_t v, nmod_eval_interp_t E, nmod_t ctx); FLINT_DLL void nmod_eval_interp_from_coeffs_poly( n_poly_t v, const n_poly_t a, nmod_eval_interp_t E, nmod_t ctx); FLINT_DLL 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); FLINT_DLL 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); N_POLY_INLINE void nmod_evals_zero(n_poly_t a) { a->length = 0; } FLINT_DLL void nmod_evals_add_inplace(n_poly_t a, n_poly_t b, slong len, nmod_t ctx); FLINT_DLL void nmod_evals_mul(n_poly_t a, n_poly_t b, n_poly_t c, slong len, nmod_t ctx); FLINT_DLL void nmod_evals_addmul(n_poly_t a, n_poly_t b, n_poly_t c, slong len, nmod_t ctx); FLINT_DLL 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); N_POLY_INLINE void n_fq_evals_zero(n_fq_poly_t a) { a->length = 0; } FLINT_DLL void n_fq_evals_add_inplace(n_fq_poly_t a, n_fq_poly_t b, slong len, const fq_nmod_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ N_POLY_INLINE void n_polyun_init(n_polyun_t A) { A->coeffs = NULL; A->exps = NULL; A->length = 0; A->alloc = 0; } FLINT_DLL int n_polyun_is_canonical(const n_polyun_t A); FLINT_DLL void n_polyun_clear(n_polyun_t A); FLINT_DLL void n_polyun_realloc(n_polyun_t A, slong len); N_POLY_INLINE void n_polyun_fit_length(n_polyun_t A, slong len) { if (len > A->alloc) n_polyun_realloc(A, len); } FLINT_DLL int n_polyun_mod_is_canonical(const n_polyun_t A, nmod_t mod); N_POLY_INLINE void n_polyun_swap(n_polyun_t A, n_polyun_t B) { n_polyun_struct t = *B; *B = *A; *A = t; } FLINT_DLL void n_polyun_set(n_polyun_t A, const n_polyun_t B); FLINT_DLL void n_polyu1n_print_pretty(const n_polyun_t A, const char * var0, const char * varlast); FLINT_DLL void n_polyu2n_print_pretty(const n_polyun_t A, const char * gen0, const char * gen1, const char * varlast); FLINT_DLL void n_polyu3n_print_pretty(const n_polyun_t A, const char * gen0, const char * gen1, const char * var2, const char * varlast); FLINT_DLL void n_fq_polyun_set(n_fq_polyun_t A, const n_fq_polyun_t B, const fq_nmod_ctx_t ctx); FLINT_DLL int n_polyun_equal(const n_polyun_t A, const n_polyun_t B); N_POLY_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); } N_POLY_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; } /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL slong n_polyun_product_roots(n_polyun_t M, const n_polyun_t H, nmod_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL void n_poly_stack_init(n_poly_stack_t S); FLINT_DLL void n_poly_stack_clear(n_poly_stack_t S); FLINT_DLL n_poly_struct ** n_poly_stack_fit_request(n_poly_stack_t S, slong k); N_POLY_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; } N_POLY_INLINE void n_poly_stack_vec_clear(n_poly_stack_t S) { FLINT_ASSERT(S->top >= 1); S->top -= 1; } N_POLY_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; } N_POLY_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]; } N_POLY_INLINE void n_poly_stack_give_back(n_poly_stack_t S, slong k) { FLINT_ASSERT(S->top >= k); S->top -= k; } N_POLY_INLINE slong n_poly_stack_size(const n_poly_stack_t S) { return S->top; } /*****************************************************************************/ FLINT_DLL void n_bpoly_stack_init(n_bpoly_stack_t S); FLINT_DLL void n_bpoly_stack_clear(n_bpoly_stack_t S); FLINT_DLL n_bpoly_struct ** n_bpoly_stack_fit_request(n_bpoly_stack_t S, slong k); N_POLY_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; } N_POLY_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]; } N_POLY_INLINE void n_bpoly_stack_give_back(n_bpoly_stack_t S, slong k) { FLINT_ASSERT(S->top >= k); S->top -= k; } N_POLY_INLINE slong n_bpoly_stack_size(const n_bpoly_stack_t S) { return S->top; } /*****************************************************************************/ FLINT_DLL void n_polyun_stack_init(n_polyun_stack_t S); FLINT_DLL void n_polyun_stack_clear(n_polyun_stack_t S); FLINT_DLL n_polyun_struct ** n_polyun_stack_fit_request(n_polyun_stack_t S, slong k); N_POLY_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; } N_POLY_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]; } N_POLY_INLINE void n_polyun_stack_give_back(n_polyun_stack_t S, slong k) { FLINT_ASSERT(S->top >= k); S->top -= k; } N_POLY_INLINE slong n_polyun_stack_size(const n_polyun_stack_t S) { return S->top; } #ifdef __cplusplus } #endif #endif flint2-2.8.4/n_poly/000077500000000000000000000000001414523752600142345ustar00rootroot00000000000000flint2-2.8.4/n_poly/n_bpoly.c000066400000000000000000000075701414523752600160530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } 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"); } 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); } flint2-2.8.4/n_poly/n_bpoly_mod.c000066400000000000000000000052401414523752600167020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_div(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); } flint2-2.8.4/n_poly/n_bpoly_mod_gcd.c000066400000000000000000000326221414523752600175230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_div(cAbar, cA, cG, ctx); n_poly_mod_div(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_div(Abarevalp, Aevalp, Gevalp, ctx); n_poly_mod_div(Bbarevalp, Bevalp, Gevalp, ctx); n_poly_mod_gcd(Gevalm, Aevalm, Bevalm, ctx); n_poly_mod_div(Abarevalm, Aevalm, Gevalm, ctx); n_poly_mod_div(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; } flint2-2.8.4/n_poly/n_bpoly_stack.c000066400000000000000000000032251414523752600172310ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/n_poly/n_fq.c000066400000000000000000000531571414523752600153360ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "nmod_vec.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); \ } 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_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) { if (lenQ == 2) _nmod_poly_divrem_q1(Q, R, A, lenA, B, lenB, ctx->mod); else _nmod_poly_divrem_q0(Q, R, A, B, lenB, 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_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; } flint2-2.8.4/n_poly/n_fq_bpoly.c000066400000000000000000000115551414523752600165370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_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_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); } flint2-2.8.4/n_poly/n_fq_bpoly_gcd.c000066400000000000000000000742171414523752600173600ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/n_poly/n_fq_bpoly_taylor_shift.c000066400000000000000000000065041414523752600213240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/n_poly/n_fq_poly.c000066400000000000000000000334441414523752600163760ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "nmod_vec.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_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_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; } flint2-2.8.4/n_poly/n_fq_poly_add.c000066400000000000000000000026171414523752600172040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/n_poly/n_fq_poly_add_si.c000066400000000000000000000014301414523752600176670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/n_poly/n_fq_poly_divrem.c000066400000000000000000000260451414523752600177430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #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); } flint2-2.8.4/n_poly/n_fq_poly_gcd.c000066400000000000000000000137151414523752600172120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 } flint2-2.8.4/n_poly/n_fq_poly_inv_series.c000066400000000000000000000015241414523752600206160ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/n_poly/n_fq_poly_mul.c000066400000000000000000000117141414523752600172470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "n_poly.h" 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); } flint2-2.8.4/n_poly/n_fq_poly_mullow.c000066400000000000000000000075711414523752600177770ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "n_poly.h" 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); } flint2-2.8.4/n_poly/n_fq_poly_mulmod.c000066400000000000000000000021061414523752600177420ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/n_poly/n_fq_poly_neg.c000066400000000000000000000013061414523752600172170ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/n_poly/n_fq_poly_pow.c000066400000000000000000000014761414523752600172630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/n_poly/n_fq_poly_rem.c000066400000000000000000000016671414523752600172430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/n_poly/n_fq_poly_sub.c000066400000000000000000000025571414523752600172500ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/n_poly/n_fq_poly_xgcd.c000066400000000000000000000022541414523752600173760ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/n_poly/n_fq_polyun.c000066400000000000000000000013101414523752600167240ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/n_poly/n_fq_pow_cache.c000066400000000000000000000162071414523752600173410ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/n_poly/n_poly.c000066400000000000000000000042351414523752600157040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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_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; } } flint2-2.8.4/n_poly/n_poly_mod.c000066400000000000000000000613101414523752600165400ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "mpn_extras.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_printf("Exception (nmod_poly_mulmod). Divide by zero.\n"); flint_abort(); } 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_printf("Exception (n_poly_mod_div). Division by zero.\n"); flint_abort(); } } 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_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_printf("Exception (nmod_poly_rem). Division by zero.\n"); flint_abort(); } 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_printf("Exception (n_poly_mod_divrem). Division by zero."); flint_abort(); } } 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) { printf("Exception (nmod_poly_invmod). lenP < 2.\n"); flint_abort(); } 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_printf("n_poly_mod_mulmod_preinv: Input is larger than modulus."); flint_abort(); } 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_printf("Exception (n_poly_div_series). Division by zero.\n"); flint_abort(); } 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; } flint2-2.8.4/n_poly/n_poly_stack.c000066400000000000000000000032071414523752600170670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/n_poly/n_polyu.c000066400000000000000000000046071414523752600160740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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_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); } flint2-2.8.4/n_poly/n_polyu1n_gcd.c000066400000000000000000000351011414523752600171410ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_div(cAbar, cA, cG, ctx); n_poly_mod_div(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_div(Abarevalp, Aevalp, Gevalp, ctx); n_poly_mod_div(Bbarevalp, Bevalp, Gevalp, ctx); n_poly_mod_gcd(Gevalm, Aevalm, Bevalm, ctx); n_poly_mod_div(Abarevalm, Aevalm, Gevalm, ctx); n_poly_mod_div(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; } flint2-2.8.4/n_poly/n_polyun.c000066400000000000000000000072271414523752600162530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" #include "mpn_extras.h" #include "nmod_vec.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_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"); } 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; } flint2-2.8.4/n_poly/n_polyun_stack.c000066400000000000000000000024211414523752600174270ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/n_poly/n_tpoly.c000066400000000000000000000022411414523752600160630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.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); } } flint2-2.8.4/n_poly/nmod_n_fq_interp.c000066400000000000000000000625241414523752600177320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "n_poly.h" /* conversion between polynomials in coefficient form and point-value form and artihmetic 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; } flint2-2.8.4/n_poly/nmod_pow_cache.c000066400000000000000000000116011414523752600173440ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/n_poly/test/000077500000000000000000000000001414523752600152135ustar00rootroot00000000000000flint2-2.8.4/n_poly/test/t-n_fq_poly_add.c000066400000000000000000000043471414523752600204260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "n_poly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); for (i = 0; i < 100 * 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_randtest(ctx, state); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/n_poly/test/t-n_fq_poly_divrem.c000066400000000000000000000051661414523752600211640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "n_poly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("n_fq_poly_divrem...."); fflush(stdout); for (i = 0; i < 2000 * 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_randtest(ctx, state); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/n_poly/test/t-n_fq_poly_gcd.c000066400000000000000000000046111414523752600204250ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "n_poly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("n_fq_poly_gcd...."); fflush(stdout); 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_randtest(ctx, state); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/n_poly/test/t-n_fq_poly_mul.c000066400000000000000000000043621414523752600204700ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "n_poly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("n_fq_poly_mul...."); fflush(stdout); 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_randtest(ctx, state); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/n_poly/test/t-n_fq_poly_sub.c000066400000000000000000000043471414523752600204670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "n_poly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); for (i = 0; i < 100 * 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_randtest(ctx, state); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/n_poly/zippel_helpers.c000066400000000000000000000314561414523752600174360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mat.h000066400000000000000000000312571414523752600147130ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define NMOD_MAT_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "longlong.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "fmpz.h" #include "thread_support.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; /* nmod_mat_t allows reference-like semantics for nmod_mat_struct */ typedef nmod_mat_struct nmod_mat_t[1]; #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; } NMOD_MAT_INLINE void _nmod_mat_set_mod(nmod_mat_t mat, mp_limb_t n) { mat->mod.n = n; count_leading_zeros(mat->mod.norm, n); invert_limb(mat->mod.ninv, n << mat->mod.norm); } /* Memory management */ FLINT_DLL void nmod_mat_init(nmod_mat_t mat, slong rows, slong cols, mp_limb_t n); FLINT_DLL void nmod_mat_init_set(nmod_mat_t mat, const nmod_mat_t src); FLINT_DLL void nmod_mat_clear(nmod_mat_t mat); FLINT_DLL void nmod_mat_one(nmod_mat_t mat); FLINT_DLL 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++) MP_LIMB_SWAP(row1[j], row2[j]); } } /* Windows and concatenation */ FLINT_DLL void nmod_mat_window_init(nmod_mat_t window, const nmod_mat_t mat, slong r1, slong c1, slong r2, slong c2); FLINT_DLL void nmod_mat_window_clear(nmod_mat_t window); FLINT_DLL void nmod_mat_concat_horizontal(nmod_mat_t res, const nmod_mat_t mat1, const nmod_mat_t mat2); FLINT_DLL void nmod_mat_concat_vertical(nmod_mat_t res, const nmod_mat_t mat1, const nmod_mat_t mat2); /* Random matrix generation */ FLINT_DLL void nmod_mat_randtest(nmod_mat_t mat, flint_rand_t state); FLINT_DLL void nmod_mat_randfull(nmod_mat_t mat, flint_rand_t state); FLINT_DLL int nmod_mat_randpermdiag(nmod_mat_t mat, flint_rand_t state, mp_srcptr diag, slong n); FLINT_DLL void nmod_mat_randrank(nmod_mat_t, flint_rand_t state, slong rank); FLINT_DLL void nmod_mat_randops(nmod_mat_t mat, slong count, flint_rand_t state); FLINT_DLL void nmod_mat_randtril(nmod_mat_t mat, flint_rand_t state, int unit); FLINT_DLL void nmod_mat_randtriu(nmod_mat_t mat, flint_rand_t state, int unit); FLINT_DLL void nmod_mat_print_pretty(const nmod_mat_t mat); FLINT_DLL int nmod_mat_equal(const nmod_mat_t mat1, const nmod_mat_t mat2); FLINT_DLL void nmod_mat_zero(nmod_mat_t mat); FLINT_DLL int nmod_mat_is_zero(const nmod_mat_t mat); NMOD_MAT_INLINE int nmod_mat_is_zero_row(const nmod_mat_t mat, slong i) { return _nmod_vec_is_zero(mat->rows[i], mat->c); } 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); } FLINT_DLL void nmod_mat_set(nmod_mat_t B, const nmod_mat_t A); FLINT_DLL void nmod_mat_transpose(nmod_mat_t B, const nmod_mat_t A); /* Addition and subtraction */ FLINT_DLL void nmod_mat_add(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); FLINT_DLL void nmod_mat_sub(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); FLINT_DLL void nmod_mat_neg(nmod_mat_t B, const nmod_mat_t A); /* Matrix-scalar arithmetic */ FLINT_DLL void nmod_mat_scalar_mul(nmod_mat_t B, const nmod_mat_t A, mp_limb_t c); FLINT_DLL 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); /* deprecated */ #define nmod_mat_scalar_mul_add(dest, X, b, Y) nmod_mat_scalar_addmul_ui(dest, X, Y, b) NMOD_MAT_INLINE void nmod_mat_scalar_mul_fmpz(nmod_mat_t res, const nmod_mat_t M, const fmpz_t c) { fmpz_t d; fmpz_init(d); fmpz_mod_ui(d, c, res->mod.n); nmod_mat_scalar_mul(res, M, fmpz_get_ui(d)); fmpz_clear(d); } /* Matrix multiplication */ FLINT_DLL void nmod_mat_mul(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); FLINT_DLL int nmod_mat_mul_blas(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); FLINT_DLL void nmod_mat_mul_classical(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); FLINT_DLL 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); FLINT_DLL void nmod_mat_mul_classical_threaded(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); FLINT_DLL void nmod_mat_mul_strassen(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); FLINT_DLL 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); FLINT_DLL void nmod_mat_addmul(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); FLINT_DLL void nmod_mat_submul(nmod_mat_t D, const nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); FLINT_DLL void nmod_mat_mul_nmod_vec(mp_limb_t * c, const nmod_mat_t A, const mp_limb_t * b, slong blen); FLINT_DLL 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); FLINT_DLL void nmod_mat_nmod_vec_mul(mp_limb_t * c, const mp_limb_t * a, slong alen, const nmod_mat_t B); FLINT_DLL 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 */ FLINT_DLL void _nmod_mat_pow(nmod_mat_t dest, const nmod_mat_t mat, ulong pow); FLINT_DLL void nmod_mat_pow(nmod_mat_t dest, const nmod_mat_t mat, ulong pow); /* Trace */ FLINT_DLL mp_limb_t nmod_mat_trace(const nmod_mat_t mat); /* Determinant */ FLINT_DLL mp_limb_t _nmod_mat_det(nmod_mat_t A); FLINT_DLL mp_limb_t nmod_mat_det(const nmod_mat_t A); FLINT_DLL mp_limb_t _nmod_mat_det_howell(nmod_mat_t A); FLINT_DLL mp_limb_t nmod_mat_det_howell(const nmod_mat_t A); /* Rank */ FLINT_DLL slong nmod_mat_rank(const nmod_mat_t A); /* Inverse */ FLINT_DLL 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)) { mp_limb_t * 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; } } 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 t; if (perm) { t = perm[s]; perm[s] = perm[r]; perm[r] = t; } for (t = 0; t < mat->r; t++) { mp_limb_t c = mat->rows[t][r]; mat->rows[t][r] = mat->rows[t][s]; mat->rows[t][s] = c; } } } NMOD_MAT_INLINE void nmod_mat_invert_cols(nmod_mat_t mat, slong * perm) { if (!(nmod_mat_is_empty(mat))) { slong t; slong i; slong c = mat->c; slong k = mat->c/2; mp_limb_t e; if (perm) { for (i =0; i < k; i++) { t = perm[i]; perm[i] = perm[c - i]; perm[c - i] = t; } } for (t = 0; t < mat->r; t++) { for (i = 0; i < k; i++) { e = mat->rows[t][i]; mat->rows[t][i] = mat->rows[t][c - i - 1]; mat->rows[t][c - i - 1] = e; } } } } FLINT_DLL void nmod_mat_apply_permutation(nmod_mat_t A, slong * P, slong n); /* Triangular solving */ FLINT_DLL void nmod_mat_solve_tril(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit); FLINT_DLL void nmod_mat_solve_tril_recursive(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit); FLINT_DLL void nmod_mat_solve_tril_classical(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit); FLINT_DLL void nmod_mat_solve_triu(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit); FLINT_DLL void nmod_mat_solve_triu_recursive(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit); FLINT_DLL void nmod_mat_solve_triu_classical(nmod_mat_t X, const nmod_mat_t U, const nmod_mat_t B, int unit); /* LU decomposition */ FLINT_DLL slong nmod_mat_lu(slong * P, nmod_mat_t A, int rank_check); FLINT_DLL slong nmod_mat_lu_classical(slong * P, nmod_mat_t A, int rank_check); FLINT_DLL slong nmod_mat_lu_recursive(slong * P, nmod_mat_t A, int rank_check); /* Nonsingular solving */ FLINT_DLL int nmod_mat_solve(nmod_mat_t X, const nmod_mat_t A, const nmod_mat_t B); FLINT_DLL int nmod_mat_solve_vec(mp_ptr x, const nmod_mat_t A, mp_srcptr b); /* Solving */ FLINT_DLL 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); FLINT_DLL int nmod_mat_can_solve(nmod_mat_t X, const nmod_mat_t A, const nmod_mat_t B); /* Reduced row echelon form */ FLINT_DLL slong nmod_mat_rref(nmod_mat_t A); FLINT_DLL slong _nmod_mat_rref(nmod_mat_t A, slong * pivots_nonpivots, slong * P); FLINT_DLL slong nmod_mat_rref_classical(nmod_mat_t A); FLINT_DLL slong _nmod_mat_rref_classical(nmod_mat_t A, slong * pivots_nonpivots); FLINT_DLL slong nmod_mat_rref_storjohann(nmod_mat_t A); FLINT_DLL slong _nmod_mat_rref_storjohann(nmod_mat_t A, slong * pivots_nonpivots); FLINT_DLL slong nmod_mat_reduce_row(nmod_mat_t M, slong * P, slong * L, slong m); /* Nullspace */ FLINT_DLL slong nmod_mat_nullspace(nmod_mat_t X, const nmod_mat_t A); /* Howell form */ FLINT_DLL void nmod_mat_strong_echelon_form(nmod_mat_t A); FLINT_DLL slong nmod_mat_howell_form(nmod_mat_t A); /* Transforms */ FLINT_DLL 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 * * FLINT_DLL void nmod_mat_charpoly_danilevsky(nmod_poly_t p, const nmod_mat_t M); * * FLINT_DLL 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 /* Cutoff between classical and recursive LU decomposition */ #define NMOD_MAT_LU_RECURSIVE_CUTOFF 4 /* 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 *******************************************************************/ FLINT_DLL void nmod_mat_set_entry(nmod_mat_t mat, slong i, slong j, mp_limb_t x); #ifdef __cplusplus } #endif #endif flint2-2.8.4/nmod_mat/000077500000000000000000000000001414523752600145325ustar00rootroot00000000000000flint2-2.8.4/nmod_mat/add.c000066400000000000000000000013301414523752600154230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.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); } } flint2-2.8.4/nmod_mat/addmul.c000066400000000000000000000021701414523752600161440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.h" #include "thread_support.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); } } flint2-2.8.4/nmod_mat/can_solve.c000066400000000000000000000062701414523752600166540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #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 == 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; 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) { 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); 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); } flint2-2.8.4/nmod_mat/charpoly.c000066400000000000000000000013251414523752600165200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.h" 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); } flint2-2.8.4/nmod_mat/charpoly_berkowitz.c000066400000000000000000000056341414523752600206270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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_printf("Exception (nmod_mat_charpoly_berkowitz). Non-square matrix.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_mat/charpoly_danilevsky.c000066400000000000000000000103351414523752600207520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.h" 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_printf("Exception (nmod_mat_charpoly_danilevsky). Non-square matrix.\n"); flint_abort(); } 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; } flint2-2.8.4/nmod_mat/clear.c000066400000000000000000000012641414523752600157670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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); } flint2-2.8.4/nmod_mat/concat_horizontal.c000066400000000000000000000013601414523752600204160ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/nmod_mat/concat_vertical.c000066400000000000000000000013751414523752600200440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" 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); } flint2-2.8.4/nmod_mat/det.c000066400000000000000000000077551414523752600154700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.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_printf("Exception (nmod_mat_det). Non-square matrix.\n"); flint_abort(); } 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; } flint2-2.8.4/nmod_mat/det_howell.c000066400000000000000000000103151414523752600170240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.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 wether 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_printf("Exception (nmod_mat_det_howell). Non-square matrix.\n"); flint_abort(); } nmod_mat_init_set(tmp, A); det = _nmod_mat_det_howell(tmp); nmod_mat_clear(tmp); return det; } flint2-2.8.4/nmod_mat/equal.c000066400000000000000000000017631414523752600160140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.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; } flint2-2.8.4/nmod_mat/howell_form.c000066400000000000000000000020621414523752600172130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.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; } flint2-2.8.4/nmod_mat/init.c000066400000000000000000000022501414523752600156400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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); } flint2-2.8.4/nmod_mat/init_set.c000066400000000000000000000023551414523752600165210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" 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; } flint2-2.8.4/nmod_mat/inlines.c000066400000000000000000000013331414523752600163370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define NMOD_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #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; } flint2-2.8.4/nmod_mat/inv.c000066400000000000000000000024351414523752600154760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.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; } flint2-2.8.4/nmod_mat/is_zero.c000066400000000000000000000013541414523752600163530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.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; } flint2-2.8.4/nmod_mat/lu.c000066400000000000000000000011661414523752600153220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_mat.h" slong nmod_mat_lu(slong * P, nmod_mat_t A, int rank_check) { return nmod_mat_lu_recursive(P, A, rank_check); } flint2-2.8.4/nmod_mat/lu_classical.c000066400000000000000000000040161414523752600173350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.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 = n_invmod(d, mod.n); length = n - col - 1; for (i = row + 1; i < m; i++) { e = n_mulmod2_preinv(a[i][col], d, mod.n, mod.ninv); 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; } flint2-2.8.4/nmod_mat/lu_recursive.c000066400000000000000000000055701414523752600174140ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #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; if (m < NMOD_MAT_LU_RECURSIVE_CUTOFF || n < NMOD_MAT_LU_RECURSIVE_CUTOFF) { 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; } flint2-2.8.4/nmod_mat/minpoly.c000066400000000000000000000100101414523752600163550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.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_printf("Exception (nmod_mat_charpoly). Non-square matrix.\n"); flint_abort(); } 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); nmod_poly_mul(p, p, b); nmod_poly_div(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); } flint2-2.8.4/nmod_mat/mul.c000066400000000000000000000050731414523752600155000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.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(); #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); } flint2-2.8.4/nmod_mat/mul_blas.c000066400000000000000000000503641414523752600165040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" #include "thread_support.h" #if FLINT_USES_BLAS && FLINT_BITS == 64 #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 calculting 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 flint2-2.8.4/nmod_mat/mul_classical.c000066400000000000000000000121541414523752600175140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.h" /* 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); } flint2-2.8.4/nmod_mat/mul_classical_threaded.c000066400000000000000000000277031414523752600213620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.h" #include "thread_support.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); } flint2-2.8.4/nmod_mat/mul_nmod_vec.c000066400000000000000000000014461414523752600173520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/nmod_mat/mul_nmod_vec_ptr.c000066400000000000000000000016411414523752600202340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" 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; } flint2-2.8.4/nmod_mat/mul_strassen.c000066400000000000000000000102761414523752600174230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" 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_sub(X1, A11, A21); nmod_mat_sub(X2, B22, B12); nmod_mat_mul(C21, X1, X2); nmod_mat_add(X1, A21, A22); nmod_mat_sub(X2, B12, B11); nmod_mat_mul(C22, X1, X2); nmod_mat_sub(X1, X1, A11); nmod_mat_sub(X2, B22, X2); nmod_mat_mul(C12, X1, X2); nmod_mat_sub(X1, A12, X1); nmod_mat_mul(C11, X1, B22); X1->c = bnc; nmod_mat_mul(X1, A11, B11); nmod_mat_add(C12, X1, C12); nmod_mat_add(C21, C12, C21); nmod_mat_add(C12, C12, C22); nmod_mat_add(C22, C21, C22); nmod_mat_add(C12, C12, C11); nmod_mat_sub(X2, X2, B21); nmod_mat_mul(C11, A22, X2); nmod_mat_clear(X2); nmod_mat_sub(C21, C21, C11); nmod_mat_mul(C11, A12, B21); nmod_mat_add(C11, X1, C11); 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); } } flint2-2.8.4/nmod_mat/neg.c000066400000000000000000000012541414523752600154510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.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); } flint2-2.8.4/nmod_mat/nmod_vec_mul.c000066400000000000000000000016621414523752600173520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mat/nmod_vec_mul_ptr.c000066400000000000000000000016411414523752600202340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mat.h" 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; } flint2-2.8.4/nmod_mat/nullspace.c000066400000000000000000000035161414523752600166710ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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; } flint2-2.8.4/nmod_mat/one.c000066400000000000000000000014231414523752600154570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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; } flint2-2.8.4/nmod_mat/pow.c000066400000000000000000000034011414523752600155010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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); } } flint2-2.8.4/nmod_mat/print_pretty.c000066400000000000000000000021671414523752600174470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.h" #include "ulong_extras.h" void nmod_mat_print_pretty(const nmod_mat_t mat) { slong i, j; int width; char fmt[FLINT_BITS + 5]; flint_printf("<%wd x %wd integer matrix mod %wu>\n", mat->r, mat->c, mat->mod.n); if (!(mat->c) || !(mat->r)) return; width = n_sizeinbase(mat->mod.n, 10); flint_sprintf(fmt, "%%%dwu", width); for (i = 0; i < mat->r; i++) { flint_printf("["); for (j = 0; j < mat->c; j++) { flint_printf(fmt, mat->rows[i][j]); if (j + 1 < mat->c) flint_printf(" "); } flint_printf("]\n"); } } flint2-2.8.4/nmod_mat/profile/000077500000000000000000000000001414523752600161725ustar00rootroot00000000000000flint2-2.8.4/nmod_mat/profile/p-mul.c000066400000000000000000000077511414523752600174020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "thread_support.h" #include "cblas.h" 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; openblas_set_num_threads(blas_num); 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; } flint2-2.8.4/nmod_mat/randfull.c000066400000000000000000000012311414523752600165020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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)); } } flint2-2.8.4/nmod_mat/randops.c000066400000000000000000000033031414523752600163430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_vec.h" void nmod_mat_randops(nmod_mat_t mat, slong count, flint_rand_t state) { 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); } } } flint2-2.8.4/nmod_mat/randpermdiag.c000066400000000000000000000020001414523752600173230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "ulong_extras.h" #include "nmod_mat.h" #include "nmod_vec.h" #include "perm.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; } flint2-2.8.4/nmod_mat/randrank.c000066400000000000000000000021101414523752600164700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #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_printf("Exception (nmod_mat_randrank). Impossible rank.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_mat/randtest.c000066400000000000000000000011271414523752600165230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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); } flint2-2.8.4/nmod_mat/randtril.c000066400000000000000000000021701414523752600165150ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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); } } } } flint2-2.8.4/nmod_mat/randtriu.c000066400000000000000000000021701414523752600165260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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); } } } } flint2-2.8.4/nmod_mat/rank.c000066400000000000000000000015261414523752600156350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #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; } flint2-2.8.4/nmod_mat/reduce_row.c000066400000000000000000000071541414523752600170430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.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; } flint2-2.8.4/nmod_mat/rref.c000066400000000000000000000066741414523752600156510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "perm.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; } flint2-2.8.4/nmod_mat/scalar_addmul_ui.c000066400000000000000000000020611414523752600201650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.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); } } } flint2-2.8.4/nmod_mat/scalar_mul.c000066400000000000000000000025601414523752600170230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.h" #include "ulong_extras.h" 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); } } flint2-2.8.4/nmod_mat/set.c000066400000000000000000000012561414523752600154750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.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); } flint2-2.8.4/nmod_mat/similarity.c000066400000000000000000000020651414523752600170670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.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); } } flint2-2.8.4/nmod_mat/solve.c000066400000000000000000000024471414523752600160350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #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; } flint2-2.8.4/nmod_mat/solve_tril.c000066400000000000000000000015311414523752600170600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.h" 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); } } flint2-2.8.4/nmod_mat/solve_tril_classical.c000066400000000000000000000031131414523752600210740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.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); } flint2-2.8.4/nmod_mat/solve_tril_recursive.c000066400000000000000000000032361414523752600211530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.h" 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); } flint2-2.8.4/nmod_mat/solve_triu.c000066400000000000000000000015311414523752600170710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.h" 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); } } flint2-2.8.4/nmod_mat/solve_triu_classical.c000066400000000000000000000032061414523752600211100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.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); } flint2-2.8.4/nmod_mat/solve_triu_recursive.c000066400000000000000000000031411414523752600211570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.h" 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); } flint2-2.8.4/nmod_mat/solve_vec.c000066400000000000000000000021271414523752600166650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #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; } flint2-2.8.4/nmod_mat/strong_echelon_form.c000066400000000000000000000142121414523752600207320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.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 wether 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); } flint2-2.8.4/nmod_mat/sub.c000066400000000000000000000013301414523752600154640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.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); } } flint2-2.8.4/nmod_mat/submul.c000066400000000000000000000021351414523752600162060ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.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); } } flint2-2.8.4/nmod_mat/swap.c000066400000000000000000000011221414523752600156440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" void nmod_mat_swap(nmod_mat_t mat1, nmod_mat_t mat2) { nmod_mat_t temp; *temp = *mat1; *mat1 = *mat2; *mat2 = *temp; } flint2-2.8.4/nmod_mat/test/000077500000000000000000000000001414523752600155115ustar00rootroot00000000000000flint2-2.8.4/nmod_mat/test/t-add.c000066400000000000000000000026731414523752600166560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, mod, rep; FLINT_TEST_INIT(state); flint_printf("add/sub...."); fflush(stdout); 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)) { flint_printf("FAIL\n"); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-addmul.c000066400000000000000000000046521414523752600173730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("addmul...."); fflush(stdout); 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)) { flint_printf("FAIL: results not equal\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); nmod_mat_print_pretty(C); nmod_mat_print_pretty(D); nmod_mat_print_pretty(E); abort(); } /* Check aliasing */ nmod_mat_addmul(C, C, A, B); if (!nmod_mat_equal(C, E)) { flint_printf("FAIL: results not equal (aliasing)\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); nmod_mat_print_pretty(C); nmod_mat_print_pretty(D); nmod_mat_print_pretty(E); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); nmod_mat_clear(E); nmod_mat_clear(T); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-can_solve.c000066400000000000000000000065621414523752600201000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { nmod_mat_t A, X, X2, B, AX; slong i, k, m, n; mp_limb_t mod; int solved; FLINT_TEST_INIT(state); flint_printf("solve...."); fflush(stdout); /* 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, 1+n_randint(state, 1+m*m), state); solved = nmod_mat_can_solve(X, A, B); nmod_mat_mul(AX, A, X); if (solved && !nmod_mat_equal(AX, B)) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("B:\n"); nmod_mat_print_pretty(B); flint_printf("X:\n"); nmod_mat_print_pretty(X); flint_printf("AX:\n"); nmod_mat_print_pretty(AX); flint_printf("\n"); abort(); } 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)) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("B:\n"); nmod_mat_print_pretty(B); flint_printf("X:\n"); nmod_mat_print_pretty(X); flint_printf("AX:\n"); nmod_mat_print_pretty(AX); flint_printf("\n"); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(X2); nmod_mat_clear(AX); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-charpoly.c000066400000000000000000000061161414523752600177430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep, i; ulong mod; FLINT_TEST_INIT(state); flint_printf("charpoly...."); fflush(stdout); 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)) { flint_printf("FAIL: charpoly(AB) != charpoly(BA).\n"); flint_printf("Matrix A:\n"), nmod_mat_print_pretty(A), flint_printf("\n"); flint_printf("Matrix B:\n"), nmod_mat_print_pretty(B), flint_printf("\n"); flint_printf("cp(AB) = "), nmod_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(BA) = "), nmod_poly_print_pretty(g, "X"), flint_printf("\n"); abort(); } 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)) { flint_printf("FAIL: charpoly(P^{-1}AP) != charpoly(A).\n"); flint_printf("Matrix A:\n"), nmod_mat_print_pretty(A), flint_printf("\n"); flint_printf("cp(A) = "), nmod_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(P^{-1}AP) = "), nmod_poly_print_pretty(g, "X"), flint_printf("\n"); abort(); } nmod_mat_clear(A); nmod_poly_clear(f); nmod_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-charpoly_berkowitz.c000066400000000000000000000061541414523752600220450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep, i; ulong mod; FLINT_TEST_INIT(state); flint_printf("charpoly...."); fflush(stdout); 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)) { flint_printf("FAIL: charpoly(AB) != charpoly(BA).\n"); flint_printf("Matrix A:\n"), nmod_mat_print_pretty(A), flint_printf("\n"); flint_printf("Matrix B:\n"), nmod_mat_print_pretty(B), flint_printf("\n"); flint_printf("cp(AB) = "), nmod_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(BA) = "), nmod_poly_print_pretty(g, "X"), flint_printf("\n"); abort(); } 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)) { flint_printf("FAIL: charpoly(P^{-1}AP) != charpoly(A).\n"); flint_printf("Matrix A:\n"), nmod_mat_print_pretty(A), flint_printf("\n"); flint_printf("cp(A) = "), nmod_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(P^{-1}AP) = "), nmod_poly_print_pretty(g, "X"), flint_printf("\n"); abort(); } nmod_mat_clear(A); nmod_poly_clear(f); nmod_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-charpoly_danilevsky.c000066400000000000000000000061661414523752600222010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep, i; ulong mod; FLINT_TEST_INIT(state); flint_printf("charpoly_danilevsky...."); fflush(stdout); 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)) { flint_printf("FAIL: charpoly(AB) != charpoly(BA).\n"); flint_printf("Matrix A:\n"), nmod_mat_print_pretty(A), flint_printf("\n"); flint_printf("Matrix B:\n"), nmod_mat_print_pretty(B), flint_printf("\n"); flint_printf("cp(AB) = "), nmod_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(BA) = "), nmod_poly_print_pretty(g, "X"), flint_printf("\n"); abort(); } 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)) { flint_printf("FAIL: charpoly(P^{-1}AP) != charpoly(A).\n"); flint_printf("Matrix A:\n"), nmod_mat_print_pretty(A), flint_printf("\n"); flint_printf("cp(A) = "), nmod_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(P^{-1}AP) = "), nmod_poly_print_pretty(g, "X"), flint_printf("\n"); abort(); } nmod_mat_clear(A); nmod_poly_clear(f); nmod_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-concat_horizontal.c000066400000000000000000000037551414523752600216500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { nmod_mat_t A, B, C; nmod_mat_t window1, window2; slong i; FLINT_TEST_INIT(state); flint_printf("concat_horizontal...."); fflush(stdout); 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))) { flint_printf("A = \n"); nmod_mat_print_pretty(A); flint_printf("B = \n"); nmod_mat_print_pretty(B); flint_printf("A concat_horizontal B = \n"); nmod_mat_print_pretty(C); flint_printf("FAIL: results not equal\n"); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_window_clear(window1); nmod_mat_window_clear(window2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-concat_vertical.c000066400000000000000000000037371414523752600212700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { nmod_mat_t A, B, C; nmod_mat_t window1, window2; slong i; FLINT_TEST_INIT(state); flint_printf("concat_vertical...."); fflush(stdout); 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))) { flint_printf("A = \n"); nmod_mat_print_pretty(A); flint_printf("B = \n"); nmod_mat_print_pretty(B); flint_printf("A concat_vertical B = \n"); nmod_mat_print_pretty(C); flint_printf("FAIL: results not equal\n"); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_window_clear(window1); nmod_mat_window_clear(window2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-det.c000066400000000000000000000040401414523752600166700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong m, mod, rep; FLINT_TEST_INIT(state); flint_printf("det...."); fflush(stdout); 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, n_randint(state, 2*m + 1), state); break; case 1: t = n_randint(state, m); t = FLINT_MIN(t, m); nmod_mat_randrank(A, state, t); nmod_mat_randops(A, n_randint(state, 2*m + 1), state); 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)) { flint_printf("FAIL\n"); flint_printf("Adet = %wu, Bdet = %wu\n", Adet, fmpz_get_ui(Bdet)); abort(); } nmod_mat_clear(A); fmpz_mat_clear(B); fmpz_clear(Bdet); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-det_howell.c000066400000000000000000000040401414523752600202420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_mat.h" int main(void) { slong m, mod, rep; FLINT_TEST_INIT(state); flint_printf("det_howell...."); fflush(stdout); 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, n_randint(state, 2*m + 1), state); break; case 1: t = n_randint(state, m); t = FLINT_MIN(t, m); nmod_mat_randrank(A, state, t); nmod_mat_randops(A, n_randint(state, 2*m + 1), state); 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)) { flint_printf("FAIL\n"); flint_printf("Adet = %wu, Bdet = %wu\n", Adet, fmpz_get_ui(Bdet)); abort(); } nmod_mat_clear(A); fmpz_mat_clear(B); fmpz_clear(Bdet); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-howell_form.c000066400000000000000000000143651414523752600204440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "perm.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; } int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("howell_form...."); 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)) { flint_printf("FAIL (malformed Howell form)\n"); nmod_mat_print_pretty(A); flint_printf("\n\n"); nmod_mat_print_pretty(B); flint_printf("\n\n"); 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++) { 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) { flint_printf("FAIL (r1 = %wd, r2 = %wd)!\n", r1, r2); nmod_mat_print_pretty(A); flint_printf("\n\n"); nmod_mat_print_pretty(B); flint_printf("\n\n"); nmod_mat_print_pretty(D); flint_printf("\n\n"); abort(); } _perm_clear(perm); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-init_clear.c000066400000000000000000000026331414523752600202330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, mod, i, j, rep; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); 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)) { flint_printf("FAIL: entries not zero!\n"); abort(); } } } if (A->mod.n != mod) { flint_printf("FAIL: bad modulus\n"); abort(); } nmod_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-inv.c000066400000000000000000000062751414523752600167240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { nmod_mat_t A, B, C, I; slong i, j, m, r; mp_limb_t mod; int result; FLINT_TEST_INIT(state); flint_printf("inv...."); fflush(stdout); 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, 1+n_randint(state, 1+m*m), state); result = nmod_mat_inv(B, A); nmod_mat_mul(C, A, B); if (!nmod_mat_equal(C, I) || !result) { flint_printf("FAIL:\n"); flint_printf("A * A^-1 != I!\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("A^-1:\n"); nmod_mat_print_pretty(B); flint_printf("A * A^-1:\n"); nmod_mat_print_pretty(C); flint_printf("\n"); abort(); } /* Test aliasing */ nmod_mat_set(C, A); nmod_mat_inv(A, A); nmod_mat_mul(B, A, C); if (!nmod_mat_equal(B, I)) { flint_printf("FAIL:\n"); flint_printf("aliasing failed!\n"); nmod_mat_print_pretty(C); abort(); } 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, 1+n_randint(state, 1+m*m), state); result = nmod_mat_inv(B, A); if (result) { flint_printf("FAIL:\n"); flint_printf("singular matrix reported as invertible\n"); abort(); } /* Aliasing */ result = nmod_mat_inv(A, A); if (result) { flint_printf("FAIL:\n"); flint_printf("singular matrix reported as invertible\n"); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-invert_rows_cols.c000066400000000000000000000033011414523752600215140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, mod, rep; FLINT_TEST_INIT(state); flint_printf("invert_rows/cols...."); fflush(stdout); 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_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)) { flint_printf("FAIL: B != A\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("B:\n"); nmod_mat_print_pretty(B); abort(); } } } nmod_mat_clear(A); nmod_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-lu_classical.c000066400000000000000000000066621414523752600205660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" 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); } void 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) { flint_printf("FAIL: wrong shape!\n"); abort(); } } } 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)) { flint_printf("FAIL\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("LU:\n"); nmod_mat_print_pretty(LU); flint_printf("B:\n"); nmod_mat_print_pretty(B); abort(); } nmod_mat_clear(B); nmod_mat_clear(L); nmod_mat_clear(U); } int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("lu_classical...."); fflush(stdout); 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, d, state); } nmod_mat_init_set(LU, A); P = flint_malloc(sizeof(slong) * m); rank = nmod_mat_lu_classical(P, LU, 0); if (r != rank) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); flint_printf("A:"); nmod_mat_print_pretty(A); flint_printf("LU:"); nmod_mat_print_pretty(LU); abort(); } check(P, LU, A, rank); nmod_mat_clear(A); nmod_mat_clear(LU); flint_free(P); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-lu_recursive.c000066400000000000000000000066621414523752600206370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" 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); } void 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) { flint_printf("FAIL: wrong shape!\n"); abort(); } } } 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)) { flint_printf("FAIL\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("LU:\n"); nmod_mat_print_pretty(LU); flint_printf("B:\n"); nmod_mat_print_pretty(B); abort(); } nmod_mat_clear(B); nmod_mat_clear(L); nmod_mat_clear(U); } int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("lu_recursive...."); fflush(stdout); 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, d, state); } nmod_mat_init_set(LU, A); P = flint_malloc(sizeof(slong) * m); rank = nmod_mat_lu_recursive(P, LU, 0); if (r != rank) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); flint_printf("A:"); nmod_mat_print_pretty(A); flint_printf("LU:"); nmod_mat_print_pretty(LU); abort(); } check(P, LU, A, rank); nmod_mat_clear(A); nmod_mat_clear(LU); flint_free(P); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-minpoly.c000066400000000000000000000062511414523752600176110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, rep, i, j; ulong mod; FLINT_TEST_INIT(state); flint_printf("minpoly...."); fflush(stdout); 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)) { flint_printf("FAIL: minpoly(A) does not divide charpoly(BA).\n"); flint_printf("Matrix A:\n"), nmod_mat_print_pretty(A), flint_printf("\n"); flint_printf("mp(A) = "), nmod_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("cp(A) = "), nmod_poly_print_pretty(g, "X"), flint_printf("\n"); abort(); } 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)) { flint_printf("FAIL: minpoly(P^{-1}AP) != minpoly(A).\n"); flint_printf("Matrix A:\n"), nmod_mat_print_pretty(A), flint_printf("\n"); flint_printf("mp(A) = "), nmod_poly_print_pretty(f, "X"), flint_printf("\n"); flint_printf("mp(P^{-1}AP) = "), nmod_poly_print_pretty(g, "X"), flint_printf("\n"); abort(); } nmod_mat_clear(A); nmod_poly_clear(f); nmod_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-mul.c000066400000000000000000000077301414523752600167220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" 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; } } } int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); 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)) { flint_printf("FAIL: results not equal\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); nmod_mat_print_pretty(C); nmod_mat_print_pretty(D); abort(); } if (n == k) { nmod_mat_mul(A, A, B); if (!nmod_mat_equal(A, C)) { flint_printf("FAIL: aliasing failed\n"); flint_abort(); } } 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)) { flint_printf("FAIL: window aliasing failed\n"); nmod_mat_print_pretty(A); flint_printf("\n\n"); nmod_mat_print_pretty(B); flint_printf("\n\n"); flint_abort(); } nmod_mat_window_clear(A_window); nmod_mat_clear(A); nmod_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-mul_blas.c000066400000000000000000000057711414523752600177260ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.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); } } int main(void) { slong i, max_threads = 5; FLINT_TEST_INIT(state); flint_printf("mul_blas...."); fflush(stdout); 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)) { flint_printf("FAIL: results not equal\n"); flint_printf("m: %wd, k: %wd, n: %wd, mod: %wu\n", m, k, n, modulus); flint_abort(); } } #if FLINT_USES_BLAS && FLINT_BITS == 64 else { flint_printf("FAIL: blas should have worked\n"); flint_abort(); } #endif nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-mul_classical_threaded.c000066400000000000000000000065501414523752600225770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "thread_support.h" 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; } } } int main(void) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) slong i, max_threads = 5; #endif FLINT_TEST_INIT(state); flint_printf("mul_classical_threaded...."); fflush(stdout); #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) 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)) { flint_printf("FAIL: results not equal\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); nmod_mat_print_pretty(C); nmod_mat_print_pretty(D); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); #else FLINT_TEST_CLEANUP(state); flint_printf("SKIPPED\n"); #endif return 0; } flint2-2.8.4/nmod_mat/test/t-mul_nmod_vec.c000066400000000000000000000050701414523752600205670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mul_nmod_vec...."); fflush(stdout); 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]) { flint_printf("FAIL: wrong answer\n"); flint_abort(); } } 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-mul_strassen.c000066400000000000000000000032601414523752600206360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mul_strassen...."); fflush(stdout); 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)) { flint_printf("FAIL: results not equal\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); nmod_mat_print_pretty(C); nmod_mat_print_pretty(D); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-neg.c000066400000000000000000000031761414523752600166760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, mod, rep; FLINT_TEST_INIT(state); flint_printf("neg...."); fflush(stdout); 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)) { flint_printf("FAIL\n"); abort(); } nmod_mat_neg(C, B); nmod_mat_neg(B, B); if (!nmod_mat_equal(C, B)) { flint_printf("FAIL\n"); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-nmod_vec_mul.c000066400000000000000000000050711414523752600205700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("nmod_vec_mul...."); fflush(stdout); 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]) { flint_printf("FAIL: wrong answer\n"); flint_abort(); } } 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-nullspace.c000066400000000000000000000045701414523752600201120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("nullspace...."); fflush(stdout); 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, d, state); nullity = nmod_mat_nullspace(ker, A); nulrank = nmod_mat_rank(ker); if (nullity != nulrank) { flint_printf("FAIL:\n"); flint_printf("rank(ker) != nullity!\n"); nmod_mat_print_pretty(A); flint_printf("\n"); abort(); } if (nullity + r != n) { flint_printf("FAIL:\n"); flint_printf("nullity + rank != n\n"); nmod_mat_print_pretty(A); flint_printf("\n"); abort(); } nmod_mat_mul(B, A, ker); if (nmod_mat_rank(B) != 0) { flint_printf("FAIL:\n"); flint_printf("A * ker != 0\n"); nmod_mat_print_pretty(A); flint_printf("\n"); abort(); } nmod_mat_clear(A); nmod_mat_clear(ker); nmod_mat_clear(B); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-pow.c000066400000000000000000000033611414523752600167260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main() { slong i; FLINT_TEST_INIT(state); flint_printf("pow...."); fflush(stdout); 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))) { flint_printf("FAIL: results not equal\n");fflush(stdout); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); nmod_mat_print_pretty(C); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-rank.c000066400000000000000000000042441414523752600170550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { nmod_mat_t A; slong i, m, n, d, r; mp_limb_t mod; FLINT_TEST_INIT(state); flint_printf("rank...."); fflush(stdout); /* 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)) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); abort(); } 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, d, state); /* flint_printf("DENSE %wd %wd\n", r, d); nmod_mat_print_pretty(A); */ if (r != nmod_mat_rank(A)) { flint_printf("FAIL:\n"); flint_printf("wrong rank!\n"); abort(); } nmod_mat_clear(A); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-rref.c000066400000000000000000000100101414523752600170440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "perm.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; } int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("rref...."); fflush(stdout); 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)) { flint_printf("FAIL (malformed rref)\n"); nmod_mat_print_pretty(A); flint_printf("\n\n"); nmod_mat_print_pretty(B); flint_printf("\n\n"); 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++) { 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) { flint_printf("FAIL (rank1 = %wd, rank2 = %wd)!\n", rank1, rank2); nmod_mat_print_pretty(A); flint_printf("\n\n"); nmod_mat_print_pretty(B); flint_printf("\n\n"); nmod_mat_print_pretty(D); flint_printf("\n\n"); abort(); } _perm_clear(perm); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-scalar_addmul_ui.c000066400000000000000000000031371414523752600214120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_mat.h" int main(void) { slong m, n, mod, rep; mp_limb_t x; FLINT_TEST_INIT(state); flint_printf("scalar_addmul_ui...."); fflush(stdout); 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)) { flint_printf("FAIL\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); nmod_mat_print_pretty(C); nmod_mat_print_pretty(D); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-scalar_mul.c000066400000000000000000000035151414523752600202440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.h" #include "ulong_extras.h" int main(void) { slong m, n, mod, rep; FLINT_TEST_INIT(state); flint_printf("scalar_mul...."); fflush(stdout); 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)) { flint_printf("FAIL\n"); abort(); } /* Aliasing */ nmod_mat_scalar_mul(C, A, c); nmod_mat_scalar_mul(A, A, c); if (!nmod_mat_equal(A, C)) { flint_printf("FAIL\n"); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-solve.c000066400000000000000000000057271414523752600172610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { nmod_mat_t A, X, B, AX; slong i, m, n, r; mp_limb_t mod; int solved; FLINT_TEST_INIT(state); flint_printf("solve...."); fflush(stdout); 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, 1+n_randint(state, 1+m*m), state); solved = nmod_mat_solve(X, A, B); nmod_mat_mul(AX, A, X); if (!nmod_mat_equal(AX, B) || !solved) { flint_printf("FAIL:\n"); flint_printf("AX != B!\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("B:\n"); nmod_mat_print_pretty(B); flint_printf("X:\n"); nmod_mat_print_pretty(X); flint_printf("AX:\n"); nmod_mat_print_pretty(AX); flint_printf("\n"); abort(); } 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, 1+n_randint(state, 1+m*m), state); solved = nmod_mat_solve(X, A, B); if (solved) { flint_printf("FAIL:\n"); flint_printf("singular system was 'solved'\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(X); nmod_mat_print_pretty(B); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(AX); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-solve_tril.c000066400000000000000000000044061414523752600203040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("solve_tril...."); fflush(stdout); 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)) { flint_printf("FAIL!\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("X:\n"); nmod_mat_print_pretty(X); flint_printf("B:\n"); nmod_mat_print_pretty(B); flint_printf("Y:\n"); nmod_mat_print_pretty(Y); abort(); } /* Check aliasing */ nmod_mat_solve_tril(B, A, B, unit); if (!nmod_mat_equal(B, X)) { flint_printf("FAIL!\n"); flint_printf("aliasing test failed"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("B:\n"); nmod_mat_print_pretty(B); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-solve_tril_classical.c000066400000000000000000000044451414523752600223250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("solve_tril_classical...."); fflush(stdout); 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)) { flint_printf("FAIL!\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("X:\n"); nmod_mat_print_pretty(X); flint_printf("B:\n"); nmod_mat_print_pretty(B); flint_printf("Y:\n"); nmod_mat_print_pretty(Y); abort(); } /* Check aliasing */ nmod_mat_solve_tril_classical(B, A, B, unit); if (!nmod_mat_equal(B, X)) { flint_printf("FAIL!\n"); flint_printf("aliasing test failed"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("B:\n"); nmod_mat_print_pretty(B); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-solve_tril_recursive.c000066400000000000000000000044451414523752600223760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("solve_tril_recursive...."); fflush(stdout); 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)) { flint_printf("FAIL!\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("X:\n"); nmod_mat_print_pretty(X); flint_printf("B:\n"); nmod_mat_print_pretty(B); flint_printf("Y:\n"); nmod_mat_print_pretty(Y); abort(); } /* Check aliasing */ nmod_mat_solve_tril_recursive(B, A, B, unit); if (!nmod_mat_equal(B, X)) { flint_printf("FAIL!\n"); flint_printf("aliasing test failed"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("B:\n"); nmod_mat_print_pretty(B); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-solve_triu.c000066400000000000000000000044061414523752600203150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("solve_triu...."); fflush(stdout); 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)) { flint_printf("FAIL!\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("X:\n"); nmod_mat_print_pretty(X); flint_printf("B:\n"); nmod_mat_print_pretty(B); flint_printf("Y:\n"); nmod_mat_print_pretty(Y); abort(); } /* Check aliasing */ nmod_mat_solve_triu(B, A, B, unit); if (!nmod_mat_equal(B, X)) { flint_printf("FAIL!\n"); flint_printf("aliasing test failed"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("B:\n"); nmod_mat_print_pretty(B); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-solve_triu_classical.c000066400000000000000000000044451414523752600223360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("solve_triu_classical...."); fflush(stdout); 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)) { flint_printf("FAIL!\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("X:\n"); nmod_mat_print_pretty(X); flint_printf("B:\n"); nmod_mat_print_pretty(B); flint_printf("Y:\n"); nmod_mat_print_pretty(Y); abort(); } /* Check aliasing */ nmod_mat_solve_triu_classical(B, A, B, unit); if (!nmod_mat_equal(B, X)) { flint_printf("FAIL!\n"); flint_printf("aliasing test failed"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("B:\n"); nmod_mat_print_pretty(B); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-solve_triu_recursive.c000066400000000000000000000044451414523752600224070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("solve_triu_recursive...."); fflush(stdout); 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)) { flint_printf("FAIL!\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("X:\n"); nmod_mat_print_pretty(X); flint_printf("B:\n"); nmod_mat_print_pretty(B); flint_printf("Y:\n"); nmod_mat_print_pretty(Y); abort(); } /* Check aliasing */ nmod_mat_solve_triu_recursive(B, A, B, unit); if (!nmod_mat_equal(B, X)) { flint_printf("FAIL!\n"); flint_printf("aliasing test failed"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("B:\n"); nmod_mat_print_pretty(B); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(X); nmod_mat_clear(Y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-solve_vec.c000066400000000000000000000055111414523752600201050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { nmod_mat_t A, x, b, Ax; slong i, m, r; int solved; mp_limb_t mod; FLINT_TEST_INIT(state); flint_printf("solve_vec...."); fflush(stdout); 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, 1+n_randint(state, 1+m*m), state); solved = nmod_mat_solve_vec(x->entries, A, b->entries); nmod_mat_mul(Ax, A, x); if (!nmod_mat_equal(Ax, b) || !solved) { flint_printf("FAIL:\n"); flint_printf("Ax != b!\n"); flint_printf("A:\n"); nmod_mat_print_pretty(A); flint_printf("b:\n"); nmod_mat_print_pretty(b); flint_printf("x:\n"); nmod_mat_print_pretty(x); flint_printf("Ax:\n"); nmod_mat_print_pretty(Ax); flint_printf("\n"); abort(); } 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, 1+n_randint(state, 1+m*m), state); solved = nmod_mat_solve_vec(x->entries, A, b->entries); if (solved) { flint_printf("FAIL:\n"); flint_printf("singular system was 'solved'\n"); abort(); } nmod_mat_clear(A); nmod_mat_clear(b); nmod_mat_clear(x); nmod_mat_clear(Ax); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-submul.c000066400000000000000000000046521414523752600174340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("submul...."); fflush(stdout); 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)) { flint_printf("FAIL: results not equal\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); nmod_mat_print_pretty(C); nmod_mat_print_pretty(D); nmod_mat_print_pretty(E); abort(); } /* Check aliasing */ nmod_mat_submul(C, C, A, B); if (!nmod_mat_equal(C, E)) { flint_printf("FAIL: results not equal (aliasing)\n"); nmod_mat_print_pretty(A); nmod_mat_print_pretty(B); nmod_mat_print_pretty(C); nmod_mat_print_pretty(D); nmod_mat_print_pretty(E); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); nmod_mat_clear(E); nmod_mat_clear(T); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-trace.c000066400000000000000000000036011414523752600172140ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("trace...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); nmod_mat_print_pretty(A), flint_printf("\n"); nmod_mat_print_pretty(B), flint_printf("\n"); nmod_mat_print_pretty(AB), flint_printf("\n"); nmod_mat_print_pretty(BA), flint_printf("\n"); flint_printf("tr(AB): %wu\n", trab); flint_printf("tr(BA): %wu\n", trba); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(AB); nmod_mat_clear(BA); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-transpose.c000066400000000000000000000056731414523752600201470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { slong m, n, mod, mod2, rep; FLINT_TEST_INIT(state); flint_printf("transpose...."); fflush(stdout); /* 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)) { flint_printf("FAIL: C != A\n"); abort(); } 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)) { flint_printf("FAIL: AT != BT\n"); abort(); } 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)) { flint_printf("FAIL: B != A\n"); abort(); } nmod_mat_clear(A); nmod_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/test/t-window_init_clear.c000066400000000000000000000027471414523752600216300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("window_init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mat/trace.c000066400000000000000000000014011414523752600157700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.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; } flint2-2.8.4/nmod_mat/transpose.c000066400000000000000000000023231414523752600167140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.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_printf("Exception (nmod_mat_transpose). Incompatible dimensions.\n"); flint_abort(); } 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]; } } flint2-2.8.4/nmod_mat/window_clear.c000066400000000000000000000012731414523752600173560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" void nmod_mat_window_clear(nmod_mat_t window) { if (window->r > 0) flint_free(window->rows); } flint2-2.8.4/nmod_mat/window_init.c000066400000000000000000000022401414523752600172260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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; } flint2-2.8.4/nmod_mat/zero.c000066400000000000000000000012501414523752600156530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_vec.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); } flint2-2.8.4/nmod_matxx.h000066400000000000000000000436621414523752600152760ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef NMOD_MATXX_H #define NMOD_MATXX_H #include #include #include "nmod_mat.h" #include "nmod_vecxx.h" #include "fmpz_matxx.h" // for modular reduction #include "permxx.h" #include "flintxx/flint_exception.h" #include "flintxx/ltuple.h" #include "flintxx/matrix.h" // TODO addmul // TODO default argument for mat_solve_triu etc? // TODO nullspace member // TODO unnecessary perm copies in set_lu* namespace flint { FLINT_DEFINE_BINOP(solve_vec) FLINT_DEFINE_BINOP(mul_strassen) FLINT_DEFINE_THREEARY(solve_tril) FLINT_DEFINE_THREEARY(solve_tril_classical) FLINT_DEFINE_THREEARY(solve_tril_recursive) FLINT_DEFINE_THREEARY(solve_triu) FLINT_DEFINE_THREEARY(solve_triu_classical) FLINT_DEFINE_THREEARY(solve_triu_recursive) FLINT_DEFINE_THREEARY(multi_CRT_precomp) namespace detail { template struct nmod_matxx_traits : matrices::generic_traits { }; } // detail template class nmod_matxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef detail::nmod_matxx_traits traits_t; FLINTXX_DEFINE_BASICS(nmod_matxx_expression) FLINTXX_DEFINE_CTORS(nmod_matxx_expression) FLINTXX_DEFINE_C_REF(nmod_matxx_expression, nmod_mat_struct, _mat) // These only make sense with immediates nmodxx_ctx_srcref _ctx() const {return nmodxx_ctx_srcref::make(_mat()->mod);} // These work on any expression without evaluation nmodxx_ctx_srcref estimate_ctx() const { return tools::find_nmodxx_ctx(*this); } mp_limb_t modulus() const {return estimate_ctx().n();} template static evaluated_t create_temporary_rowscols( const Expr& e, slong rows, slong cols) { return evaluated_t(rows, cols, tools::find_nmodxx_ctx(e).n()); } FLINTXX_DEFINE_MATRIX_METHODS(traits_t) template static nmod_matxx_expression reduce(const Fmpz_mat& mat, mp_limb_t modulus, typename mp::enable_if >::type* = 0) { nmod_matxx_expression res(mat.rows(), mat.cols(), modulus); fmpz_mat_get_nmod_mat(res._mat(), mat.evaluate()._mat()); return res; } static nmod_matxx_expression randtest(slong rows, slong cols, mp_limb_t n, frandxx& state) { nmod_matxx_expression res(rows, cols, n); res.set_randtest(state); return res; } static nmod_matxx_expression randfull(slong rows, slong cols, mp_limb_t n, frandxx& state) { nmod_matxx_expression res(rows, cols, n); res.set_randfull(state); return res; } static nmod_matxx_expression randrank(slong rows, slong cols, mp_limb_t n, frandxx& state, slong rank) { nmod_matxx_expression res(rows, cols, n); res.set_randrank(state, rank); return res; } static nmod_matxx_expression randtril(slong rows, slong cols, mp_limb_t n, frandxx& state, bool unit) { nmod_matxx_expression res(rows, cols, n); res.set_randtril(state, unit); return res; } static nmod_matxx_expression randtriu(slong rows, slong cols, mp_limb_t n, frandxx& state, bool unit) { nmod_matxx_expression res(rows, cols, n); res.set_randtriu(state, unit); return res; } template static nmod_matxx_expression randpermdiag(slong rows, slong cols, mp_limb_t n, frandxx& state, const Vec& v) { nmod_matxx_expression res(rows, cols, n); res.set_randpermdiag(state, v); return res; } static nmod_matxx_expression zero(slong rows, slong cols, mp_limb_t n) {return nmod_matxx_expression(rows, cols, n);} // these only make sense with targets void set_randtest(frandxx& state) {nmod_mat_randtest(_mat(), state._data());} void set_randfull(frandxx& state) {nmod_mat_randfull(_mat(), state._data());} void set_randrank(frandxx& state, slong rank) {nmod_mat_randrank(_mat(), state._data(), rank);} void set_randtril(frandxx& state, bool unit) {nmod_mat_randtril(_mat(), state._data(), unit);} void set_randtriu(frandxx& state, bool unit) {nmod_mat_randtriu(_mat(), state._data(), unit);} template int set_randpermdiag(frandxx& state, const Vec& v) { return nmod_mat_randpermdiag(_mat(), state._data(), v._array(), v.size()); } void apply_randops(frandxx& state, slong count) {nmod_mat_randops(_mat(), count, state._data());} slong set_rref() {return nmod_mat_rref(_mat());} void set_zero() {nmod_mat_zero(_mat());} typedef mp::make_tuple::type lu_rt; lu_rt set_lu(bool rank_check = false) { lu_rt res = mp::make_tuple::make(0, permxx(rows())); res.first() = nmod_mat_lu(res.second()._data(), _mat(), rank_check); return res; } lu_rt set_lu_classical(bool rank_check = false) { lu_rt res = mp::make_tuple::make(0, permxx(rows())); res.first() = nmod_mat_lu_classical( res.second()._data(), _mat(), rank_check); return res; } lu_rt set_lu_recursive(bool rank_check = false) { lu_rt res = mp::make_tuple::make(0, permxx(rows())); res.first() = nmod_mat_lu_recursive( res.second()._data(), _mat(), rank_check); return res; } // these cause evaluation slong rank() const {return nmod_mat_rank(this->evaluate()._mat());} bool is_zero() const {return nmod_mat_is_zero(this->evaluate()._mat());} bool is_empty() const {return nmod_mat_is_empty(this->evaluate()._mat());} bool is_square() const {return nmod_mat_is_square(this->evaluate()._mat());} // lazy members FLINTXX_DEFINE_MEMBER_BINOP(solve) FLINTXX_DEFINE_MEMBER_BINOP(mul_classical) FLINTXX_DEFINE_MEMBER_BINOP(mul_strassen) FLINTXX_DEFINE_MEMBER_UNOP(inv) FLINTXX_DEFINE_MEMBER_UNOP(transpose) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(nmodxx, trace) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(nmodxx, det) //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(???, nullspace) // TODO FLINTXX_DEFINE_MEMBER_3OP(solve_tril) FLINTXX_DEFINE_MEMBER_3OP(solve_tril_recursive) FLINTXX_DEFINE_MEMBER_3OP(solve_tril_classical) FLINTXX_DEFINE_MEMBER_3OP(solve_triu) FLINTXX_DEFINE_MEMBER_3OP(solve_triu_recursive) FLINTXX_DEFINE_MEMBER_3OP(solve_triu_classical) }; namespace detail { struct nmod_mat_data; } // detail typedef nmod_matxx_expression nmod_matxx; typedef nmod_matxx_expression > nmod_matxx_ref; typedef nmod_matxx_expression > nmod_matxx_srcref; template<> struct matrix_traits { template static slong rows(const M& m) { return nmod_mat_nrows(m._mat()); } template static slong cols(const M& m) { return nmod_mat_ncols(m._mat()); } template static nmodxx_srcref at(const M& m, slong i, slong j) { return nmodxx_srcref::make(nmod_mat_entry(m._mat(), i, j), m.estimate_ctx()); } template static nmodxx_ref at(M& m, slong i, slong j) { return nmodxx_ref::make(nmod_mat_entry(m._mat(), i, j), m.estimate_ctx()); } }; namespace traits { template<> struct has_nmodxx_ctx : mp::true_ { }; template<> struct has_nmodxx_ctx : mp::true_ { }; template<> struct has_nmodxx_ctx : mp::true_ { }; } // traits namespace detail { template<> struct nmod_matxx_traits : matrices::generic_traits_srcref { }; template<> struct nmod_matxx_traits : matrices::generic_traits_ref { }; template<> struct nmod_matxx_traits : matrices::generic_traits_nonref { }; struct nmod_mat_data { typedef nmod_mat_t& data_ref_t; typedef const nmod_mat_t& data_srcref_t; nmod_mat_t inner; nmod_mat_data(slong m, slong n, mp_limb_t modulus) { nmod_mat_init(inner, m, n, modulus); } nmod_mat_data(const nmod_mat_data& o) { nmod_mat_init_set(inner, o.inner); } nmod_mat_data(nmod_matxx_srcref o) { nmod_mat_init_set(inner, o._data().inner); } ~nmod_mat_data() {nmod_mat_clear(inner);} }; } // detail namespace matrices { template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; template<> struct outsize : outsize { }; } // temporary instantiation stuff FLINTXX_DEFINE_TEMPORARY_RULES(nmod_matxx) #define NMOD_MATXX_COND_S FLINTXX_COND_S(nmod_matxx) #define NMOD_MATXX_COND_T FLINTXX_COND_T(nmod_matxx) namespace traits { template struct is_nmod_matxx : flint_classes::is_Base { }; } // traits namespace rules { FLINT_DEFINE_DOIT_COND2(assignment, NMOD_MATXX_COND_T, NMOD_MATXX_COND_S, nmod_mat_set(to._mat(), from._mat())) FLINTXX_DEFINE_SWAP(nmod_matxx, nmod_mat_swap(e1._mat(), e2._mat())) FLINTXX_DEFINE_EQUALS(nmod_matxx, nmod_mat_equal(e1._mat(), e2._mat())) FLINT_DEFINE_PRINT_PRETTY_COND(NMOD_MATXX_COND_S, (nmod_mat_print_pretty(from._mat()), 1)) FLINT_DEFINE_THREEARY_EXPR_COND3(mat_at_op, nmodxx, NMOD_MATXX_COND_S, traits::fits_into_slong, traits::fits_into_slong, to.set_nored(nmod_mat_entry(e1._mat(), e2, e3))) FLINT_DEFINE_BINARY_EXPR_COND2(times, nmod_matxx, NMOD_MATXX_COND_S, NMOD_MATXX_COND_S, nmod_mat_mul(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, nmod_matxx, NMOD_MATXX_COND_S, NMODXX_COND_S, nmod_mat_scalar_mul(to._mat(), e1._mat(), e2._limb())) FLINT_DEFINE_BINARY_EXPR_COND2(plus, nmod_matxx, NMOD_MATXX_COND_S, NMOD_MATXX_COND_S, nmod_mat_add(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, nmod_matxx, NMOD_MATXX_COND_S, NMOD_MATXX_COND_S, nmod_mat_sub(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_UNARY_EXPR_COND(negate, nmod_matxx, NMOD_MATXX_COND_S, nmod_mat_neg(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(transpose_op, nmod_matxx, NMOD_MATXX_COND_S, nmod_mat_transpose(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(trace_op, nmodxx, NMOD_MATXX_COND_S, to.set_nored(nmod_mat_trace(from._mat()))) FLINT_DEFINE_BINARY_EXPR_COND2(mul_classical_op, nmod_matxx, NMOD_MATXX_COND_S, NMOD_MATXX_COND_S, nmod_mat_mul(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(mul_strassen_op, nmod_matxx, NMOD_MATXX_COND_S, NMOD_MATXX_COND_S, nmod_mat_mul(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_UNARY_EXPR_COND(det_op, nmodxx, NMOD_MATXX_COND_S, to.set_nored(nmod_mat_det(from._mat()))) FLINT_DEFINE_UNARY_EXPR_COND(inv_op, nmod_matxx, NMOD_MATXX_COND_S, execution_check(nmod_mat_inv(to._mat(), from._mat()), "inv", "nmod_mat")) #define NMOD_MATXX_DEFINE_SOLVE_TRI(name) \ FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, nmod_matxx, \ NMOD_MATXX_COND_S, NMOD_MATXX_COND_S, tools::is_bool, \ nmod_mat_##name(to._mat(), e1._mat(), e2._mat(), e3)) NMOD_MATXX_DEFINE_SOLVE_TRI(solve_tril) NMOD_MATXX_DEFINE_SOLVE_TRI(solve_tril_classical) NMOD_MATXX_DEFINE_SOLVE_TRI(solve_tril_recursive) NMOD_MATXX_DEFINE_SOLVE_TRI(solve_triu) NMOD_MATXX_DEFINE_SOLVE_TRI(solve_triu_classical) NMOD_MATXX_DEFINE_SOLVE_TRI(solve_triu_recursive) FLINT_DEFINE_BINARY_EXPR_COND2(solve_op, nmod_matxx, NMOD_MATXX_COND_S, NMOD_MATXX_COND_S, execution_check(nmod_mat_solve(to._mat(), e1._mat(), e2._mat()), "solve", "nmod_mat")) FLINT_DEFINE_BINARY_EXPR_COND2(solve_op, nmod_vecxx, NMOD_MATXX_COND_S, NMOD_VECXX_COND_S, execution_check(nmod_mat_solve_vec(to._array(), e1._mat(), e2._array()), "solve_vec", "nmod_mat")) namespace rdetail { typedef make_ltuple::type >::type nmod_mat_nullspace_rt; } // rdetail FLINT_DEFINE_UNARY_EXPR_COND(nullspace_op, rdetail::nmod_mat_nullspace_rt, NMOD_MATXX_COND_S, to.template get<0>() = nmod_mat_nullspace( to.template get<1>()._mat(), from._mat())) } // rules ////////////////////////////////////////////////////////////////////////////// // nmod_mat_vector class ////////////////////////////////////////////////////////////////////////////// // This class stores a vector of nmod_matxx with differing moduli. It is *not* // an expression template class! class nmod_mat_vector { private: nmod_mat_t* data; std::size_t size_; void init(const nmod_mat_vector& o) { size_ = o.size_; data = new nmod_mat_t[size_]; for(std::size_t i = 0;i < size_;++i) nmod_mat_init_set(data[i], o.data[i]); } void clear(void) { for(std::size_t i = 0;i < size_;++i) nmod_mat_clear(data[i]); delete[] data; } public: ~nmod_mat_vector() {clear();} nmod_mat_vector(slong rows, slong cols, const std::vector& primes) { size_ = primes.size(); data = new nmod_mat_t[primes.size()]; for(std::size_t i = 0;i < primes.size();++i) nmod_mat_init(data[i], rows, cols, primes[i]); } nmod_mat_vector(const nmod_mat_vector& o) { init(o); } nmod_mat_vector& operator=(const nmod_mat_vector& o) { clear(); init(o); return *this; } nmod_matxx_ref operator[](std::size_t idx) {return nmod_matxx_ref::make(data[idx]);} nmod_matxx_srcref operator[](std::size_t idx) const {return nmod_matxx_srcref::make(data[idx]);} std::size_t size() const {return size_;} const nmod_mat_t* _data() const {return data;} nmod_mat_t* _data() {return data;} bool operator==(const nmod_mat_vector& o) { if(size() != o.size()) return false; for(std::size_t i = 0;i < size();++i) if((*this)[i] != o[i]) return false; return true; } bool operator!=(const nmod_mat_vector& o) { return !(*this == o); } template void set_multi_mod(const Fmpz_mat& m, typename mp::enable_if >::type* = 0) { fmpz_mat_multi_mod_ui(data, size(), m.evaluate()._mat()); } template void set_multi_mod_precomp(const Fmpz_mat& m, const fmpz_combxx& comb, typename mp::enable_if >::type* = 0) { fmpz_mat_multi_mod_ui_precomp(data, size(), m.evaluate()._mat(), comb._comb(), comb._temp()); } }; ///////////////////////////////////////////////////////////////////////////// // chinese remaindering ///////////////////////////////////////////////////////////////////////////// // Note this operates on fmpz_matxx and fmpz_combxx (as well as nmod_matxx). // We define it here to deal with the circular dependencies. fmpz_matxx.h // includes nmod_matxx.h at the bottom. template inline nmod_mat_vector multi_mod(const Fmpz_mat& m, const std::vector& primes, typename mp::enable_if >::type* = 0) { nmod_mat_vector res(m.rows(), m.cols(), primes); res.set_multi_mod(m); return res; } template inline nmod_mat_vector multi_mod_precomp(const Fmpz_mat& m, const std::vector& primes, const fmpz_combxx& comb, typename mp::enable_if >::type* = 0) { nmod_mat_vector res(m.rows(), m.cols(), primes); res.set_multi_mod_precomp(m, comb); return res; } namespace matrices { // outsize computation for multi-CRT struct outsize_CRT { template static slong rows(const Mat& m) { return m._data().first()[0].rows(); } template static slong cols(const Mat& m) { return m._data().first()[0].cols(); } }; template<> struct outsize : outsize_CRT { }; template<> struct outsize : outsize_CRT { }; } namespace rules { FLINT_DEFINE_FOURARY_EXPR_COND4(CRT_op, fmpz_matxx, FMPZ_MATXX_COND_T, FMPZXX_COND_S, NMOD_MATXX_COND_S, tools::is_bool, fmpz_mat_CRT_ui(to._mat(), e1._mat(), e2._fmpz(), e3._mat(), e4)) FLINT_DEFINE_BINARY_EXPR2(multi_CRT_op, fmpz_matxx, nmod_mat_vector, bool, fmpz_mat_multi_CRT_ui(to._mat(), (nmod_mat_t * const) e1._data(), e1.size(), e2)) FLINT_DEFINE_THREEARY_EXPR(multi_CRT_precomp_op, fmpz_matxx, nmod_mat_vector, fmpz_combxx, bool, fmpz_mat_multi_CRT_ui_precomp(to._mat(), (nmod_mat_t * const) e1._data(), e1.size(), e2._comb(), e2._temp(), e3)) } // rules } // flint #endif flint2-2.8.4/nmod_mpoly.h000066400000000000000000002236321414523752600152720ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define NMOD_MPOLY_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_vec.h" #include "mpoly.h" #include "fq_nmod_poly.h" #include "thread_pool.h" #include "n_poly.h" #ifdef __cplusplus extern "C" { #endif /* Type definitions **********************************************************/ /* context object for nmod_mpoly */ typedef struct { mpoly_ctx_t minfo; nmod_t mod; } nmod_mpoly_ctx_struct; typedef nmod_mpoly_ctx_struct nmod_mpoly_ctx_t[1]; /* nmod_mpoly_t sparse multivariates with nmod coeffs */ 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]; NMOD_MPOLY_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 *************************************************/ NMOD_MPOLY_INLINE n_poly_struct * evil_cast_nmod_poly_to_n_poly(nmod_poly_struct * a) { return (n_poly_struct *) a; } NMOD_MPOLY_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_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]; /* nmod_mpolyd_t A dense mpoly is stored as a flat array of coeffcients. 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]; FLINT_DLL void nmod_poly_stack_init(nmod_poly_stack_t S, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_poly_stack_clear(nmod_poly_stack_t S); FLINT_DLL void nmod_poly_stack_set_ctx(nmod_poly_stack_t S, const nmod_mpoly_ctx_t ctx); FLINT_DLL n_poly_struct ** nmod_poly_stack_fit_request_poly( nmod_poly_stack_t S, slong k); FLINT_DLL nmod_mpolyun_struct ** nmod_poly_stack_fit_request_mpolyun( nmod_poly_stack_t S, slong k); FLINT_DLL nmod_mpolyn_struct ** nmod_poly_stack_fit_request_mpolyn( nmod_poly_stack_t S, slong k); NMOD_MPOLY_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; } NMOD_MPOLY_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]; } NMOD_MPOLY_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; } NMOD_MPOLY_INLINE slong nmod_poly_stack_size_poly(const nmod_poly_stack_t S) { return S->poly_top; } NMOD_MPOLY_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; } NMOD_MPOLY_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]; } NMOD_MPOLY_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; } NMOD_MPOLY_INLINE slong nmod_poly_stack_size_mpolyun(const nmod_poly_stack_t S) { return S->mpolyun_top; } NMOD_MPOLY_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; } NMOD_MPOLY_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]; } NMOD_MPOLY_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; } NMOD_MPOLY_INLINE slong nmod_poly_stack_size_mpolyn(const nmod_poly_stack_t S) { return S->mpolyn_top; } /* Context object ************************************************************/ FLINT_DLL void nmod_mpoly_ctx_init(nmod_mpoly_ctx_t ctx, slong nvars, const ordering_t ord, mp_limb_t modulus); FLINT_DLL void nmod_mpoly_ctx_init_rand(nmod_mpoly_ctx_t ctx, flint_rand_t state, slong max_nvars, mp_limb_t modulus); FLINT_DLL void nmod_mpoly_ctx_clear(nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE void nmod_mpoly_ctx_set_modulus(nmod_mpoly_ctx_t ctx, mp_limb_t p) { nmod_init(&ctx->mod, p); } 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; } NMOD_MPOLY_INLINE void nmod_mpoly_ctx_change_modulus(nmod_mpoly_ctx_t ctx, mp_limb_t modulus) { nmod_init(&ctx->mod, modulus); } /* 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); } FLINT_DLL void nmod_mpoly_init2(nmod_mpoly_t A, slong alloc, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_init3(nmod_mpoly_t A, slong alloc, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_realloc(nmod_mpoly_t A, slong alloc, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_fit_length(nmod_mpoly_t A, slong length, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_fit_length_fit_bits(nmod_mpoly_t A, slong len, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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 **************************************************************/ FLINT_DLL int nmod_mpoly_set_str_pretty(nmod_mpoly_t A, const char * str, const char ** x, const nmod_mpoly_ctx_t ctx); FLINT_DLL char * nmod_mpoly_get_str_pretty(const nmod_mpoly_t A, const char ** x, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_fprint_pretty(FILE * file, const nmod_mpoly_t A, const char ** x, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE 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); } /* Basic manipulation *******************************************************/ FLINT_DLL void nmod_mpoly_gen(nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_is_gen(const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_set(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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) { nmod_mpoly_struct t = *A; *A = *B; *B = t; } /* Constants *****************************************************************/ FLINT_DLL int nmod_mpoly_is_ui(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL ulong nmod_mpoly_get_ui(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_set_ui(nmod_mpoly_t A, ulong c, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); } FLINT_DLL 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 *******************************************************************/ NMOD_MPOLY_INLINE 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); } NMOD_MPOLY_INLINE 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); } NMOD_MPOLY_INLINE 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); } NMOD_MPOLY_INLINE void nmod_mpoly_degree_fmpz(fmpz_t deg, const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) { mpoly_degree_fmpz(deg, A->exps, A->length, A->bits, var, ctx->minfo); } NMOD_MPOLY_INLINE slong nmod_mpoly_degree_si(const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx) { return mpoly_degree_si(A->exps, A->length, A->bits, var, ctx->minfo); } NMOD_MPOLY_INLINE 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); } NMOD_MPOLY_INLINE 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); } NMOD_MPOLY_INLINE 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); } NMOD_MPOLY_INLINE 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); } /* Coefficients **************************************************************/ FLINT_DLL ulong nmod_mpoly_get_coeff_ui_monomial(const nmod_mpoly_t A, const nmod_mpoly_t M, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_set_coeff_ui_monomial(nmod_mpoly_t A, ulong c, const nmod_mpoly_t M, const nmod_mpoly_ctx_t ctx); FLINT_DLL ulong nmod_mpoly_get_coeff_ui_fmpz(const nmod_mpoly_t A, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL ulong nmod_mpoly_get_coeff_ui_ui(const nmod_mpoly_t A, const ulong * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL void _nmod_mpoly_set_coeff_ui_fmpz(nmod_mpoly_t A, ulong c, const fmpz * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_set_coeff_ui_fmpz(nmod_mpoly_t A, ulong c, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_set_coeff_ui_ui(nmod_mpoly_t A, ulong c, const ulong * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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 ****************************************************************/ FLINT_DLL int nmod_mpoly_is_nmod_poly(const nmod_mpoly_t A, slong var, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_get_n_poly(n_poly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_get_nmod_poly(nmod_poly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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_DLL void nmod_mpoly_set_nmod_poly(nmod_mpoly_t A, const nmod_poly_t B, slong var, const nmod_mpoly_ctx_t ctx); /* comparison ****************************************************************/ FLINT_DLL int nmod_mpoly_cmp(const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); /* container operations ******************************************************/ FLINT_DLL 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; } FLINT_DLL void nmod_mpoly_resize(nmod_mpoly_t A, slong new_length, const nmod_mpoly_ctx_t ctx); FLINT_DLL ulong nmod_mpoly_get_term_coeff_ui(const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_set_term_coeff_ui(nmod_mpoly_t A, slong i, ulong c, const nmod_mpoly_ctx_t ctx); NMOD_MPOLY_INLINE 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); } NMOD_MPOLY_INLINE 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_DLL void nmod_mpoly_get_term_exp_fmpz(fmpz ** exp, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_get_term_exp_ui(ulong * exp, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_get_term_exp_si(slong * exp, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); FLINT_DLL ulong nmod_mpoly_get_term_var_exp_ui(const nmod_mpoly_t A, slong i, slong var, const nmod_mpoly_ctx_t ctx); FLINT_DLL slong nmod_mpoly_get_term_var_exp_si(const nmod_mpoly_t A, slong i, slong var, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_set_term_exp_fmpz(nmod_mpoly_t A, slong i, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_set_term_exp_ui(nmod_mpoly_t A, slong i, const ulong * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_get_term(nmod_mpoly_t M, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_get_term_monomial(nmod_mpoly_t M, const nmod_mpoly_t A, slong i, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_push_term_ui_fmpz(nmod_mpoly_t A, ulong c, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_push_term_ui_ui(nmod_mpoly_t A, ulong c, const ulong * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_sort_terms(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_combine_like_terms(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_reverse(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_assert_canonical(const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void _nmod_mpoly_radix_sort1(nmod_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, ulong cmpmask, ulong totalmask); FLINT_DLL void _nmod_mpoly_radix_sort(nmod_mpoly_t A, slong left, slong right, flint_bitcnt_t pos, slong N, ulong * cmpmask); FLINT_DLL void _nmod_mpoly_push_exp_ffmpz(nmod_mpoly_t A, const fmpz * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL void _nmod_mpoly_push_exp_pfmpz(nmod_mpoly_t A, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL void _nmod_mpoly_push_exp_ui(nmod_mpoly_t A, const ulong * exp, const nmod_mpoly_ctx_t ctx); /* Random generation *********************************************************/ FLINT_DLL void nmod_mpoly_randtest_bounds(nmod_mpoly_t A, flint_rand_t state, slong length, ulong * exp_bounds, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_randtest_bound(nmod_mpoly_t A, flint_rand_t state, slong length, ulong exp_bound, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL ulong _nmod_mpoly_get_term_ui_fmpz(const nmod_mpoly_t poly, const fmpz * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL ulong nmod_mpoly_get_term_ui_fmpz(const nmod_mpoly_t poly, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL ulong nmod_mpoly_get_term_ui_ui(const nmod_mpoly_t poly, const ulong * exp, const nmod_mpoly_ctx_t ctx); FLINT_DLL void _nmod_mpoly_max_degrees(ulong * max_degs, const ulong * exps, slong len, slong bits, slong n, int deg, int rev, slong N); FLINT_DLL void nmod_mpoly_max_degrees(ulong * max_degs, const nmod_mpoly_t poly, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_set_nmod(nmod_mpoly_t poly, const nmod_t c, const nmod_mpoly_ctx_t ctx); FLINT_DLL ulong nmod_mpoly_get_coeff_ui(nmod_t x, const nmod_mpoly_t poly, slong n, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_set_coeff_ui(nmod_mpoly_t poly, slong n, ulong x, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_get_monomial(ulong * exps, const nmod_mpoly_t poly, slong n, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_set_monomial(nmod_mpoly_t poly, slong n, const ulong * exps, const nmod_mpoly_ctx_t ctx); /* Addition/Subtraction ******************************************************/ FLINT_DLL void nmod_mpoly_add_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong c, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_sub_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong c, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_add(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_sub(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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 *********************************************************/ FLINT_DLL void nmod_mpoly_neg(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_scalar_mul_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong c, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_make_monic(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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_DLL 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 **************************************************************/ FLINT_DLL void nmod_mpoly_derivative(nmod_mpoly_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx); /* Evaluation ****************************************************************/ FLINT_DLL int _ff_poly_pow_fmpz_is_not_feasible(slong length, const fmpz_t e); FLINT_DLL int _ff_poly_pow_ui_is_not_feasible(slong length, ulong e); FLINT_DLL 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); FLINT_DLL ulong nmod_mpoly_evaluate_all_ui(const nmod_mpoly_t A, const ulong * vals, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ************************************************************/ FLINT_DLL void nmod_mpoly_mul(nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_t C, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ******************************************************************/ FLINT_DLL 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_DLL void nmod_mpoly_pow_rmul(nmod_mpoly_t A, const nmod_mpoly_t B, ulong k, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_pow_fmpz(nmod_mpoly_t A, const nmod_mpoly_t B, const fmpz_t k, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_pow_ui(nmod_mpoly_t A, const nmod_mpoly_t B, ulong k, const nmod_mpoly_ctx_t ctx); /* Division ******************************************************************/ FLINT_DLL int nmod_mpoly_divides(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void nmod_mpoly_div(nmod_mpoly_t Q, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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"); } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ***************************************************************/ FLINT_DLL 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; } FLINT_DLL 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 ***********************************************************************/ FLINT_DLL void nmod_mpoly_term_content(nmod_mpoly_t M, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int nmod_mpoly_gcd(nmod_mpoly_t G, const nmod_mpoly_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void nmod_mpoly_deflation(fmpz * shift, fmpz * stride, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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) ******************************************************************************/ FLINT_DLL void mpoly_void_ring_init_nmod_mpoly_ctx(mpoly_void_ring_t R, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyl_lead_coeff(nmod_mpoly_t c, const nmod_mpoly_t A, slong num_vars, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpolyl_content(nmod_mpoly_t g, const nmod_mpoly_t A, slong num_vars, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int nmod_mpoly_repack_bits(nmod_mpoly_t A, const nmod_mpoly_t B, flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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 ***************************************************************/ FLINT_DLL void nmod_mpoly_univar_init(nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_univar_clear(nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_univar_fit_length(nmod_mpoly_univar_t A, slong length, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_univar_print_pretty(const nmod_mpoly_univar_t A, const char ** x, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL 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); FLINT_DLL void nmod_mpoly_to_univar(nmod_mpoly_univar_t A, const nmod_mpoly_t B, slong var, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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) { nmod_mpoly_univar_struct t = *A; *A = *B; *B = t; } NMOD_MPOLY_INLINE 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); } NMOD_MPOLY_INLINE slong nmod_mpoly_univar_length(const nmod_mpoly_univar_t A, const nmod_mpoly_ctx_t ctx) { return A->length; } NMOD_MPOLY_INLINE 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); } 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); } FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int nmod_mpoly_univar_discriminant(nmod_mpoly_t D, const nmod_mpoly_univar_t Fx, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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 *************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _nmod_mpoly_addmul_array1_ulong1(ulong * poly1, const ulong * poly2, const ulong * exp2, slong len2, const ulong * poly3, const ulong * exp3, slong len3); FLINT_DLL void _nmod_mpoly_addmul_array1_ulong2(ulong * poly1, const ulong * poly2, const ulong * exp2, slong len2, const ulong * poly3, const ulong * exp3, slong len3); FLINT_DLL void _nmod_mpoly_addmul_array1_ulong3(ulong * poly1, const ulong * poly2, const ulong * exp2, slong len2, const ulong * poly3, const ulong * exp3, slong len3); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ********************************************************************/ FLINT_DLL void nmod_mpolyd_ctx_init(nmod_mpolyd_ctx_t dctx, slong nvars); FLINT_DLL void nmod_mpolyd_ctx_clear(nmod_mpolyd_ctx_t dctx); NMOD_MPOLY_INLINE void nmod_mpolyd_swap(nmod_mpolyd_t poly1, nmod_mpolyd_t poly2) { nmod_mpolyd_struct t = *poly1; *poly1 = *poly2; *poly2 = t; } FLINT_DLL int nmod_mpolyd_set_degbounds(nmod_mpolyd_t A, slong * bounds); FLINT_DLL int nmod_mpolyd_set_degbounds_perm(nmod_mpolyd_t A, const nmod_mpolyd_ctx_t dctx, slong * bounds); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void nmod_mpolyd_init(nmod_mpolyd_t poly, slong nvars); FLINT_DLL void nmod_mpolyd_fit_length(nmod_mpolyd_t poly, slong len); FLINT_DLL void nmod_mpolyd_zero(nmod_mpolyd_t poly); FLINT_DLL void nmod_mpolyd_set_nvars(nmod_mpolyd_t poly, slong nvars); FLINT_DLL void nmod_mpolyd_set(nmod_mpolyd_t A, const nmod_mpolyd_t B); FLINT_DLL void nmod_mpolyd_clear(nmod_mpolyd_t poly); FLINT_DLL void nmod_mpolyd_print(nmod_mpolyd_t poly); FLINT_DLL slong nmod_mpolyd_length(const nmod_mpolyd_t A); /* mpolyu ********************************************************************/ FLINT_DLL void nmod_mpolyu_init(nmod_mpolyu_t A, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyu_clear(nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx); FLINT_DLL void nmod_mpolyu_swap(nmod_mpolyu_t A, nmod_mpolyu_t B, const nmod_mpoly_ctx_t uctx); FLINT_DLL void nmod_mpolyu_zero(nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx); FLINT_DLL int nmod_mpolyu_is_one(nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx); FLINT_DLL void nmod_mpolyu_print_pretty(const nmod_mpolyu_t poly, const char ** x, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyu_fit_length(nmod_mpolyu_t A, slong length, const nmod_mpoly_ctx_t uctx); FLINT_DLL void nmod_mpolyu_one(nmod_mpolyu_t A, const nmod_mpoly_ctx_t uctx); FLINT_DLL void nmod_mpolyu_degrees_si( slong * degs, const nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyu_repack_bits_inplace( nmod_mpolyu_t A, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); FLINT_DLL nmod_mpoly_struct * _nmod_mpolyu_get_coeff(nmod_mpolyu_t A, ulong pow, const nmod_mpoly_ctx_t uctx); FLINT_DLL void nmod_mpolyu_shift_right(nmod_mpolyu_t A, ulong s); FLINT_DLL void nmod_mpolyu_shift_left(nmod_mpolyu_t A, ulong s); FLINT_DLL int nmod_mpolyu_content_mpoly(nmod_mpoly_t g, const nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyu_scalar_mul_nmod(nmod_mpolyu_t A, mp_limb_t c, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyu_set(nmod_mpolyu_t A, const nmod_mpolyu_t B, const nmod_mpoly_ctx_t uctx); FLINT_DLL void nmod_mpolyu_cvtto_poly(nmod_poly_t a, nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyu_cvtfrom_poly(nmod_mpolyu_t A, nmod_poly_t a, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyu_cvtfrom_poly_notmain(nmod_mpolyu_t A, nmod_poly_t a, slong var, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_DLL void nmod_mpolyu_divexact_mpoly_inplace(nmod_mpolyu_t A, nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyu_mul_mpoly(nmod_mpolyu_t A, nmod_mpolyu_t B, nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyu_mul_mpoly_inplace(nmod_mpolyu_t A, nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyu_setform(nmod_mpolyu_t A, nmod_mpolyu_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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 ********************************************************************/ FLINT_DLL void nmod_mpolyn_init(nmod_mpolyn_t A, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_clear(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_swap(nmod_mpolyn_t A, nmod_mpolyn_t B); FLINT_DLL void nmod_mpolyn_zero(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpolyn_is_zero(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_print_pretty(const nmod_mpolyn_t A, const char ** x_in, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_fit_length(nmod_mpolyn_t A, slong length, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_set_length(nmod_mpolyn_t A, slong newlen, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_fit_bits(nmod_mpolyn_t A, slong bits, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpolyn_is_canonical(const nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_set(nmod_mpolyn_t A, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_set_mpoly(nmod_mpolyn_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_cvtfrom_mpolyn(nmod_mpoly_t A, const nmod_mpolyn_t B, slong var, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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 *******************************************************************/ FLINT_DLL void nmod_mpolyun_init(nmod_mpolyun_t A, flint_bitcnt_t bits, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyun_clear(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyun_swap(nmod_mpolyun_t A, nmod_mpolyun_t B); FLINT_DLL void nmod_mpolyun_zero(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyun_print_pretty(const nmod_mpolyun_t poly, const char ** x, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyun_fit_length(nmod_mpolyun_t A, slong length, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpolyun_is_canonical(const nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyun_shift_right(nmod_mpolyun_t A, ulong s); FLINT_DLL void nmod_mpolyun_shift_left(nmod_mpolyun_t A, ulong s); FLINT_DLL slong nmod_mpolyn_lastdeg(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL slong nmod_mpolyun_lastdeg(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyun_set(nmod_mpolyun_t A, const nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_one(nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyun_one(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL mp_limb_t nmod_mpolyun_leadcoeff_last(nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_set_mod(nmod_mpolyn_t A, const nmod_t mod); FLINT_DLL void nmod_mpolyun_set_mod(nmod_mpolyun_t A, const nmod_t mod); FLINT_DLL int nmod_mpolyn_is_nonzero_nmod(const nmod_mpolyn_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpolyun_is_nonzero_nmod(const nmod_mpolyun_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_scalar_mul_nmod( nmod_mpolyn_t A, mp_limb_t c, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyun_scalar_mul_nmod(nmod_mpolyun_t A, mp_limb_t c, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_mul_last(nmod_mpolyn_t A, n_poly_t b, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyun_mul_last(nmod_mpolyun_t A, n_poly_t b, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpolyn_equal( const nmod_mpolyn_t A, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpolyun_equal(const nmod_mpolyun_t A, const nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyu_cvtto_mpolyun(nmod_mpolyun_t A, const nmod_mpolyu_t B, slong k, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyu_cvtfrom_mpolyun(nmod_mpolyu_t A, const nmod_mpolyun_t B, slong var, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void nmod_mpolyn_content_last(n_poly_t a, nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyun_content_last(n_poly_t a, nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyn_divexact_last(nmod_mpolyn_t A, n_poly_t b, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyun_divexact_last(nmod_mpolyun_t A, n_poly_t b, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpolyn_divides(nmod_mpolyn_t Q, const nmod_mpolyn_t A, const nmod_mpolyn_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int nmod_mpolyun_divides(nmod_mpolyun_t Q, const nmod_mpolyun_t A, const nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ***********************************************************************/ FLINT_DLL int mpoly_gcd_get_use_first(slong rGdeg, slong Adeg, slong Bdeg, slong gammadeg); FLINT_DLL 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); FLINT_DLL void nmod_mpolyu_setform_mpolyun(nmod_mpolyu_t A, nmod_mpolyun_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); 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; FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ********************************************************************/ FLINT_DLL void _nmod_poly_eval2_pow(mp_limb_t * vp, mp_limb_t * vm, n_poly_t P, n_poly_t alphapow, nmod_t fctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void nmod_mpolyn_interp_lift_sm_bpoly(nmod_mpolyn_t F, n_bpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void nmod_mpolyn_interp_lift_sm_mpoly(nmod_mpolyn_t A, const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyun_interp_lift_sm_mpolyu(nmod_mpolyun_t A, const nmod_mpolyu_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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]; FLINT_DLL void nmod_mpoly_geobucket_init(nmod_mpoly_geobucket_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_geobucket_clear(nmod_mpoly_geobucket_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_geobucket_empty(nmod_mpoly_t p, nmod_mpoly_geobucket_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_geobucket_fit_length(nmod_mpoly_geobucket_t B, slong i, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_geobucket_set(nmod_mpoly_geobucket_t B, nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_geobucket_add(nmod_mpoly_geobucket_t B, nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_geobucket_sub(nmod_mpoly_geobucket_t B, nmod_mpoly_t p, const nmod_mpoly_ctx_t ctx); /****************************************************************************** Internal consistency checks ******************************************************************************/ /* test that r is a valid remainder upon division by g this means that no monomial of r is divisible by lm(g) */ NMOD_MPOLY_INLINE 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); /* mask with high bit set in each field of exponent vector */ for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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_printf("nmod_mpoly_remainder_strongtest FAILED i = %wd\n", i); flint_printf("rem ");nmod_mpoly_print_pretty(r, NULL, ctx); printf("\n\n"); flint_printf("den ");nmod_mpoly_print_pretty(g, NULL, ctx); printf("\n\n"); flint_abort(); } } flint_free(rexp); flint_free(gexp); } #ifdef __cplusplus } #endif #endif flint2-2.8.4/nmod_mpoly/000077500000000000000000000000001414523752600151115ustar00rootroot00000000000000flint2-2.8.4/nmod_mpoly/add.c000066400000000000000000000120421414523752600160040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/add_ui.c000066400000000000000000000034771414523752600165150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/nmod_mpoly/cmp.c000066400000000000000000000021651414523752600160400ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/combine_like_terms.c000066400000000000000000000026231414523752600211120ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/compose_mat.c000066400000000000000000000040541414523752600175660ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_vec(v, M, u); 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; } flint2-2.8.4/nmod_mpoly/compose_nmod_mpoly.c000066400000000000000000000035021414523752600211570ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/compose_nmod_mpoly_gen.c000066400000000000000000000023441414523752600220130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/compose_nmod_mpoly_geobucket.c000066400000000000000000000035071414523752600232140ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/compose_nmod_mpoly_horner.c000066400000000000000000000247301414523752600225420ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 == 0) { nmod_mpoly_zero(A, 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; } flint2-2.8.4/nmod_mpoly/compose_nmod_poly.c000066400000000000000000000150711414523752600210060ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/nmod_mpoly/content_vars.c000066400000000000000000000127011414523752600177630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/ctx_clear.c000066400000000000000000000007541414523752600172270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" void nmod_mpoly_ctx_clear(nmod_mpoly_ctx_t ctx) { mpoly_ctx_clear(ctx->minfo); } flint2-2.8.4/nmod_mpoly/ctx_init.c000066400000000000000000000011661414523752600171020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/ctx_init_rand.c000066400000000000000000000012151414523752600201010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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); } flint2-2.8.4/nmod_mpoly/deflate.c000066400000000000000000000030371414523752600166640ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/deflation.c000066400000000000000000000012751414523752600172270ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/derivative.c000066400000000000000000000062131414523752600174210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/discriminant.c000066400000000000000000000014401414523752600177400ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/nmod_mpoly/div.c000066400000000000000000000011511414523752600160350ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/nmod_mpoly/div_monagan_pearce.c000066400000000000000000000434001414523752600210570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 indicies */ 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 cofficient 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) { /* optimation: 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 neccesary */ 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 indicies */ 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 cofficient 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) { /* optimation: 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 neccesary */ 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); } flint2-2.8.4/nmod_mpoly/divides.c000066400000000000000000000117571414523752600167170ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" #include "thread_pool.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; } 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); } 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; } flint2-2.8.4/nmod_mpoly/divides_dense.c000066400000000000000000000225501414523752600200660ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.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)) { count_leading_zeros(msb, 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) { 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; } flint2-2.8.4/nmod_mpoly/divides_heap_threaded.c000066400000000000000000001523271414523752600215530ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "nmod_mpoly.h" #include "fmpz_mpoly.h" /* for mpoly_divides_select_exps */ #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 stuct 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 with high bit set in each word of each field of exponent vector */ mask = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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 !FLINT_KNOW_STRONG_ORDER return nmod_mpoly_divides_monagan_pearce(Q, A, B, ctx); #endif 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; } flint2-2.8.4/nmod_mpoly/divides_monagan_pearce.c000066400000000000000000000443151414523752600217320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 indicies */ 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 cofficient 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 neccesary */ 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 indicies */ 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 cofficient 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; } flint2-2.8.4/nmod_mpoly/divrem.c000066400000000000000000000012021414523752600165360ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/nmod_mpoly/divrem_ideal.c000066400000000000000000000013241414523752600177010ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/nmod_mpoly/divrem_ideal_monagan_pearce.c000066400000000000000000000471711414523752600227320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; slong ** hinds; 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 = (mpoly_nheap_t **) TMP_ALLOC(Blen*sizeof(mpoly_nheap_t *)); hinds = (slong **) TMP_ALLOC(Blen*sizeof(slong *)); 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_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; } flint2-2.8.4/nmod_mpoly/divrem_monagan_pearce.c000066400000000000000000000510221414523752600215620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 indicies */ 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 cofficient 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 neccesary */ 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 indicies */ 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 cofficient 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 neccesary */ 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); } flint2-2.8.4/nmod_mpoly/equal.c000066400000000000000000000042661414523752600163740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/equal_ui.c000066400000000000000000000015331414523752600170630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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; } flint2-2.8.4/nmod_mpoly/evaluate_all.c000066400000000000000000000057211414523752600177200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/evaluate_one.c000066400000000000000000000130771414523752600177340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" #include "n_poly.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); } flint2-2.8.4/nmod_mpoly/fit_length.c000066400000000000000000000012531414523752600174010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/fit_length_fit_bits.c000066400000000000000000000030541414523752600212650ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "fq_nmod_mpoly.h" 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)); } } } flint2-2.8.4/nmod_mpoly/fit_length_reset_bits.c000066400000000000000000000013401414523752600216210ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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; } flint2-2.8.4/nmod_mpoly/fprint_pretty.c000066400000000000000000000057221414523752600201740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_mpoly.h" 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); } flint2-2.8.4/nmod_mpoly/gcd.c000066400000000000000000002027011414523752600160140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "n_poly.h" #include "nmod_mpoly.h" #include "fq_nmod_mpoly.h" #include "nmod_mpoly_factor.h" #include "fq_zech_poly.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); fmpz_t P; if (max_degree < 2) return; flint_randinit(state); fmpz_init_set_ui(P, smctx->mod.n); fq_zech_ctx_init(medctx, P, 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_clear(medctx); fq_zech_ctx_init(medctx, P, 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); fmpz_clear(P); 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_div(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_div(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); } flint2-2.8.4/nmod_mpoly/gcd_brown.c000066400000000000000000001177231414523752600172340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" #include "thread_pool.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_div(Abarevalp, Aevalp, Gevalp, ctx->mod); n_poly_mod_div(Bbarevalp, Bevalp, Gevalp, ctx->mod); n_poly_mod_gcd(Gevalm, Aevalm, Bevalm, ctx->mod); n_poly_mod_div(Abarevalm, Aevalm, Gevalm, ctx->mod); n_poly_mod_div(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_div(cAbar, cA, cG, ctx->mod); n_poly_mod_div(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); 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); 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); 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); 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); 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); 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); } flint2-2.8.4/nmod_mpoly/gcd_cofactors.c000066400000000000000000000035751414523752600200670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/gcd_hensel.c000066400000000000000000000631121414523752600173530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" #include "fq_zech_mpoly.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); } flint2-2.8.4/nmod_mpoly/gcd_zippel.c000066400000000000000000000374561414523752600174140ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 everytime, 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); } flint2-2.8.4/nmod_mpoly/gcd_zippel2.c000066400000000000000000002366011414523752600174670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" #include "nmod_mpoly_factor.h" #include "fq_nmod_mpoly.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); } flint2-2.8.4/nmod_mpoly/gen.c000066400000000000000000000016021414523752600160250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/geobuckets.c000066400000000000000000000101051414523752600174050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/get_coeff_ui_fmpz.c000066400000000000000000000015311414523752600207270ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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]; } } flint2-2.8.4/nmod_mpoly/get_coeff_ui_monomial.c000066400000000000000000000017511414523752600215720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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]; } } flint2-2.8.4/nmod_mpoly/get_coeff_ui_ui.c000066400000000000000000000015241414523752600203720ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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]; } } flint2-2.8.4/nmod_mpoly/get_coeff_vars_ui.c000066400000000000000000000101341414523752600207250ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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; } flint2-2.8.4/nmod_mpoly/get_set_is_nmod_poly.c000066400000000000000000000073341414523752600214710ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/get_str_pretty.c000066400000000000000000000063221414523752600203360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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, "%wd", 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); } flint2-2.8.4/nmod_mpoly/get_term.c000066400000000000000000000016341414523752600170670ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/get_term_coeff_ui.c000066400000000000000000000013231414523752600207210ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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]; } flint2-2.8.4/nmod_mpoly/get_term_exp_fmpz.c000066400000000000000000000015361414523752600210000ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/get_term_exp_si.c000066400000000000000000000015311414523752600204320ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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); } flint2-2.8.4/nmod_mpoly/get_term_exp_ui.c000066400000000000000000000015311414523752600204340ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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); } flint2-2.8.4/nmod_mpoly/get_term_monomial.c000066400000000000000000000016751414523752600207670ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/get_term_ui_fmpz.c000066400000000000000000000036211414523752600206160ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/get_term_ui_ui.c000066400000000000000000000016541414523752600202630ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/get_term_var_exp_si.c000066400000000000000000000015211414523752600213010ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/get_term_var_exp_ui.c000066400000000000000000000015211414523752600213030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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); } flint2-2.8.4/nmod_mpoly/get_ui.c000066400000000000000000000015641414523752600165370ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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]; } flint2-2.8.4/nmod_mpoly/inflate.c000066400000000000000000000046341414523752600167060ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/init.c000066400000000000000000000022201414523752600162140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/inlines.c000066400000000000000000000011431414523752600167150ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #define NMOD_MPOLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "nmod_mpoly.h" flint2-2.8.4/nmod_mpoly/interp.c000066400000000000000000001256221414523752600165660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } /*****************************************************************************/ /* 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; } /****************************************************************************/ 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; } flint2-2.8.4/nmod_mpoly/is_canonical.c000066400000000000000000000034251414523752600177030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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"); } } flint2-2.8.4/nmod_mpoly/is_gen.c000066400000000000000000000012711414523752600165220ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/is_ui.c000066400000000000000000000012701414523752600163650ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/lead_coeff_vars.c000066400000000000000000000035421414523752600203630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/nmod_mpoly/make_monic.c000066400000000000000000000014471414523752600173650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/mpolyd.c000066400000000000000000000240421414523752600165630ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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)) { count_leading_zeros(msb, 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; } 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^%wd", j, e); } FLINT_ASSERT(k == 0); first = 0; } if (first) flint_printf("0"); } 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; } flint2-2.8.4/nmod_mpoly/mpolyn.c000066400000000000000000000153051414523752600165770ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_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; } 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; } flint2-2.8.4/nmod_mpoly/mpolyn_divides_threaded.c000066400000000000000000001465111414523752600221520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" #include "nmod_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 stuct 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 with high bit set in each word of each field of exponent vector */ mask = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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 with high bit set in each word of each field of exponent vector */ mask = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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 i; slong N = H->N; nmod_mpolyn_struct * C = L->polyC; slong q_prev_length; ulong mask; 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; 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; 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 !FLINT_KNOW_STRONG_ORDER return nmod_mpolyn_divides(Q, A, B, ctx); #endif 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_div(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 = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); 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; } flint2-2.8.4/nmod_mpoly/mpolyn_gcd_brown.c000066400000000000000000001134761414523752600206330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_div(cAbar, cA, cG, ctx->mod); n_poly_mod_div(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_div(Abarevalp, Aevalp, Gevalp, ctx->mod); n_poly_mod_div(Bbarevalp, Bevalp, Gevalp, ctx->mod); n_poly_mod_gcd(Gevalm, Aevalm, Bevalm, ctx->mod); n_poly_mod_div(Abarevalm, Aevalm, Gevalm, ctx->mod); n_poly_mod_div(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_div(cAbar, cA, cG, ctx->mod); n_poly_mod_div(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_div(cAbar, cA, cG, ctx->mod); n_poly_mod_div(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_div(cAbar, cA, cG, ctx->mod); n_poly_mod_div(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; } flint2-2.8.4/nmod_mpoly/mpolyu.c000066400000000000000000000703611414523752600166110ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } void nmod_mpolyu_swap(nmod_mpolyu_t A, nmod_mpolyu_t B, const nmod_mpoly_ctx_t uctx) { nmod_mpolyu_struct t = *A; *A = *B; *B = t; } 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) { 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++) SLONG_SWAP(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; } flint2-2.8.4/nmod_mpoly/mpolyu_divides.c000066400000000000000000000441271414523752600203210ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 indicies */ 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 neccesary */ 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; } flint2-2.8.4/nmod_mpoly/mpolyu_gcdp_zippel.c000066400000000000000000001064321414523752600211700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_div(t, a, g); nmod_mpolyu_cvtfrom_poly(Abar, t, ctx); nmod_poly_div(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; } flint2-2.8.4/nmod_mpoly/mpolyun.c000066400000000000000000000675331414523752600167760ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_swap(nmod_mpolyun_t A, nmod_mpolyun_t B) { nmod_mpolyun_struct t = *A; *A = *B; *B = t; } 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); } flint2-2.8.4/nmod_mpoly/mpolyun_divides.c000066400000000000000000000670171414523752600205020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" 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; 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 = mpoly_words_per_exp_sp(bits, ctx->minfo); cmpmask = (ulong *) TMP_ALLOC(N*sizeof(ulong)); mpoly_get_cmpmask(cmpmask, N, bits, ctx->minfo); 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 indicies */ hind = (slong *) TMP_ALLOC(B->length*sizeof(slong)); for (i = 0; i < B->length; i++) hind[i] = 1; /* mask with high bit set in each word of each field of exponent vector */ mask = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); /* 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, 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 indicies */ hind = (slong *) TMP_ALLOC(B->length*sizeof(slong)); for (i = 0; i < B->length; i++) hind[i] = 1; /* mask with high bit set in each word of each field of exponent vector */ mask = 0; for (i = 0; i < FLINT_BITS/bits; i++) mask = (mask << bits) + (UWORD(1) << (bits - 1)); /* 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; } 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 indicies */ 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 neccesary */ 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; } flint2-2.8.4/nmod_mpoly/mul.c000066400000000000000000000167571414523752600160720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 relevent 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 (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; } flint2-2.8.4/nmod_mpoly/mul_array.c000066400000000000000000001135641414523752600172620ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" /* 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++) { c2 = poly1 + 2*((slong) exp2[i]); if (poly2[i] != 0) { for (j = jj; j < FLINT_MIN(jj + BLOCK, len3); j++) { c = c2 + 2*((slong) exp3[j]); 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(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 wil 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(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 wil 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 ( 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; } flint2-2.8.4/nmod_mpoly/mul_array_threaded.c000066400000000000000000000631321414523752600211150ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "string.h" #include "thread_pool.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 wil 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 wil 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 (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; } flint2-2.8.4/nmod_mpoly/mul_dense.c000066400000000000000000000114221414523752600172300ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.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(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) { 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; } flint2-2.8.4/nmod_mpoly/mul_heap_threaded.c000066400000000000000000000575211414523752600207210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "thread_pool.h" #include "nmod_mpoly.h" #include "long_extras.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 divisons */ 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; } flint2-2.8.4/nmod_mpoly/mul_johnson.c000066400000000000000000000270771414523752600176250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/neg.c000066400000000000000000000015631414523752600160330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/pow_fmpz.c000066400000000000000000000036101414523752600171160ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/pow_rmul.c000066400000000000000000000042651414523752600171300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/pow_ui.c000066400000000000000000000107401414523752600165610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/profile/000077500000000000000000000000001414523752600165515ustar00rootroot00000000000000flint2-2.8.4/nmod_mpoly/profile/p-divides.c000066400000000000000000000172301414523752600206040ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/nmod_mpoly/profile/p-gcd.c000066400000000000000000000262221414523752600177130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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() { 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; } flint2-2.8.4/nmod_mpoly/profile/p-mul.c000066400000000000000000000160431414523752600177530ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/nmod_mpoly/profile/p-sqrt.c000066400000000000000000000046331414523752600201510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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) << (FLINT_BITS - 2), 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; } flint2-2.8.4/nmod_mpoly/push_term_ui_fmpz.c000066400000000000000000000033411414523752600210150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/push_term_ui_ui.c000066400000000000000000000022611414523752600204560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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; } flint2-2.8.4/nmod_mpoly/quadratic_root.c000066400000000000000000000275461414523752600203130ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/randtest_bits.c000066400000000000000000000023061414523752600201230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/randtest_bound.c000066400000000000000000000021211414523752600202640ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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; } flint2-2.8.4/nmod_mpoly/randtest_bounds.c000066400000000000000000000021261414523752600204540ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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; } flint2-2.8.4/nmod_mpoly/realloc.c000066400000000000000000000016561414523752600167060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/nmod_mpoly/repack_bits.c000066400000000000000000000037761414523752600175600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/resize.c000066400000000000000000000020351414523752600165560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/resultant.c000066400000000000000000000016241414523752600173010ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/nmod_mpoly/reverse.c000066400000000000000000000017551414523752600167400ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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++) MP_LIMB_SWAP(A->coeffs[i], A->coeffs[Blen - i - 1]); } mpoly_reverse(A->exps, B->exps, Blen, N); } flint2-2.8.4/nmod_mpoly/scalar_addmul_ui.c000066400000000000000000000127251414523752600205540ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/scalar_mul_ui.c000066400000000000000000000047351414523752600201050ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" /* 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; } flint2-2.8.4/nmod_mpoly/set.c000066400000000000000000000014701414523752600160520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/set_coeff_ui_fmpz.c000066400000000000000000000053001414523752600207410ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/set_coeff_ui_monomial.c000066400000000000000000000021161414523752600216020ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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; } flint2-2.8.4/nmod_mpoly/set_coeff_ui_ui.c000066400000000000000000000015761414523752600204150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mpoly.h" 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; } flint2-2.8.4/nmod_mpoly/set_fmpz.c000066400000000000000000000017651414523752600171150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_fdiv_ui(c, ctx->mod.n), ctx); } flint2-2.8.4/nmod_mpoly/set_str_pretty.c000066400000000000000000000024201414523752600203450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/nmod_mpoly/set_term_coeff_ui.c000066400000000000000000000014211414523752600207340ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/set_term_exp_fmpz.c000066400000000000000000000020031414523752600210020ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/set_term_exp_ui.c000066400000000000000000000017741414523752600204610ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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); } flint2-2.8.4/nmod_mpoly/set_term_ui_fmpz.c000066400000000000000000000006271414523752600206350ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" flint2-2.8.4/nmod_mpoly/set_term_ui_ui.c000066400000000000000000000006301414523752600202700ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" flint2-2.8.4/nmod_mpoly/setform.c000066400000000000000000000042201414523752600167320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/sort_terms.c000066400000000000000000000112331414523752600174560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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) { count_leading_zeros(msb, 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; } flint2-2.8.4/nmod_mpoly/sqrt_heap.c000066400000000000000000000521051414523752600172460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; fmpz_t p; 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; fmpz_init_set_ui(p, mod.n); fq_zech_ctx_init(fqctx, p, 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; fmpz_clear(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 cofficient 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 cofficient 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; } flint2-2.8.4/nmod_mpoly/stack.c000066400000000000000000000120241414523752600163610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_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; } flint2-2.8.4/nmod_mpoly/sub.c000066400000000000000000000124131414523752600160470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/sub_ui.c000066400000000000000000000012501414523752600165410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly/term_content.c000066400000000000000000000032231414523752600177560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/test/000077500000000000000000000000001414523752600160705ustar00rootroot00000000000000flint2-2.8.4/nmod_mpoly/test/t-add_sub.c000066400000000000000000000336021414523752600201020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("add_sub...."); fflush(stdout); /* 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 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); 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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 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); 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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 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); 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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 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(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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 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(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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 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); 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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 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); 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-add_sub_ui.c000066400000000000000000000100141414523752600205670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("add_sub_ui...."); fflush(stdout); /* 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; ordering_t ord; mp_limb_t modulus; ulong c; slong nvars, len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 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); 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); 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; ordering_t ord; mp_limb_t modulus; ulong c; slong nvars, len1, len2; slong exp_bits1, exp_bits2; ord = mpoly_ordering_randtest(state); nvars = n_randint(state, 20) + 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); 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-cmp.c000066400000000000000000000134411414523752600172570ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" #include "ulong_extras.h" int main(void) { int result; slong i, j1, j2; FLINT_TEST_INIT(state); flint_printf("cmp...."); fflush(stdout); /* 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-compose_nmod_mpoly.c000066400000000000000000000346171414523752600224120ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j, v; FLINT_TEST_INIT(state); flint_printf("compose_nmod_mpoly...."); fflush(stdout); { 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); 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); 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); 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); 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); 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); 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); 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/nvars1 + 1); len2 = n_randint(state, 10/nvars2 + 2); exp_bound1 = n_randint(state, 12/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); 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); 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-compose_nmod_poly.c000066400000000000000000000113051414523752600222220ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, v; FLINT_TEST_INIT(state); flint_printf("compose_nmod_poly...."); fflush(stdout); { 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); 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); flint_abort(); } if (!nmod_poly_is_zero(A)) { printf("FAIL\n"); flint_printf("Check example 2 equality\n", i); 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/nvars1 + 1); len2 = n_randint(state, 100); exp_bound1 = n_randint(state, 200/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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-content_vars.c000066400000000000000000000112041414523752600212000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("content_vars...."); fflush(stdout); /* 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"); 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; 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); SLONG_SWAP(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"); flint_abort(); } if (nmod_mpoly_is_zero(g, ctx)) { if (!nmod_mpoly_is_zero(f, ctx)) { flint_printf("FAIL: check zero content\n"); 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"); flint_abort(); } } if (!nmod_mpoly_divides(t, f, g, ctx)) { flint_printf("FAIL: check content divides\n"); flint_abort(); } if (!nmod_mpoly_content_vars(t, t, vars, num_vars, ctx)) { flint_printf("FAIL: check cofactor content could be computed\n"); flint_abort(); } if (!nmod_mpoly_is_one(t, ctx)) { flint_printf("FAIL: check cofactor content is one\n"); flint_abort(); } } if (!nmod_mpoly_content_vars(f, f, vars, num_vars, ctx)) { flint_printf("FAIL: check aliased content could be computed\n"); flint_abort(); } if (!nmod_mpoly_equal(f, g, ctx)) { flint_printf("FAIL: check aliasing\n"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-degree.c000066400000000000000000000110721414523752600177310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("degree...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-derivative.c000066400000000000000000000142131414523752600206400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result; slong tmul = 5; FLINT_TEST_INIT(state); flint_printf("derivative...."); fflush(stdout); /* 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); 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); flint_abort(); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-div.c000066400000000000000000000215611414523752600172640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("div...."); fflush(stdout); { 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"); 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); 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); 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); 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 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; max_bound = 1 + 400/nvars/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++) { 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-div_monagan_pearce.c000066400000000000000000000152251414523752600223030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("div_monagan_pearce...."); fflush(stdout); /* 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); 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); 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); 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; 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; exp_bound = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound1 = n_randint(state, 50/ctx->minfo->nvars) + 1; exp_bound2 = n_randint(state, 50/ctx->minfo->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(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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-divides.c000066400000000000000000000346441414523752600201370ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result, ret, max_threads = 5, tmul = 25; FLINT_TEST_INIT(state); flint_printf("divides...."); fflush(stdout); /* 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); 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); 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; 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); max_bound = 1 + 150/ctx->minfo->nvars/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)); 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); 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/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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-divides_dense.c000066400000000000000000000253111414523752600213040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result, ret; FLINT_TEST_INIT(state); flint_printf("divides_dense...."); fflush(stdout); /* 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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; 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/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)); 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/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)); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-divides_heap_threaded.c000066400000000000000000000340241414523752600227640ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "thread_pool.h" #include "nmod_mpoly.h" #include "fmpz_mpoly.h" int main(void) { int i, j, result, result2, max_threads = 5, tmul = 30; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 1; #endif flint_printf("divides_heap_threaded...."); fflush(stdout); { 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"); 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); 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); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-divides_monagan_pearce.c000066400000000000000000000316621414523752600231530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result, ok1, ok2; FLINT_TEST_INIT(state); flint_printf("divides_monagan_pearce...."); fflush(stdout); /* 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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; exp_bound = n_randint(state, 200/nvars + 1) + 1; exp_bound1 = n_randint(state, 200/nvars + 1) + 1; exp_bound2 = n_randint(state, 200/nvars + 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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; 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); 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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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); len = n_randint(state, 20); len1 = n_randint(state, 20); len2 = n_randint(state, 20) + 1; exp_bound = n_randint(state, 200/nvars + 1) + 1; exp_bound1 = n_randint(state, 200/nvars + 1) + 1; exp_bound2 = n_randint(state, 200/nvars + 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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2; slong exp_bits, exp_bits1, exp_bits2; 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); 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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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); len = n_randint(state, 100); len1 = n_randint(state, 100); len2 = n_randint(state, 100) + 1; exp_bound = n_randint(state, 200/nvars + 1) + 1; exp_bound1 = n_randint(state, 200/nvars + 1) + 1; exp_bound2 = n_randint(state, 200/nvars + 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-divrem.c000066400000000000000000000352221414523752600177670ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("divrem...."); fflush(stdout); /* 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 nvars, len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; 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; exp_bits = n_randint(state, FLINT_BITS - 2) + 1; exp_bits1 = n_randint(state, FLINT_BITS - 2) + 1; exp_bits2 = n_randint(state, FLINT_BITS - 2) + 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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/nvars) + 1; exp_bound1 = n_randint(state, 50/nvars) + 1; exp_bound2 = n_randint(state, 50/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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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(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/nvars) + 1; exp_bound1 = n_randint(state, 50/nvars) + 1; exp_bound2 = n_randint(state, 50/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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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(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/nvars) + 1; exp_bound1 = n_randint(state, 50/nvars) + 1; exp_bound2 = n_randint(state, 50/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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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(r1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/nvars) + 1; exp_bound1 = n_randint(state, 50/nvars) + 1; exp_bound2 = n_randint(state, 50/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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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(r1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/nvars) + 1; exp_bound1 = n_randint(state, 50/nvars) + 1; exp_bound2 = n_randint(state, 50/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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-divrem_ideal.c000066400000000000000000000242661414523752600211330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int result; slong i, j, w; FLINT_TEST_INIT(state); flint_printf("divrem_ideal...."); fflush(stdout); /* 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 nvars, len, len1, len2; flint_bitcnt_t 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; 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); 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; ordering_t ord; 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)); 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); 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/nvars + 1) + 2; exp_bound1 = n_randint(state, 25/nvars + 1) + 2; exp_bound2 = n_randint(state, 20/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); 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; ordering_t ord; 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)); 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); 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/nvars + 1) + 2; exp_bound1 = n_randint(state, 25/nvars + 1) + 2; exp_bound2 = n_randint(state, 20/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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-divrem_ideal_monagan_pearce.c000066400000000000000000000234131414523752600241430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int result; slong i, j, w; FLINT_TEST_INIT(state); flint_printf("divrem_ideal_monagan_pearce...."); fflush(stdout); /* 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); 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; ordering_t ord; 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)); 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); 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/nvars + 1) + 2; exp_bound1 = n_randint(state, 25/nvars + 1) + 2; exp_bound2 = n_randint(state, 20/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); 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; ordering_t ord; 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)); 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); 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/nvars + 1) + 2; exp_bound1 = n_randint(state, 25/nvars + 1) + 2; exp_bound2 = n_randint(state, 20/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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-divrem_monagan_pearce.c000066400000000000000000000354701414523752600230130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("divrem_monagan_pearce...."); fflush(stdout); /* 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 nvars, len, len1, len2; flint_bitcnt_t exp_bits, exp_bits1, exp_bits2; 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; 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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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, 10); len1 = n_randint(state, 20); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/nvars) + 1; exp_bound1 = n_randint(state, 50/nvars) + 1; exp_bound2 = n_randint(state, 50/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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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(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/nvars) + 1; exp_bound1 = n_randint(state, 50/nvars) + 1; exp_bound2 = n_randint(state, 50/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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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(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/nvars) + 1; exp_bound1 = n_randint(state, 50/nvars) + 1; exp_bound2 = n_randint(state, 50/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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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(r1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/nvars) + 1; exp_bound1 = n_randint(state, 50/nvars) + 1; exp_bound2 = n_randint(state, 50/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); 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; ordering_t ord; mp_limb_t modulus; slong nvars, len, len1, len2, exp_bound, exp_bound1, exp_bound2; 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(r1, ctx); len = n_randint(state, 10); len1 = n_randint(state, 10); len2 = n_randint(state, 10) + 1; exp_bound = n_randint(state, 50/nvars) + 1; exp_bound1 = n_randint(state, 50/nvars) + 1; exp_bound2 = n_randint(state, 50/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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-evaluate.c000066400000000000000000000146361414523752600203150ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j, v; int tmul = 20; FLINT_TEST_INIT(state); flint_printf("evaluate...."); fflush(stdout); /* 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); 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); 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-gcd.c000066400000000000000000000664431414523752600172470ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } int main(void) { const slong max_threads = 5; slong i, j, k, tmul = 5; FLINT_TEST_INIT(state); flint_printf("gcd...."); fflush(stdout); { 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"); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-gcd_brown.c000066400000000000000000000146141414523752600204470ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; slong tmul = 10; slong max_threads = 6; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 1; #endif flint_printf("gcd_brown...."); fflush(stdout); { 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/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 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); degbound = 1 + 60/ctx->minfo->nvars/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"); } 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-gcd_cofactors.c000066400000000000000000001024451414523752600213030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); } int main(void) { const slong max_threads = 5; slong i, j, k, tmul = 3; FLINT_TEST_INIT(state); flint_printf("gcd_cofactors...."); fflush(stdout); { 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-gcd_hensel.c000066400000000000000000000122271414523752600205740ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_hensel...."); fflush(stdout); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-gcd_zippel.c000066400000000000000000000115751414523752600206260ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_zippel...."); fflush(stdout); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-gcd_zippel2.c000066400000000000000000000116501414523752600207020ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("gcd_zippel2...."); fflush(stdout); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-gen.c000066400000000000000000000046551414523752600172600ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gen/is_gen...."); fflush(stdout); 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); 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); 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); flint_abort(); } nmod_mpoly_clear(f1, ctx); nmod_mpoly_clear(f2, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-get_coeff_vars_ui.c000066400000000000000000000133621414523752600221530ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j1, j2; FLINT_TEST_INIT(state); flint_printf("get_coeff_vars_ui...."); fflush(stdout); /* 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"); 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); 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-get_set_string_pretty.c000066400000000000000000000035311414523752600231260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("get_set_string_pretty...."); fflush(stdout); { 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"); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(f1, ctx); nmod_mpoly_ctx_clear(ctx); } } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-get_set_term_coeff_ui.c000066400000000000000000000042551414523752600230230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("get/set_term_coeff_ui...."); fflush(stdout); /* 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); 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); flint_abort(); } } } nmod_mpoly_clear(f, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-get_set_term_exp_si.c000066400000000000000000000054001414523752600225240ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get/set_term_exp_si...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } nmod_mpoly_clear(f, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-get_set_term_exp_ui.c000066400000000000000000000053631414523752600225360ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" #include "ulong_extras.h" int main(void) { slong i, j, k; int result; FLINT_TEST_INIT(state); flint_printf("get/set_term_exp_ui...."); fflush(stdout); /* 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); flint_abort(); } flint_free(exp1); flint_free(exp2); } nmod_mpoly_clear(f, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-get_term.c000066400000000000000000000041311414523752600203020ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("get_term...."); fflush(stdout); /* 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); flint_abort(); } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-get_term_monomial.c000066400000000000000000000046201414523752600222000ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("get_term_monomial...."); fflush(stdout); /* 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-inflate_deflate.c000066400000000000000000000154451414523752600216140ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, success; FLINT_TEST_INIT(state); flint_printf("inflate_deflate...."); fflush(stdout); /* 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-mpolyn_divides_threaded.c000066400000000000000000000137531414523752600233730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" 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); 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); 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); } int main(void) { slong i, j, max_threads = 5, tmul = 50; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 2; #endif flint_printf("mpolyn_divides_threaded...."); fflush(stdout); /* 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-mpolyuu_divides.c000066400000000000000000000133001414523752600217130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_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); 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); 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); } int main(void) { slong i, j, tmul = 50; FLINT_TEST_INIT(state); flint_printf("mpolyuu_divides...."); fflush(stdout); /* 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly/test/t-mul.c000066400000000000000000000162221414523752600172750ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result, max_threads = 5; int tmul = 10; #ifdef _WIN32 tmul = 1; #endif FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); /* 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, FLINT_BITS - 2) + 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); 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, nvars; flint_bitcnt_t exp_bound, exp_bound1, exp_bound2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 2) + 2; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 4, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); exp_bound = 3 + n_randint(state, 1 + 100/nvars/nvars); exp_bound1 = 3 + n_randint(state, 1 + 100/nvars/nvars); exp_bound2 = 3 + n_randint(state, 1 + 100/nvars/nvars); len = exp_bound + 1; len1 = exp_bound1 + 1; len2 = exp_bound2 + 1; for (j = n_randint(state, nvars) + 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); 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, nvars; flint_bitcnt_t exp_bound, exp_bound1, exp_bound2; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 2) + 2; modulus = n_randbits(state, modulus); nmod_mpoly_ctx_init_rand(ctx, state, 4, modulus); nvars = ctx->minfo->nvars; nmod_mpoly_init(f, ctx); nmod_mpoly_init(g, ctx); nmod_mpoly_init(h, ctx); exp_bound = 3 + n_randint(state, 1 + 100/nvars/nvars); exp_bound1 = 3 + n_randint(state, 1 + 100/nvars/nvars); exp_bound2 = 3 + n_randint(state, 1 + 100/nvars/nvars); len = exp_bound + 1; len1 = exp_bound1 + 1; len2 = exp_bound2 + 1; for (j = n_randint(state, nvars) + 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-mul_array.c000066400000000000000000000140661414523752600204770ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("mul_array...."); fflush(stdout); /* 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 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; max_bound = max_bound/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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 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); max_bound = 200/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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 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); max_bound = 200/ctx->minfo->nvars/ctx->minfo->nvars; 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-mul_array_threaded.c000066400000000000000000000150401414523752600223300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" #include "ulong_extras.h" int main(void) { int i, j, result, max_threads = 5; int tmul = 50; #ifdef _WIN32 tmul = 1; #endif FLINT_TEST_INIT(state); flint_printf("mul_array_threaded...."); fflush(stdout); /* 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 max_bound; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 2) + 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; max_bound = max_bound/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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 max_bound; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 2) + 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); max_bound = 200/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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 max_bound; mp_limb_t modulus; modulus = n_randint(state, FLINT_BITS - 2) + 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); max_bound = 200/ctx->minfo->nvars/ctx->minfo->nvars; 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-mul_dense.c000066400000000000000000000143351414523752600204560ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result, success; FLINT_TEST_INIT(state); flint_printf("mul_dense...."); fflush(stdout); /* 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/ctx->minfo->nvars; 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); 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; 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); max_bound = 1 + 100/ctx->minfo->nvars/ctx->minfo->nvars; 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-mul_heap_threaded.c000066400000000000000000000160061414523752600221320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j, result, max_threads = 5; slong tmul = 10; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 2; #endif flint_printf("mul_heap_threaded...."); fflush(stdout); { 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"); 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); 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); 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-mul_johnson.c000066400000000000000000000145231414523752600210350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong tmul = 8; int i, j, result; FLINT_TEST_INIT(state); flint_printf("mul_johnson...."); fflush(stdout); /* 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); 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); 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-pow_rmul.c000066400000000000000000000077141414523752600203520ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" 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); } } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("pow_rmul...."); fflush(stdout); { 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"); 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/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); 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-pow_ui.c000066400000000000000000000075331414523752600200070ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" 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); } } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("pow_ui...."); fflush(stdout); 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/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); 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); 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); 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-push_term_ui_ui.c000066400000000000000000000062651414523752600217060ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("push_term_ui_ui...."); fflush(stdout); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-quadratic_root.c000066400000000000000000000070451414523752600215230ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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"); 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"); 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"); 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"); flint_abort(); } nmod_mpoly_clear(s, ctx); nmod_mpoly_clear(t, ctx); } int main(void) { slong i, j, tmul = 20; FLINT_TEST_INIT(state); flint_printf("quadratic_root...."); fflush(stdout); /* 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-repack_bits.c000066400000000000000000000147051414523752600207720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j; int success; FLINT_TEST_INIT(state); flint_printf("repack_bits...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-resize.c000066400000000000000000000061261414523752600200030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("resize...."); fflush(stdout); 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); flint_abort(); } if (!nmod_mpoly_equal(f1, f3, ctx)) { printf("FAIL\n"); flint_printf("Check resize+setterm matches add\ni=%wd\n",i); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-resultant_discriminant.c000066400000000000000000000205431414523752600232660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("resultant_discriminant...."); fflush(stdout); /* 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"); flint_abort(); } if (!nmod_mpoly_equal(d, d1, ctx)) { flint_printf("FAIL: Check quadratic polynomial\n"); 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_rand(ctx, state, 1, 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-scalar_addmul_ui.c000066400000000000000000000057741414523752600220020ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("scalar_addmul_ui...."); fflush(stdout); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-scalar_mul_ui.c000066400000000000000000000136331414523752600213220ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_ui...."); fflush(stdout); /* 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-sqrt.c000066400000000000000000000133531414523752600174730ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j, tmul = 10; FLINT_TEST_INIT(state); flint_printf("sqrt...."); fflush(stdout); /* 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"); 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); 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); flint_abort(); } } else if (!nmod_mpoly_is_zero(g, ctx)) { flint_printf("FAIL: Check nonsquare returns 0 sqrt\n"); 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"); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(h, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-term_content.c000066400000000000000000000070411414523752600212000ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("term_content...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); flint_abort(); } } nmod_mpoly_clear(f, ctx); nmod_mpoly_clear(g, ctx); nmod_mpoly_clear(k, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-total_degree.c000066400000000000000000000124471414523752600211430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); } int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("total_degree...."); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-univar.c000066400000000000000000000067121414523752600200070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("univar...."); fflush(stdout); /* 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, FLINT_BITS - 2) + 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-univar_resultant.c000066400000000000000000000127671414523752600221170ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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); 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); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("univar_resultant...."); fflush(stdout); { 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"); 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"); 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"); 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_rand(ctx, state, 1, 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/test/t-used_vars.c000066400000000000000000000041411414523752600204700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("used_vars...."); fflush(stdout); 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 < 10; 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"); flint_abort(); } } } flint_free(used); fmpz_clear(fdeg); nmod_mpoly_clear(f, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly/to_from_nmod_poly.c000066400000000000000000000067641414523752600210170ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly/univar.c000066400000000000000000000435171414523752600165730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } 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); } SLONG_SWAP(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; } flint2-2.8.4/nmod_mpoly/void_ring.c000066400000000000000000000072751414523752600172500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly_factor.h000066400000000000000000000460671414523752600166350ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define NMOD_MPOLY_FACTOR_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "nmod_mpoly.h" #include "n_poly.h" #ifdef __cplusplus extern "C" { #endif FLINT_DLL void nmod_mpoly_get_bpoly(n_bpoly_t A, const nmod_mpoly_t B, slong var0, slong var1, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int n_bpoly_mod_factor_smprime( n_poly_t c, n_tpoly_t F, n_bpoly_t B, int allow_shift, nmod_t ctx); FLINT_DLL void n_bpoly_mod_factor_lgprime( n_poly_t c, n_tpoly_t F, n_bpoly_t B, nmod_t ctx); /*****************************************************************************/ FLINT_DLL int nmod_mat_is_reduced(const nmod_mat_t N); FLINT_DLL void nmod_mat_init_nullspace_tr(nmod_mat_t X, nmod_mat_t tmp); /*****************************************************************************/ 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]; 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; } FLINT_DLL void nmod_mpoly_factor_init2(nmod_mpoly_factor_t f, slong alloc, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_factor_realloc(nmod_mpoly_factor_t f, slong alloc, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_factor_fit_length(nmod_mpoly_factor_t f, slong len, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); } NMOD_MPOLY_FACTOR_INLINE 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); } FLINT_DLL void nmod_mpoly_factor_append_ui(nmod_mpoly_factor_t f, const nmod_mpoly_t A, ulong e, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void nmod_mpoly_factor_set(nmod_mpoly_factor_t f, const nmod_mpoly_factor_t g, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_factor_print_pretty(const nmod_mpoly_factor_t f, const char ** vars, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_factor_content(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_factor_squarefree(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_factor_separable(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, int sep); FLINT_DLL int nmod_mpoly_factor(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpoly_factor_sort(nmod_mpoly_factor_t f, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_factor_cmp( const nmod_mpoly_factor_t A, const nmod_mpoly_factor_t B, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL 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; } FLINT_DLL void _nmod_mpoly_get_lead0( nmod_mpoly_t c, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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 ****************************************************************/ FLINT_DLL slong _n_poly_vec_max_degree(const n_poly_struct * A, slong Alen); FLINT_DLL void _n_poly_vec_mul_nmod_intertible(n_poly_struct * A, slong Alen, mp_limb_t c, nmod_t ctx); FLINT_DLL void _n_poly_vec_mod_mul_poly(n_poly_struct * A, slong Alen, const n_poly_t g, const nmod_t ctx); FLINT_DLL void _n_poly_vec_mod_divexact_poly(n_poly_struct * A, slong Alen, const n_poly_t g, nmod_t ctx); FLINT_DLL void _n_poly_vec_mod_content(n_poly_t g, const n_poly_struct * A, slong Alen, nmod_t ctx); FLINT_DLL void _n_poly_vec_mod_remove_content(n_poly_t g, n_poly_struct * A, slong Alen, nmod_t ctx); /* polyun ********************************************************************/ FLINT_DLL void nmod_mpoly_get_polyu1n(n_polyun_t A, const nmod_mpoly_t B, slong varx, slong vary, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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; } FLINT_DLL void nmod_mpolyv_clear(nmod_mpolyv_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyv_print_pretty(const nmod_mpolyv_t poly, const char ** x, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyv_fit_length(nmod_mpolyv_t A, slong length, const nmod_mpoly_ctx_t ctx); FLINT_DLL void nmod_mpolyv_set_coeff(nmod_mpolyv_t A, slong i, nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int _nmod_mpoly_vec_content_mpoly(nmod_mpoly_t g, const nmod_mpoly_struct * A, slong Alen, const nmod_mpoly_ctx_t ctx); FLINT_DLL void _nmod_mpoly_vec_divexact_mpoly(nmod_mpoly_struct * A, slong Alen, const nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); FLINT_DLL void _nmod_mpoly_vec_mul_mpoly(nmod_mpoly_struct * A, slong Alen, const nmod_mpoly_t c, const nmod_mpoly_ctx_t ctx); /*****************************************************************************/ FLINT_DLL int _nmod_mpoly_factor_separable(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, int sep); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL 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); FLINT_DLL 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); /*****************************************************************************/ FLINT_DLL int nmod_mpolyu_is_canonical(const nmod_mpolyu_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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]; FLINT_DLL 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); FLINT_DLL void nmod_mpoly_pfrac_clear(nmod_mpoly_pfrac_t I, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_pfrac(slong r, nmod_mpoly_t t, const slong * deg, nmod_mpoly_pfrac_t I, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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_DLL int nmod_mpoly_factor_algo(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx, unsigned int algo); FLINT_DLL int nmod_mpoly_factor_zassenhaus(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_factor_wang(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL int nmod_mpoly_factor_zippel(nmod_mpoly_factor_t f, const nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 ***********************************************************************/ FLINT_DLL 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_DLL 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 ***************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void n_polyun_zip_start(n_polyun_t Z, n_polyun_t H, slong req_images); FLINT_DLL int n_polyu2n_add_zip_must_match(n_polyun_t Z, const n_bpoly_t A, slong cur_length); FLINT_DLL 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 flint2-2.8.4/nmod_mpoly_factor/000077500000000000000000000000001414523752600164475ustar00rootroot00000000000000flint2-2.8.4/nmod_mpoly_factor/append.c000066400000000000000000000017761414523752600200750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly_factor/clear.c000066400000000000000000000013641414523752600177050ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/nmod_mpoly_factor/cmp.c000066400000000000000000000017351414523752600174000ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly_factor/compression.c000066400000000000000000000060721414523752600211610ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly_factor/eval.c000066400000000000000000000135411414523752600175460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly_factor/expand.c000066400000000000000000000021101414523752600200640ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly_factor/factor.c000066400000000000000000000677551414523752600201150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" #include "fq_nmod_mpoly_factor.h" #include "long_extras.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) { SLONG_SWAP(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); } flint2-2.8.4/nmod_mpoly_factor/factor_content.c000066400000000000000000000115531414523752600216300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 primitve 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--) SLONG_SWAP(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; } flint2-2.8.4/nmod_mpoly_factor/factor_squarefree.c000066400000000000000000000263571414523752600223300ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly_factor/fit_length.c000066400000000000000000000014151414523752600207370ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/nmod_mpoly_factor/gcd_zippel.c000066400000000000000000000631021414523752600207350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_vec.h" #include "fmpz_mod_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--) SLONG_SWAP(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; } flint2-2.8.4/nmod_mpoly_factor/get_set_lead0.c000066400000000000000000000021701414523752600213120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" 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); } flint2-2.8.4/nmod_mpoly_factor/init.c000066400000000000000000000021151414523752600175550ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly_factor/inlines.c000066400000000000000000000011611414523752600202530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #define NMOD_MPOLY_FACTOR_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "nmod_mpoly_factor.h" flint2-2.8.4/nmod_mpoly_factor/irred_lgprime.c000066400000000000000000000222461414523752600214450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_printf("fatal error in _frob_combine"); flint_abort(); } } 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; } flint2-2.8.4/nmod_mpoly_factor/irred_medprime.c000066400000000000000000000221451414523752600216060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_printf("fatal error in _frob_combine"); flint_abort(); } 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; } flint2-2.8.4/nmod_mpoly_factor/irred_smprime_wang.c000066400000000000000000000210661414523752600224750ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly_factor/irred_smprime_zassenhaus.c000066400000000000000000000253461414523752600237320ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_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( 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; } flint2-2.8.4/nmod_mpoly_factor/irred_smprime_zippel.c000066400000000000000000000217441414523752600230470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly_factor/lcc_wang.c000066400000000000000000000077161414523752600204030ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "n_poly.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_div(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; } flint2-2.8.4/nmod_mpoly_factor/mpoly_hlift.c000066400000000000000000000272161414523752600211510ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/nmod_mpoly_factor/mpoly_hlift_zippel.c000066400000000000000000000524041414523752600225310ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 comming 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); ULONG_SWAP(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; } flint2-2.8.4/nmod_mpoly_factor/mpoly_pfrac.c000066400000000000000000000220471414523752600211330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly_factor/mpolyu.c000066400000000000000000000026761414523752600201530ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } 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"); } flint2-2.8.4/nmod_mpoly_factor/mpolyv.c000066400000000000000000000103641414523752600201450ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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"); } } 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); } flint2-2.8.4/nmod_mpoly_factor/n_bpoly_mod.c000066400000000000000000000356201414523752600211220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } } flint2-2.8.4/nmod_mpoly_factor/n_bpoly_mod_factor_lgprime.c000066400000000000000000000567621414523752600242110ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" #include "fq_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); SLONG_SWAP(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); SLONG_SWAP(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; fmpz_t P; 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; fmpz_init_set_ui(P, ctx.n); fq_nmod_ctx_init(ectx, P, 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(ectx, P, 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: fmpz_clear(P); 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; } flint2-2.8.4/nmod_mpoly_factor/n_bpoly_mod_factor_smprime.c000066400000000000000000001266161414523752600242220ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" #include "fq_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); SLONG_SWAP(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); SLONG_SWAP(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_div(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 */ local_fac_tmp->num = 0; 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; } flint2-2.8.4/nmod_mpoly_factor/n_bpoly_mod_hlift.c000066400000000000000000000542451414523752600223140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_div(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_div(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_div(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; } flint2-2.8.4/nmod_mpoly_factor/n_bpoly_mod_pfrac.c000066400000000000000000000265071414523752600223010ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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_div(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_div(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; } flint2-2.8.4/nmod_mpoly_factor/n_poly_vec.c000066400000000000000000000037361414523752600207610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" 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); } flint2-2.8.4/nmod_mpoly_factor/nmod_mat_extras.c000066400000000000000000000041641414523752600220040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_mpoly_factor/polyu3_mod_hlift.c000066400000000000000000000577061414523752600221120ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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--) { MP_LIMB_SWAP(A->coeffs[j - 1], A->coeffs[j]); ULONG_SWAP(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; } flint2-2.8.4/nmod_mpoly_factor/polyun.c000066400000000000000000000050351414523752600201440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/nmod_mpoly_factor/print_pretty.c000066400000000000000000000014461414523752600213630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/nmod_mpoly_factor/profile/000077500000000000000000000000001414523752600201075ustar00rootroot00000000000000flint2-2.8.4/nmod_mpoly_factor/profile/p-factor.c000066400000000000000000007160641414523752600220040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_mpoly_factor.h" #include "profiler.h" 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; } flint2-2.8.4/nmod_mpoly_factor/realloc.c000066400000000000000000000036471414523752600202460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_mpoly_factor/set.c000066400000000000000000000015431414523752600174110ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" 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; } flint2-2.8.4/nmod_mpoly_factor/sort.c000066400000000000000000000034441414523752600176070ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/nmod_mpoly_factor/test/000077500000000000000000000000001414523752600174265ustar00rootroot00000000000000flint2-2.8.4/nmod_mpoly_factor/test/t-factor.c000066400000000000000000000140651414523752600213170ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" /* 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, const char * s) { 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 (!nmod_mpoly_factor(g, p, ctx)) { flint_printf("FAIL: %s\ncheck factorization could be computed\n", s); flint_abort(); } for (i = 0; i < g->num; i++) { if (g->poly[i].length < 1 || g->poly[i].coeffs[0] != 1) { flint_printf("FAIL: %s\nfactorization is not unit normal\n", s); 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: %s\nfactorization has wrong number of factors\n", s); flint_abort(); } nmod_mpoly_factor_expand(q, g, ctx); if (!nmod_mpoly_equal(q, p, ctx)) { flint_printf("FAIL: %s\nfactorization does not match\n", s); 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: %s\nfactor is reducible\n", s); flint_abort(); } } nmod_mpoly_clear(q, ctx); nmod_mpoly_factor_clear(g, ctx); nmod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } int main(void) { slong i, j, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor...."); fflush(stdout); { 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, "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, "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, "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 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); nfacs = 1 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 3 + 100/nfacs/ctx->minfo->nvars/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, "multivariate"); nmod_mpoly_clear(t, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly_factor/test/t-factor_content.c000066400000000000000000000073221414523752600230470ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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"); 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"); 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"); 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"); flint_abort(); } } else { if (!nmod_mpoly_content_vars(q, g->poly + i, &v, 1, ctx)) { flint_printf("FAIL:\ncheck content could be computed\n"); 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"); flint_abort(); } } } } nmod_mpoly_clear(q, ctx); nmod_mpoly_factor_clear(g, ctx); fmpz_clear(deg); } int main(void) { slong i, j, k, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_content...."); fflush(stdout); for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, t; slong 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); nfacs = 5 + (8 + n_randint(state, 8))/ctx->minfo->nvars; 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly_factor/test/t-factor_squarefree.c000066400000000000000000000066241414523752600235430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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"); 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"); 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"); 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"); 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); } int main(void) { slong i, j, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_squarefree...."); fflush(stdout); for (i = 0; i < tmul * flint_test_multiplier(); i++) { nmod_mpoly_ctx_t ctx; nmod_mpoly_t a, t; slong 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); nfacs = 1 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); expbound = 3 + 25/nfacs/ctx->minfo->nvars/powbound; nmod_mpoly_one(a, ctx); for (j = 0; j < nfacs; j++) { len = 1 + n_randint(state, 60/powbound/ctx->minfo->nvars); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly_factor/test/t-factor_wang.c000066400000000000000000000076741414523752600223430ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" /* 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) { 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 (!nmod_mpoly_factor_wang(g, p, ctx)) { flint_printf("FAIL:\nfactorization 1 could be computed\n"); flint_abort(); } if (!nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\nfactorization 2 could be computed\n"); 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"); 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"); 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"); flint_abort(); } 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"); 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"); flint_abort(); } } nmod_mpoly_clear(q, ctx); nmod_mpoly_factor_clear(g, ctx); nmod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } int main(void) { slong i, j, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_wang...."); fflush(stdout); 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; 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); nfacs = 1 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 3 + 20/nfacs/ctx->minfo->nvars/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_clear(t, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly_factor/test/t-factor_zassenhaus.c000066400000000000000000000076751414523752600235740ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" /* 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) { 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 (!nmod_mpoly_factor_zassenhaus(g, p, ctx)) { flint_printf("FAIL:\ncheck factorization 1 could be computed\n"); flint_abort(); } if (!nmod_mpoly_factor(h, p, ctx)) { flint_printf("check factorization 2 could be computed\n"); 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"); 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"); 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"); flint_abort(); } nmod_mpoly_factor_sort(g, ctx); nmod_mpoly_factor_sort(h, ctx); if (nmod_mpoly_factor_cmp(g, h, ctx) != 0) { flint_printf("factorizations do not match\n"); 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"); flint_abort(); } } nmod_mpoly_clear(q, ctx); nmod_mpoly_factor_clear(g, ctx); nmod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } int main(void) { slong i, j, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_zassenhaus...."); fflush(stdout); 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; 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); nfacs = 1 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 3 + 15/nfacs/ctx->minfo->nvars/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_clear(t, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly_factor/test/t-factor_zippel.c000066400000000000000000000076761414523752600227140ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" /* 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) { 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 (!nmod_mpoly_factor_zippel(g, p, ctx)) { flint_printf("FAIL:\nfactorization could be computed\n"); flint_abort(); } if (!nmod_mpoly_factor(h, p, ctx)) { flint_printf("FAIL:\nfactorization 2 could be computed\n"); 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"); 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"); 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"); flint_abort(); } 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"); 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"); flint_abort(); } } nmod_mpoly_clear(q, ctx); nmod_mpoly_factor_clear(g, ctx); nmod_mpoly_factor_clear(h, ctx); fmpz_clear(omega); } int main(void) { slong i, j, tmul = 30; FLINT_TEST_INIT(state); flint_printf("factor_zippel...."); fflush(stdout); 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; 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); nfacs = 1 + (6 + n_randint(state, 6))/ctx->minfo->nvars; powbound = 1 + n_randint(state, 3); powbound = 1 + n_randint(state, powbound); expbound = 2 + 80/nfacs/ctx->minfo->nvars/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_clear(t, ctx); nmod_mpoly_clear(a, ctx); nmod_mpoly_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_mpoly_factor/test/t-gcd_subresultant.c000066400000000000000000000154561414523752600234160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly_factor.h" 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; } 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 15; FLINT_TEST_INIT(state); flint_printf("gcd_subresultant...."); fflush(stdout); 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); 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly_factor/test/t-gcd_zippel.c000066400000000000000000000353241414523752600221620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_mpoly_factor.h" 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"); 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; } 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); 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); 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); 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); 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); 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); 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); flint_abort(); } cleanup: nmod_mpoly_clear(ca, ctx); nmod_mpoly_clear(cb, ctx); nmod_mpoly_clear(cg, ctx); } int main(void) { slong i, j, tmul = 20; FLINT_TEST_INIT(state); flint_printf("gcd_zippel...."); fflush(stdout); { 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); } flint_printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_mpoly_factor/zip_helpers.c000066400000000000000000000202701414523752600211400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/nmod_poly.h000066400000000000000000001636411414523752600151200ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define NMOD_POLY_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "fmpz.h" #include "thread_support.h" #ifdef __cplusplus extern "C" { #endif #define NMOD_DIVREM_DIVCONQUER_CUTOFF 300 #define NMOD_DIV_DIVCONQUER_CUTOFF 300 /* Must be <= NMOD_DIVREM_DIVCONQUER_CUTOFF */ #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 */ NMOD_POLY_INLINE 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); } NMOD_POLY_INLINE slong NMOD_DIV_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 - lenB + 1; else if (bits <= 2 * FLINT_BITS) return 2*lenA; else return 3*lenA; } NMOD_POLY_INLINE slong NMOD_DIVREM_DC_ITCH(slong lenB, nmod_t mod) { slong i = 0; while (lenB > NMOD_DIVREM_DIVCONQUER_CUTOFF + i) { lenB = (lenB + 1)/2; i++; } if (lenB > NMOD_DIVREM_DIVCONQUER_CUTOFF) lenB = NMOD_DIVREM_DIVCONQUER_CUTOFF; return NMOD_DIVREM_BC_ITCH(2*lenB - 1, lenB, mod) + 2*lenB - 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 { 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 ********************************************************/ FLINT_DLL void nmod_poly_init(nmod_poly_t poly, mp_limb_t n); FLINT_DLL void nmod_poly_init_preinv(nmod_poly_t poly, mp_limb_t n, mp_limb_t ninv); FLINT_DLL void nmod_poly_init2(nmod_poly_t poly, mp_limb_t n, slong alloc); FLINT_DLL void nmod_poly_init2_preinv(nmod_poly_t poly, mp_limb_t n, mp_limb_t ninv, slong alloc); FLINT_DLL void nmod_poly_realloc(nmod_poly_t poly, slong alloc); FLINT_DLL void nmod_poly_clear(nmod_poly_t poly); FLINT_DLL 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; } NMOD_POLY_INLINE flint_bitcnt_t nmod_poly_max_bits(const nmod_poly_t poly) { return _nmod_vec_max_bits(poly->coeffs, poly->length); } 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) { slong t; mp_ptr tp; t = poly1->alloc; poly1->alloc = poly2->alloc; poly2->alloc = t; t = poly1->length; poly1->length = poly2->length; poly2->length = t; tp = poly1->coeffs; poly1->coeffs = poly2->coeffs; poly2->coeffs = tp; } 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; } NMOD_POLY_INLINE void nmod_poly_truncate(nmod_poly_t poly, slong len) { if (poly->length > len) { poly->length = len; _nmod_poly_normalise(poly); } } FLINT_DLL void nmod_poly_set_trunc(nmod_poly_t res, const nmod_poly_t poly, slong n); FLINT_DLL void _nmod_poly_reverse(mp_ptr output, mp_srcptr input, slong len, slong m); FLINT_DLL void nmod_poly_reverse(nmod_poly_t output, const nmod_poly_t input, slong m); /* Comparison ***************************************************************/ NMOD_POLY_INLINE 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; } FLINT_DLL 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->length == 1) && (poly->coeffs[0] == 1); } /* Randomisation ************************************************************/ FLINT_DLL 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)); } FLINT_DLL void nmod_poly_randtest_irreducible(nmod_poly_t poly, flint_rand_t state, slong len); FLINT_DLL void nmod_poly_randtest_monic(nmod_poly_t poly, flint_rand_t state, slong len); FLINT_DLL void nmod_poly_randtest_monic_irreducible(nmod_poly_t poly, flint_rand_t state, slong len); FLINT_DLL void nmod_poly_randtest_monic_primitive(nmod_poly_t poly, flint_rand_t state, slong len); FLINT_DLL void nmod_poly_randtest_trinomial(nmod_poly_t poly, flint_rand_t state, slong len); FLINT_DLL int nmod_poly_randtest_trinomial_irreducible(nmod_poly_t poly, flint_rand_t state, slong len, slong max_attempts); FLINT_DLL void nmod_poly_randtest_pentomial(nmod_poly_t poly, flint_rand_t state, slong len); FLINT_DLL int nmod_poly_randtest_pentomial_irreducible(nmod_poly_t poly, flint_rand_t state, slong len, slong max_attempts); FLINT_DLL 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]; } FLINT_DLL void nmod_poly_set_coeff_ui(nmod_poly_t poly, slong j, ulong c); /* Input and output *********************************************************/ FLINT_DLL char * nmod_poly_get_str(const nmod_poly_t poly); FLINT_DLL char * nmod_poly_get_str_pretty(const nmod_poly_t poly, const char * x); FLINT_DLL int nmod_poly_set_str(nmod_poly_t poly, const char * s); FLINT_DLL int nmod_poly_fread(FILE * f, nmod_poly_t poly); NMOD_POLY_INLINE 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; } FLINT_DLL int nmod_poly_fprint_pretty(FILE * f, const nmod_poly_t a, const char * x); NMOD_POLY_INLINE int nmod_poly_print(const nmod_poly_t a) { size_t r; slong i; r = flint_printf("%wd %wu", a->length, a->mod.n); if (a->length == 0) return r; else if (r > 0) r = flint_printf(" "); for (i = 0; (r > 0) && (i < a->length); i++) r = flint_printf(" %wu", a->coeffs[i]); return (int) r; } NMOD_POLY_INLINE int nmod_poly_print_pretty(const nmod_poly_t a, const char * x) { return nmod_poly_fprint_pretty(stdout, a, x); } NMOD_POLY_INLINE int nmod_poly_read(nmod_poly_t poly) { return nmod_poly_fread(stdin, poly); } /* Shifting *****************************************************************/ FLINT_DLL void _nmod_poly_shift_left(mp_ptr res, mp_srcptr poly, slong len, slong k); FLINT_DLL void nmod_poly_shift_left(nmod_poly_t res, const nmod_poly_t poly, slong k); FLINT_DLL void _nmod_poly_shift_right(mp_ptr res, mp_srcptr poly, slong len, slong k); FLINT_DLL void nmod_poly_shift_right(nmod_poly_t res, const nmod_poly_t poly, slong k); /* Addition and subtraction *************************************************/ FLINT_DLL void _nmod_poly_add(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); FLINT_DLL void nmod_poly_add(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); FLINT_DLL void nmod_poly_add_ui(nmod_poly_t res, const nmod_poly_t poly, ulong c); FLINT_DLL void nmod_poly_add_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n); FLINT_DLL void _nmod_poly_sub(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); FLINT_DLL void nmod_poly_sub(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); FLINT_DLL void nmod_poly_sub_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n); FLINT_DLL void nmod_poly_sub_ui(nmod_poly_t res, const nmod_poly_t poly, ulong c); FLINT_DLL void nmod_poly_neg(nmod_poly_t res, const nmod_poly_t poly1); /* Scalar multiplication and division ***************************************/ FLINT_DLL void nmod_poly_scalar_mul_nmod(nmod_poly_t res, const nmod_poly_t poly1, mp_limb_t c); FLINT_DLL void _nmod_poly_make_monic(mp_ptr output, mp_srcptr input, slong len, nmod_t mod); FLINT_DLL void nmod_poly_make_monic(nmod_poly_t output, const nmod_poly_t input); /* Bit packing and unpacking aand reduction **********************************/ FLINT_DLL void _nmod_poly_KS2_pack1(mp_ptr res, mp_srcptr op, slong n, slong s, ulong b, ulong k, slong r); FLINT_DLL void _nmod_poly_KS2_pack(mp_ptr res, mp_srcptr op, slong n, slong s, ulong b, ulong k, slong r); FLINT_DLL void _nmod_poly_KS2_unpack1(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k); FLINT_DLL void _nmod_poly_KS2_unpack2(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k); FLINT_DLL void _nmod_poly_KS2_unpack3(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k); FLINT_DLL void _nmod_poly_KS2_unpack(mp_ptr res, mp_srcptr op, slong n, ulong b, ulong k); FLINT_DLL void _nmod_poly_KS2_reduce(mp_ptr res, slong s, mp_srcptr op, slong n, ulong w, nmod_t mod); FLINT_DLL void _nmod_poly_KS2_recover_reduce1(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod); FLINT_DLL void _nmod_poly_KS2_recover_reduce2(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod); FLINT_DLL void _nmod_poly_KS2_recover_reduce2b(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod); FLINT_DLL void _nmod_poly_KS2_recover_reduce3(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod); FLINT_DLL void _nmod_poly_KS2_recover_reduce(mp_ptr res, slong s, mp_srcptr op1, mp_srcptr op2, slong n, ulong b, nmod_t mod); FLINT_DLL void _nmod_poly_bit_pack(mp_ptr res, mp_srcptr poly, slong len, flint_bitcnt_t bits); FLINT_DLL void _nmod_poly_bit_unpack(mp_ptr res, slong len, mp_srcptr mpn, flint_bitcnt_t bits, nmod_t mod); FLINT_DLL void nmod_poly_bit_pack(fmpz_t f, const nmod_poly_t poly, flint_bitcnt_t bit_size); FLINT_DLL void nmod_poly_bit_unpack(nmod_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size); /* Multiplication ***********************************************************/ FLINT_DLL void _nmod_poly_mul_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); FLINT_DLL void nmod_poly_mul_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); FLINT_DLL void _nmod_poly_mullow_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong trunc, nmod_t mod); FLINT_DLL void nmod_poly_mullow_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong trunc); FLINT_DLL void _nmod_poly_mulhigh_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong start, nmod_t mod); FLINT_DLL void nmod_poly_mulhigh_classical(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong start); FLINT_DLL 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); FLINT_DLL void nmod_poly_mul_KS(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, flint_bitcnt_t bits); FLINT_DLL void _nmod_poly_mul_KS2(mp_ptr res, mp_srcptr op1, slong n1, mp_srcptr op2, slong n2, nmod_t mod); FLINT_DLL void nmod_poly_mul_KS2(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); FLINT_DLL void _nmod_poly_mul_KS4(mp_ptr res, mp_srcptr op1, slong n1, mp_srcptr op2, slong n2, nmod_t mod); FLINT_DLL void nmod_poly_mul_KS4(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _nmod_poly_mul(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); FLINT_DLL void nmod_poly_mul(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); FLINT_DLL void _nmod_poly_mullow(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong trunc, nmod_t mod); FLINT_DLL void nmod_poly_mullow(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong trunc); FLINT_DLL void _nmod_poly_mulhigh(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod); FLINT_DLL void nmod_poly_mulhigh(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n); FLINT_DLL 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); FLINT_DLL void nmod_poly_mulmod(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t f); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int nmod_poly_invmod(nmod_poly_t A, const nmod_poly_t B, const nmod_poly_t P); /* Powering *****************************************************************/ FLINT_DLL void _nmod_poly_pow_binexp(mp_ptr res, mp_srcptr poly, slong len, ulong e, nmod_t mod); FLINT_DLL void nmod_poly_pow_binexp(nmod_poly_t res, const nmod_poly_t poly, ulong e); FLINT_DLL void _nmod_poly_pow(mp_ptr res, mp_srcptr poly, slong len, ulong e, nmod_t mod); FLINT_DLL void nmod_poly_pow(nmod_poly_t res, const nmod_poly_t poly, ulong e); FLINT_DLL void _nmod_poly_pow_trunc_binexp(mp_ptr res, mp_srcptr poly, ulong e, slong trunc, nmod_t mod); FLINT_DLL void nmod_poly_pow_trunc_binexp(nmod_poly_t res, const nmod_poly_t poly, ulong e, slong trunc); FLINT_DLL void _nmod_poly_pow_trunc(mp_ptr res, mp_srcptr poly, ulong e, slong trunc, nmod_t mod); FLINT_DLL void nmod_poly_pow_trunc(nmod_poly_t res, const nmod_poly_t poly, ulong e, slong trunc); FLINT_DLL void nmod_poly_powmod_ui_binexp(nmod_poly_t res, const nmod_poly_t poly, ulong e, const nmod_poly_t f); FLINT_DLL void _nmod_poly_powmod_ui_binexp(mp_ptr res, mp_srcptr poly, ulong e, mp_srcptr f, slong lenf, nmod_t mod); FLINT_DLL void nmod_poly_powmod_fmpz_binexp(nmod_poly_t res, const nmod_poly_t poly, fmpz_t e, const nmod_poly_t f); FLINT_DLL void _nmod_poly_powmod_fmpz_binexp(mp_ptr res, mp_srcptr poly, fmpz_t e, mp_srcptr f, slong lenf, nmod_t mod); FLINT_DLL void _nmod_poly_powmod_mpz_binexp(mp_ptr res, mp_srcptr poly, mpz_srcptr e, mp_srcptr f, slong lenf, nmod_t mod); FLINT_DLL void nmod_poly_powmod_mpz_binexp(nmod_poly_t res, const nmod_poly_t poly, mpz_srcptr e, const nmod_poly_t f); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void nmod_poly_powmod_x_ui_preinv(nmod_poly_t res, ulong e, const nmod_poly_t f, const nmod_poly_t finv); FLINT_DLL void _nmod_poly_powmod_mpz_binexp_preinv (mp_ptr res, mp_srcptr poly, mpz_srcptr e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod); FLINT_DLL void nmod_poly_powmod_mpz_binexp_preinv(nmod_poly_t res, const nmod_poly_t poly, mpz_srcptr e, const nmod_poly_t f, const nmod_poly_t finv); FLINT_DLL 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); FLINT_DLL void nmod_poly_powmod_x_fmpz_preinv(nmod_poly_t res, fmpz_t e, const nmod_poly_t f, const nmod_poly_t finv); FLINT_DLL 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); FLINT_DLL void nmod_poly_powers_mod_naive(nmod_poly_struct * res, const nmod_poly_t f, slong n, const nmod_poly_t g); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void nmod_poly_powers_mod_bsgs(nmod_poly_struct * res, const nmod_poly_t f, slong n, const nmod_poly_t g); /* Division *****************************************************************/ FLINT_DLL void _nmod_poly_divrem_basecase(mp_ptr Q, mp_ptr R, mp_ptr W, mp_srcptr A, slong A_len, mp_srcptr B, slong B_len, nmod_t mod); FLINT_DLL void nmod_poly_divrem_basecase(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL void _nmod_poly_divrem_divconquer_recursive(mp_ptr Q, mp_ptr BQ, mp_ptr W, mp_ptr V, mp_srcptr A, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void _nmod_poly_divrem_divconquer(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void nmod_poly_divrem_divconquer(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL void _nmod_poly_divrem_q0(mp_ptr Q, mp_ptr R, mp_srcptr A, mp_srcptr B, slong lenA, nmod_t mod); FLINT_DLL void _nmod_poly_divrem_q1(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void _nmod_poly_divrem(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void nmod_poly_divrem(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL void _nmod_poly_div_basecase(mp_ptr Q, mp_ptr W, mp_srcptr A, slong A_len, mp_srcptr B, slong B_len, nmod_t mod); FLINT_DLL void nmod_poly_div_basecase(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL void _nmod_poly_div_divconquer_recursive(mp_ptr Q, mp_ptr W, mp_ptr V, mp_srcptr A, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void _nmod_poly_div_divconquer(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void nmod_poly_div_divconquer(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL void _nmod_poly_div(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void nmod_poly_div(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL void _nmod_poly_rem_basecase(mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void nmod_poly_rem_basecase(nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL void _nmod_poly_rem_q1(mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void _nmod_poly_rem(mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void nmod_poly_rem(nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL void _nmod_poly_inv_series_basecase(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod); FLINT_DLL void nmod_poly_inv_series_basecase(nmod_poly_t Qinv, const nmod_poly_t Q, slong n); FLINT_DLL void _nmod_poly_inv_series_newton(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod); FLINT_DLL void nmod_poly_inv_series_newton(nmod_poly_t Qinv, const nmod_poly_t Q, slong n); NMOD_POLY_INLINE void _nmod_poly_inv_series(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod) { _nmod_poly_inv_series_newton(Qinv, Q, Qlen, n, mod); } NMOD_POLY_INLINE void nmod_poly_inv_series(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) { nmod_poly_inv_series_newton(Qinv, Q, n); } FLINT_DLL void _nmod_poly_div_series_basecase(mp_ptr Q, mp_srcptr A, slong Alen, mp_srcptr B, slong Blen, slong n, nmod_t mod); FLINT_DLL void nmod_poly_div_series_basecase(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B, slong n); FLINT_DLL void _nmod_poly_div_series(mp_ptr Q, mp_srcptr A, slong Alen, mp_srcptr B, slong Blen, slong n, nmod_t mod); FLINT_DLL void nmod_poly_div_series(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B, slong n); FLINT_DLL void _nmod_poly_div_newton(mp_ptr Q, mp_srcptr A, slong Alen, mp_srcptr B, slong Blen, nmod_t mod); FLINT_DLL void nmod_poly_div_newton(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL void _nmod_poly_divrem_newton(mp_ptr Q, mp_ptr R, mp_srcptr A, slong Alen, mp_srcptr B, slong Blen, nmod_t mod); FLINT_DLL void nmod_poly_divrem_newton(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL mp_limb_t _nmod_poly_div_root(mp_ptr Q, mp_srcptr A, slong len, mp_limb_t c, nmod_t mod); FLINT_DLL mp_limb_t nmod_poly_div_root(nmod_poly_t Q, const nmod_poly_t A, mp_limb_t c); /* Divisibility testing *****************************************************/ FLINT_DLL int _nmod_poly_divides_classical(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL int nmod_poly_divides_classical(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL int _nmod_poly_divides(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL int nmod_poly_divides(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B); /* Derivative ***************************************************************/ FLINT_DLL void _nmod_poly_derivative(mp_ptr x_prime, mp_srcptr x, slong len, nmod_t mod); FLINT_DLL void nmod_poly_derivative(nmod_poly_t x_prime, const nmod_poly_t x); FLINT_DLL void _nmod_poly_integral(mp_ptr x_int, mp_srcptr x, slong len, nmod_t mod); FLINT_DLL void nmod_poly_integral(nmod_poly_t x_int, const nmod_poly_t x); /* Evaluation ***************************************************************/ FLINT_DLL void _nmod_poly_evaluate_fmpz(fmpz_t rop, mp_srcptr poly, const slong len, const fmpz_t c); FLINT_DLL void nmod_poly_evaluate_fmpz(fmpz_t rop, const nmod_poly_t poly, const fmpz_t c); FLINT_DLL mp_limb_t _nmod_poly_evaluate_nmod(mp_srcptr poly, slong len, mp_limb_t c, nmod_t mod); FLINT_DLL mp_limb_t nmod_poly_evaluate_nmod(const nmod_poly_t poly, mp_limb_t c); FLINT_DLL void _nmod_poly_evaluate_nmod_vec(mp_ptr ys, mp_srcptr coeffs, slong len, mp_srcptr xs, slong n, nmod_t mod); FLINT_DLL void nmod_poly_evaluate_nmod_vec(mp_ptr ys, const nmod_poly_t poly, mp_srcptr xs, slong n); FLINT_DLL void _nmod_poly_evaluate_nmod_vec_iter(mp_ptr ys, mp_srcptr coeffs, slong len, mp_srcptr xs, slong n, nmod_t mod); FLINT_DLL void nmod_poly_evaluate_nmod_vec_iter(mp_ptr ys, const nmod_poly_t poly, mp_srcptr xs, slong n); FLINT_DLL 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); FLINT_DLL void _nmod_poly_evaluate_nmod_vec_fast(mp_ptr ys, mp_srcptr coeffs, slong len, mp_srcptr xs, slong n, nmod_t mod); FLINT_DLL void nmod_poly_evaluate_nmod_vec_fast(mp_ptr ys, const nmod_poly_t poly, mp_srcptr xs, slong n); FLINT_DLL void nmod_mat_one_addmul(nmod_mat_t dest, const nmod_mat_t mat, mp_limb_t c); FLINT_DLL void nmod_poly_evaluate_mat_horner(nmod_mat_t dest, const nmod_poly_t poly, const nmod_mat_t c); FLINT_DLL 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 **********************************************************/ FLINT_DLL mp_ptr * _nmod_poly_tree_alloc(slong len); FLINT_DLL void _nmod_poly_tree_free(mp_ptr * tree, slong len); FLINT_DLL void _nmod_poly_tree_build(mp_ptr * tree, mp_srcptr roots, slong len, nmod_t mod); /* Interpolation ************************************************************/ FLINT_DLL void _nmod_poly_interpolate_nmod_vec_newton(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod); FLINT_DLL void nmod_poly_interpolate_nmod_vec_newton(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n); FLINT_DLL void _nmod_poly_interpolate_nmod_vec_barycentric(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod); FLINT_DLL void nmod_poly_interpolate_nmod_vec_barycentric(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n); FLINT_DLL void _nmod_poly_interpolate_nmod_vec(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod); FLINT_DLL void nmod_poly_interpolate_nmod_vec(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n); FLINT_DLL void nmod_poly_interpolate_nmod_vec_fast(nmod_poly_t poly, mp_srcptr xs, mp_srcptr ys, slong n); FLINT_DLL void _nmod_poly_interpolate_nmod_vec_fast(mp_ptr poly, mp_srcptr xs, mp_srcptr ys, slong len, nmod_t mod); FLINT_DLL 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); FLINT_DLL void _nmod_poly_interpolation_weights(mp_ptr w, const mp_ptr * tree, slong len, nmod_t mod); /* Composition **************************************************************/ FLINT_DLL void _nmod_poly_compose_horner(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); FLINT_DLL void nmod_poly_compose_horner(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); FLINT_DLL void _nmod_poly_compose_divconquer(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); FLINT_DLL void nmod_poly_compose_divconquer(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); FLINT_DLL void _nmod_poly_compose(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); FLINT_DLL void nmod_poly_compose(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2); /* Taylor shift *************************************************************/ FLINT_DLL void _nmod_poly_taylor_shift_horner(mp_ptr poly, mp_limb_t c, slong len, nmod_t mod); FLINT_DLL void nmod_poly_taylor_shift_horner(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c); FLINT_DLL void _nmod_poly_taylor_shift_convolution(mp_ptr poly, mp_limb_t c, slong len, nmod_t mod); FLINT_DLL void nmod_poly_taylor_shift_convolution(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c); FLINT_DLL void _nmod_poly_taylor_shift(mp_ptr poly, mp_limb_t c, slong len, nmod_t mod); FLINT_DLL void nmod_poly_taylor_shift(nmod_poly_t g, const nmod_poly_t f, mp_limb_t c); /* Modular composition ******************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _nmod_poly_reduce_matrix_mod_poly(nmod_mat_t A, const nmod_mat_t B, const nmod_poly_t f); FLINT_DLL 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); FLINT_DLL void _nmod_poly_precompute_matrix_worker(void * arg_ptr); FLINT_DLL void nmod_poly_precompute_matrix(nmod_mat_t A, const nmod_poly_t poly1, const nmod_poly_t poly2, const nmod_poly_t poly2inv); FLINT_DLL 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); FLINT_DLL void _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker(void * arg_ptr); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _nmod_poly_compose_mod_brent_kung_vec_preinv_worker(void * arg_ptr); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void _nmod_poly_compose_mod(mp_ptr res, mp_srcptr f, slong lenf, mp_srcptr g, mp_srcptr h, slong lenh, nmod_t mod); FLINT_DLL 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 ************************************/ FLINT_DLL void _nmod_poly_compose_series_horner(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod); FLINT_DLL void nmod_poly_compose_series_horner(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n); FLINT_DLL void _nmod_poly_compose_series_brent_kung(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod); FLINT_DLL void nmod_poly_compose_series_brent_kung(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n); FLINT_DLL void _nmod_poly_compose_series(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod); FLINT_DLL void nmod_poly_compose_series(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong n); FLINT_DLL void _nmod_poly_revert_series_lagrange(mp_ptr Qinv, mp_srcptr Q, slong n, nmod_t mod); FLINT_DLL void nmod_poly_revert_series_lagrange(nmod_poly_t Qinv, const nmod_poly_t Q, slong n); FLINT_DLL void _nmod_poly_revert_series_lagrange_fast(mp_ptr Qinv, mp_srcptr Q, slong n, nmod_t mod); FLINT_DLL void nmod_poly_revert_series_lagrange_fast(nmod_poly_t Qinv, const nmod_poly_t Q, slong n); FLINT_DLL void _nmod_poly_revert_series_newton(mp_ptr Qinv, mp_srcptr Q, slong n, nmod_t mod); FLINT_DLL void nmod_poly_revert_series_newton(nmod_poly_t Qinv, const nmod_poly_t Q, slong n); FLINT_DLL void _nmod_poly_revert_series(mp_ptr Qinv, mp_srcptr Q, slong n, nmod_t mod); FLINT_DLL void nmod_poly_revert_series(nmod_poly_t Qinv, const nmod_poly_t Q, slong n); FLINT_DLL void _nmod_poly_compose_series_divconquer(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong N, nmod_t mod); FLINT_DLL void nmod_poly_compose_series_divconquer(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong N); /* Greatest common divisor **************************************************/ FLINT_DLL slong _nmod_poly_gcd_euclidean(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void nmod_poly_gcd_euclidean(nmod_poly_t G, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL slong _nmod_poly_gcd_hgcd(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void nmod_poly_gcd_hgcd(nmod_poly_t G, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL slong _nmod_poly_gcd(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL void nmod_poly_gcd(nmod_poly_t G, const nmod_poly_t A, const nmod_poly_t B); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL mp_limb_t _nmod_poly_resultant_euclidean(mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod); FLINT_DLL mp_limb_t nmod_poly_resultant_euclidean(const nmod_poly_t f, const nmod_poly_t g); FLINT_DLL mp_limb_t _nmod_poly_resultant_hgcd(mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod); FLINT_DLL mp_limb_t nmod_poly_resultant_hgcd(const nmod_poly_t A, const nmod_poly_t B); NMOD_POLY_INLINE mp_limb_t _nmod_poly_resultant(mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) { const slong cutoff = FLINT_BIT_COUNT(mod.n) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; if (len1 < cutoff) return _nmod_poly_resultant_euclidean(poly1, len1, poly2, len2, mod); else return _nmod_poly_resultant_hgcd(poly1, len1, poly2, len2, mod); } NMOD_POLY_INLINE mp_limb_t nmod_poly_resultant(const nmod_poly_t f, const nmod_poly_t g) { const slong cutoff = FLINT_BIT_COUNT(f->mod.n) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; if (FLINT_MAX(f->length, g->length) < cutoff) return nmod_poly_resultant_euclidean(f, g); else return nmod_poly_resultant_hgcd(f, g); } FLINT_DLL 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); FLINT_DLL void nmod_poly_gcdinv(nmod_poly_t G, nmod_poly_t S, const nmod_poly_t A, const nmod_poly_t B); /* Discriminant **************************************************************/ FLINT_DLL mp_limb_t _nmod_poly_discriminant(mp_srcptr poly, slong len, nmod_t mod); FLINT_DLL mp_limb_t nmod_poly_discriminant(const nmod_poly_t f); /* Square roots **************************************************************/ FLINT_DLL void _nmod_poly_invsqrt_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); FLINT_DLL void nmod_poly_invsqrt_series(nmod_poly_t g, const nmod_poly_t h, slong n); FLINT_DLL void _nmod_poly_sqrt_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); FLINT_DLL void nmod_poly_sqrt_series(nmod_poly_t g, const nmod_poly_t h, slong n); FLINT_DLL int _nmod_poly_sqrt(mp_ptr s, mp_srcptr p, slong len, nmod_t mod); FLINT_DLL int nmod_poly_sqrt(nmod_poly_t b, const nmod_poly_t a); /* Power sums ****************************************************************/ FLINT_DLL void _nmod_poly_power_sums_naive(mp_ptr res, mp_srcptr poly, slong len, slong n, nmod_t mod); FLINT_DLL void nmod_poly_power_sums_naive(nmod_poly_t res, const nmod_poly_t poly, slong n); FLINT_DLL void _nmod_poly_power_sums_schoenhage(mp_ptr res, mp_srcptr poly, slong len, slong n, nmod_t mod); FLINT_DLL void nmod_poly_power_sums_schoenhage(nmod_poly_t res, const nmod_poly_t poly, slong n); FLINT_DLL void _nmod_poly_power_sums(mp_ptr res, mp_srcptr poly, slong len, slong n, nmod_t mod); FLINT_DLL void nmod_poly_power_sums(nmod_poly_t res, const nmod_poly_t poly, slong n); FLINT_DLL void _nmod_poly_power_sums_to_poly_naive(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod); FLINT_DLL void nmod_poly_power_sums_to_poly_naive(nmod_poly_t res, const nmod_poly_t Q); FLINT_DLL void _nmod_poly_power_sums_to_poly_schoenhage(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod); FLINT_DLL void nmod_poly_power_sums_to_poly_schoenhage(nmod_poly_t res, const nmod_poly_t Q); FLINT_DLL void _nmod_poly_power_sums_to_poly(mp_ptr res, mp_srcptr poly, slong len, nmod_t mod); FLINT_DLL void nmod_poly_power_sums_to_poly(nmod_poly_t res, const nmod_poly_t Q); /* Transcendental functions **************************************************/ FLINT_DLL void _nmod_poly_atan_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); FLINT_DLL void nmod_poly_atan_series(nmod_poly_t g, const nmod_poly_t h, slong n); FLINT_DLL void _nmod_poly_tan_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); FLINT_DLL void nmod_poly_tan_series(nmod_poly_t g, const nmod_poly_t h, slong n); FLINT_DLL void _nmod_poly_asin_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); FLINT_DLL void nmod_poly_asin_series(nmod_poly_t g, const nmod_poly_t h, slong n); FLINT_DLL void _nmod_poly_sin_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); FLINT_DLL void nmod_poly_sin_series(nmod_poly_t g, const nmod_poly_t h, slong n); FLINT_DLL void _nmod_poly_cos_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); FLINT_DLL void nmod_poly_cos_series(nmod_poly_t g, const nmod_poly_t h, slong n); FLINT_DLL void _nmod_poly_asinh_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); FLINT_DLL void nmod_poly_asinh_series(nmod_poly_t g, const nmod_poly_t h, slong n); FLINT_DLL void _nmod_poly_atanh_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); FLINT_DLL void nmod_poly_atanh_series(nmod_poly_t g, const nmod_poly_t h, slong n); FLINT_DLL void _nmod_poly_sinh_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); FLINT_DLL void nmod_poly_sinh_series(nmod_poly_t g, const nmod_poly_t h, slong n); FLINT_DLL void _nmod_poly_cosh_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); FLINT_DLL void nmod_poly_cosh_series(nmod_poly_t g, const nmod_poly_t h, slong n); FLINT_DLL void _nmod_poly_tanh_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod); FLINT_DLL void nmod_poly_tanh_series(nmod_poly_t g, const nmod_poly_t h, slong n); FLINT_DLL void _nmod_poly_log_series_monomial_ui(mp_ptr res, mp_limb_t coeff, ulong power, slong n, nmod_t mod); FLINT_DLL void nmod_poly_log_series_monomial_ui(nmod_poly_t res, mp_limb_t coeff, ulong power, slong n); FLINT_DLL void _nmod_poly_log_series(mp_ptr res, mp_srcptr f, slong flen, slong n, nmod_t mod); FLINT_DLL void nmod_poly_log_series(nmod_poly_t res, const nmod_poly_t f, slong n); FLINT_DLL void _nmod_poly_exp_series_monomial_ui(mp_ptr res, mp_limb_t coeff, ulong power, slong n, nmod_t mod); FLINT_DLL void nmod_poly_exp_series_monomial_ui(nmod_poly_t res, mp_limb_t coeff, ulong power, slong n); FLINT_DLL void _nmod_poly_exp_series_basecase(mp_ptr f, mp_srcptr h, slong hlen, slong n, nmod_t mod); FLINT_DLL void nmod_poly_exp_series_basecase(nmod_poly_t f, const nmod_poly_t h, slong n); FLINT_DLL void _nmod_poly_exp_expinv_series(mp_ptr f, mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod); FLINT_DLL void _nmod_poly_exp_series(mp_ptr f, mp_srcptr h, slong hlen, slong n, nmod_t mod); FLINT_DLL void nmod_poly_exp_series(nmod_poly_t f, const nmod_poly_t h, slong n); /* Products *****************************************************************/ FLINT_DLL void nmod_poly_product_roots_nmod_vec(nmod_poly_t poly, mp_srcptr xs, slong n); FLINT_DLL void _nmod_poly_product_roots_nmod_vec(mp_ptr poly, mp_srcptr xs, slong n, nmod_t mod); FLINT_DLL 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_DLL 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 tempory 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]; FLINT_DLL void nmod_poly_multi_crt_init(nmod_poly_multi_crt_t CRT); FLINT_DLL int nmod_poly_multi_crt_precompute(nmod_poly_multi_crt_t CRT, const nmod_poly_struct * moduli, slong len); FLINT_DLL int nmod_poly_multi_crt_precompute_p(nmod_poly_multi_crt_t CRT, const nmod_poly_struct * const * moduli, slong len); FLINT_DLL void nmod_poly_multi_crt_precomp(nmod_poly_t output, const nmod_poly_multi_crt_t CRT, const nmod_poly_struct * values); FLINT_DLL void nmod_poly_multi_crt_precomp_p(nmod_poly_t output, const nmod_poly_multi_crt_t CRT, const nmod_poly_struct * const * values); FLINT_DLL int nmod_poly_multi_crt(nmod_poly_t output, const nmod_poly_struct * moduli, const nmod_poly_struct * values, slong len); FLINT_DLL 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; } FLINT_DLL void _nmod_poly_multi_crt_run(nmod_poly_struct * outputs, const nmod_poly_multi_crt_t CRT, const nmod_poly_struct * inputs); FLINT_DLL 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 ***************************************************/ FLINT_DLL ulong nmod_poly_deflation(const nmod_poly_t input); FLINT_DLL void nmod_poly_deflate(nmod_poly_t result, const nmod_poly_t input, ulong deflation); FLINT_DLL void nmod_poly_inflate(nmod_poly_t result, const nmod_poly_t input, ulong inflation); /* Characteristic polynomial and minimal polynomial */ FLINT_DLL void _nmod_mat_charpoly_berkowitz(mp_ptr p, const nmod_mat_t M, nmod_t mod); FLINT_DLL void nmod_mat_charpoly_berkowitz(nmod_poly_t p, const nmod_mat_t M); FLINT_DLL void nmod_mat_charpoly_danilevsky(nmod_poly_t p, const nmod_mat_t M); FLINT_DLL void nmod_mat_charpoly(nmod_poly_t p, const nmod_mat_t M); FLINT_DLL void nmod_mat_minpoly_with_gens(nmod_poly_t p, const nmod_mat_t X, ulong * P); FLINT_DLL 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]; FLINT_DLL void nmod_berlekamp_massey_init( nmod_berlekamp_massey_t B, mp_limb_t p); FLINT_DLL void nmod_berlekamp_massey_start_over( nmod_berlekamp_massey_t B); FLINT_DLL void nmod_berlekamp_massey_clear( nmod_berlekamp_massey_t B); FLINT_DLL void nmod_berlekamp_massey_set_prime( nmod_berlekamp_massey_t B, mp_limb_t p); FLINT_DLL void nmod_berlekamp_massey_print( const nmod_berlekamp_massey_t B); FLINT_DLL void nmod_berlekamp_massey_add_points( nmod_berlekamp_massey_t B, const mp_limb_t * a, slong count); FLINT_DLL void nmod_berlekamp_massey_add_zeros( nmod_berlekamp_massey_t B, slong count); FLINT_DLL void nmod_berlekamp_massey_add_point( nmod_berlekamp_massey_t B, mp_limb_t a); FLINT_DLL 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 #include "nmod_poly_factor.h" #endif flint2-2.8.4/nmod_poly/000077500000000000000000000000001414523752600147345ustar00rootroot00000000000000flint2-2.8.4/nmod_poly/KS2_pack.c000066400000000000000000000064641414523752600165070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #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; } } flint2-2.8.4/nmod_poly/KS2_reduce.c000066400000000000000000000125371414523752600170360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.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); } flint2-2.8.4/nmod_poly/KS2_unpack.c000066400000000000000000000136101414523752600170410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #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); } flint2-2.8.4/nmod_poly/add.c000066400000000000000000000026531414523752600156360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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 */ } flint2-2.8.4/nmod_poly/add_series.c000066400000000000000000000021231414523752600172000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #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); } flint2-2.8.4/nmod_poly/add_ui.c000066400000000000000000000017751414523752600163370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/nmod_poly/asin_series.c000066400000000000000000000034321414523752600174060ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_asin_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); /* asin(h(x)) = integral(h'(x)/sqrt(1-h(x)^2)) */ _nmod_poly_mullow(u, h, n, h, n, n, mod); _nmod_vec_neg(u, u, n, mod); u[0] = UWORD(1); _nmod_poly_invsqrt_series(t, u, n, mod); _nmod_poly_derivative(u, h, n, mod); u[n-1] = UWORD(0); _nmod_poly_mullow(g, t, n, u, n, n, mod); _nmod_poly_integral(g, g, n, mod); _nmod_vec_clear(t); _nmod_vec_clear(u); } void nmod_poly_asin_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_printf("Exception (nmod_poly_asin_series). Constant term != 0.\n"); flint_abort(); } 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_asin_series(g->coeffs, h_coeffs, n, h->mod); if (h_len < n) _nmod_vec_clear(h_coeffs); g->length = n; _nmod_poly_normalise(g); } flint2-2.8.4/nmod_poly/asinh_series.c000066400000000000000000000033761414523752600175650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_asinh_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); /* asinh(h(x)) = integral(h'(x)/sqrt(1+h(x)^2)) */ _nmod_poly_mullow(u, h, n, h, n, n, mod); u[0] = UWORD(1); _nmod_poly_invsqrt_series(t, u, n, mod); _nmod_poly_derivative(u, h, n, mod); u[n-1] = UWORD(0); _nmod_poly_mullow(g, t, n, u, n, n, mod); _nmod_poly_integral(g, g, n, mod); _nmod_vec_clear(t); _nmod_vec_clear(u); } void nmod_poly_asinh_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_printf("Exception (nmod_poly_asinh_series). Constant term != 0.\n"); flint_abort(); } 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_asinh_series(g->coeffs, h_coeffs, n, h->mod); if (h_len < n) _nmod_vec_clear(h_coeffs); g->length = n; _nmod_poly_normalise(g); } flint2-2.8.4/nmod_poly/atan_series.c000066400000000000000000000033471414523752600174040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" /* todo: handle short h */ void _nmod_poly_atan_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); /* atan(h(x)) = integral(h'(x)/(1+h(x)^2)) */ _nmod_poly_mullow(u, h, n, h, n, n, mod); u[0] = UWORD(1); _nmod_poly_derivative(t, h, n, mod); t[n-1] = UWORD(0); _nmod_poly_div_series(g, t, n, u, n, n, mod); _nmod_poly_integral(g, g, n, mod); _nmod_vec_clear(t); _nmod_vec_clear(u); } void nmod_poly_atan_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_printf("Exception (nmod_poly_atan_series): Constant term != 0.\n"); flint_abort(); } 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_atan_series(g->coeffs, h_coeffs, n, h->mod); if (h_len < n) _nmod_vec_clear(h_coeffs); g->length = n; _nmod_poly_normalise(g); } flint2-2.8.4/nmod_poly/atanh_series.c000066400000000000000000000034151414523752600175500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" /* todo: handle short h */ void _nmod_poly_atanh_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); /* atanh(h(x)) = integral(h'(x)/(1-h(x)^2)) */ _nmod_poly_mullow(u, h, n, h, n, n, mod); _nmod_vec_neg(u, u, n, mod); u[0] = UWORD(1); _nmod_poly_derivative(t, h, n, mod); t[n-1] = UWORD(0); _nmod_poly_div_series(g, t, n, u, n, n, mod); _nmod_poly_integral(g, g, n, mod); _nmod_vec_clear(t); _nmod_vec_clear(u); } void nmod_poly_atanh_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_printf("Exception (nmod_poly_atanh_series): Constant term != 0.\n"); flint_abort(); } 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_atanh_series(g->coeffs, h_coeffs, n, h->mod); if (h_len < n) _nmod_vec_clear(h_coeffs); g->length = n; _nmod_poly_normalise(g); } flint2-2.8.4/nmod_poly/berlekamp_massey.c000066400000000000000000000211221414523752600204210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "mpn_extras.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; } flint2-2.8.4/nmod_poly/bit_pack.c000066400000000000000000000103131414523752600166520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #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 accross 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 accross 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); } flint2-2.8.4/nmod_poly/bit_unpack.c000066400000000000000000000157651414523752600172350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.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_printf("Exception (nmod_poly_bit_unpack). f < 0.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/clear.c000066400000000000000000000011571414523752600161720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" void nmod_poly_clear(nmod_poly_t poly) { if (poly->coeffs) flint_free(poly->coeffs); } flint2-2.8.4/nmod_poly/compose.c000066400000000000000000000040611414523752600165460ustar00rootroot00000000000000/* Copyright (C) 2010 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_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 _nmod_poly_compose_divconquer(res, poly1, len1, poly2, len2, mod); } 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_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); } } flint2-2.8.4/nmod_poly/compose_divconquer.c000066400000000000000000000155021414523752600210070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_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 _nmod_poly_compose_divconquer(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, nmod_t mod) { slong i, j, k, n; slong * hlen, alloc, powlen; mp_ptr v, * h, pow, temp; if (len1 == 1) { res[0] = poly1[0]; return; } if (len2 == 1) { res[0] = _nmod_poly_evaluate_nmod(poly1, len1, poly2[0], mod); return; } if (len1 == 2) { _nmod_poly_compose_horner(res, poly1, len1, poly2, len2, mod); return; } /* 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]; v = _nmod_vec_init(alloc + 2 * powlen); h = (mp_ptr *) flint_malloc(((len1 + 1) / 2) * sizeof(mp_ptr)); 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)) { _nmod_vec_scalar_mul_nmod(h[i], poly2, len2, poly1[j + 1], mod); h[i][0] = n_addmod(h[i][0], poly1[j], mod.n); hlen[i] = len2; } else if (poly1[j] != WORD(0)) { h[i][0] = poly1[j]; hlen[i] = 1; } } if ((len1 & WORD(1))) { if (poly1[j] != WORD(0)) { h[i][0] = poly1[j]; hlen[i] = 1; } } _nmod_poly_mul(pow, poly2, len2, poly2, len2, mod); 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; _nmod_poly_mul(temp, pow, powlen, h[1], hlen[1], mod); _nmod_poly_add(h[0], temp, templen, h[0], hlen[0], mod); hlen[0] = FLINT_MAX(hlen[0], templen); } for (i = 1; i < n / 2; i++) { if (hlen[2*i + 1] > 0) { _nmod_poly_mul(h[i], pow, powlen, h[2*i + 1], hlen[2*i + 1], mod); hlen[i] = hlen[2*i + 1] + powlen - 1; } else hlen[i] = 0; _nmod_poly_add(h[i], h[i], hlen[i], h[2*i], hlen[2*i], mod); hlen[i] = FLINT_MAX(hlen[i], hlen[2*i]); } if ((n & WORD(1))) { flint_mpn_copyi(h[i], h[2*i], hlen[2*i]); hlen[i] = hlen[2*i]; } _nmod_poly_mul(temp, pow, powlen, pow, powlen, mod); powlen += powlen - 1; { mp_ptr t = pow; pow = temp; temp = t; } } _nmod_poly_mul(res, pow, powlen, h[1], hlen[1], mod); _nmod_vec_add(res, res, h[0], hlen[0], mod); _nmod_vec_clear(v); flint_free(h); flint_free(hlen); } void nmod_poly_compose_divconquer(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); } } flint2-2.8.4/nmod_poly/compose_horner.c000066400000000000000000000056761414523752600201400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "ulong_extras.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_limb_t *t, *t1, *t2; t = _nmod_vec_init(alloc); 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; MP_PTR_SWAP(t1, t2); t1[0] = n_addmod(t1[0], poly1[i], mod.n); } _nmod_vec_clear(t); } } 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); } } flint2-2.8.4/nmod_poly/compose_mod.c000066400000000000000000000042521414523752600174070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.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_printf("Exception (nmod_poly_compose_mod). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/compose_mod_brent_kung.c000066400000000000000000000073411414523752600216270ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "ulong_extras.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_printf("Exception (nmod_poly_compose_mod_brent_kung). Division by zero.\n"); flint_abort(); } if (len1 >= len3) { flint_printf("Exception (nmod_poly_compose_brent_kung). The degree of the \n" "first polynomial must be smaller than that of the modulus.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000132171414523752600247360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "ulong_extras.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_printf("Exception (nmod_poly_precompute_matrix). Division by zero.\n"); flint_abort(); } if (A->r != m || A->c != len) { flint_printf("Exception (nmod_poly_precompute_matrix). Wrong dimensions.\n"); flint_abort(); } 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_printf("Exception (nmod_poly_compose_mod_brent_kung_precomp_preinv). Division by zero.\n"); flint_abort(); } if (len1 >= len3) { flint_printf("Exception (nmod_poly_compose_mod_brent_kung_precomp_preinv). The degree of the \n" "first polynomial must be smaller than that of the modulus.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/compose_mod_brent_kung_preinv.c000066400000000000000000000102111414523752600232000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "ulong_extras.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_printf("Exception (nmod_poly_compose_mod_brent_kung_preinv). Division by zero.\n"); flint_abort(); } if (len1 >= len3) { flint_printf("Exception (nmod_poly_compose_mod_brent_kung_preinv). The degree of the \n" "first polynomial must be smaller than that of the modulus.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/compose_mod_brent_kung_vec_preinv.c000066400000000000000000000111411414523752600240400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "ulong_extras.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_printf("Exception (nmod_poly_compose_mod_brent_kung_vec_preinv)." "The degree of the first polynomial must be smaller than that of the " " modulus\n"); flint_abort(); } } if (n > len1) { flint_printf("Exception (nmod_poly_compose_mod_brent_kung_vec_preinv)." "n is larger than the length of polys\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/compose_mod_brent_kung_vec_preinv_threaded.c000066400000000000000000000234251414523752600257100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #if FLINT_USES_PTHREAD #include #endif #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "thread_support.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_printf ("Exception (nmod_poly_compose_mod_brent_kung_vec_preinv_threaded)." "The degree of the first polynomial must be smaller than that of the " " modulus\n"); flint_abort(); } } if (n > len1) { flint_printf ("Exception (nmod_poly_compose_mod_brent_kung_vec_preinv_threaded)." "n is larger than the length of polys\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/compose_mod_horner.c000066400000000000000000000052061414523752600207640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.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_printf("Exception (nmod_poly_compose_mod_horner). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/compose_series.c000066400000000000000000000047251414523752600201270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_compose_series(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod) { if (len1 < 24 || len2 < 8) _nmod_poly_compose_series_horner(res, poly1, len1, poly2, len2, n, mod); else _nmod_poly_compose_series_brent_kung(res, poly1, len1, poly2, len2, n, mod); } 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_printf("Exception (nmod_poly_compose_series). Inner polynomial \n" "must have zero constant term.\n"); flint_abort(); } 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); } } flint2-2.8.4/nmod_poly/compose_series_brent_kung.c000066400000000000000000000065601414523752600223440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" #include "ulong_extras.h" void _nmod_poly_compose_series_brent_kung(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod) { nmod_mat_t A, B, C; mp_ptr t, h; slong i, m; if (n == 1) { res[0] = poly1[0]; 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, len2); for (i = 2; i < m; i++) _nmod_poly_mullow(A->rows[i], A->rows[i-1], n, poly2, len2, n, 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_mullow(h, A->rows[m - 1], n, poly2, len2, n, mod); for (i = m - 2; i >= 0; i--) { _nmod_poly_mullow(t, res, n, h, n, n, 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_series_brent_kung(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_printf("Exception (nmod_poly_compose_series_brent_kung). Inner \n" "polynomial must have zero constant term.\n"); flint_abort(); } 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_brent_kung(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_brent_kung(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); } } flint2-2.8.4/nmod_poly/compose_series_divconquer.c000066400000000000000000000126571414523752600223710ustar00rootroot00000000000000/* Copyright (C) 2010, 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" /* See fmpz_poly/compose_divconquer.c */ void _nmod_poly_compose_series_divconquer(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong N, nmod_t mod) { slong i, j, k, n; slong *hlen, alloc, powlen; mp_ptr v, *h, pow, temp; if (len1 == 1) { res[0] = poly1[0]; return; } if (len2 == 1) { res[0] = _nmod_poly_evaluate_nmod(poly1, len1, poly2[0], mod); return; } if (len1 == 2) { mp_limb_t t = poly1[0]; _nmod_vec_scalar_mul_nmod(res, poly2, len2, poly1[1], mod); res[0] = n_addmod(res[0], t, mod.n); return; } /* 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]; v = _nmod_vec_init(alloc + 2 * powlen); h = (mp_ptr *) flint_malloc(((len1 + 1) / 2) * sizeof(mp_ptr)); 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)) { _nmod_vec_scalar_mul_nmod(h[i], poly2, len2, poly1[j + 1], mod); h[i][0] = n_addmod(h[i][0], poly1[j], mod.n); hlen[i] = len2; } else if (poly1[j] != WORD(0)) { h[i][0] = poly1[j]; hlen[i] = 1; } } if ((len1 & WORD(1))) { if (poly1[j] != WORD(0)) { h[i][0] = poly1[j]; hlen[i] = 1; } } powlen = FLINT_MIN(N, 2 * len2 - 1); _nmod_poly_mullow(pow, poly2, len2, poly2, len2, powlen, mod); for (n = (len1 + 1) / 2; n > 2; n = (n + 1) / 2) { if (hlen[1] > 0) { slong templen = FLINT_MIN(N, powlen + hlen[1] - 1); _nmod_poly_mullow(temp, pow, powlen, h[1], hlen[1], templen, mod); _nmod_poly_add(h[0], temp, templen, h[0], hlen[0], mod); 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); _nmod_poly_mullow(h[i], pow, powlen, h[2*i + 1], hlen[2*i + 1], hlen[i], mod); } else { hlen[i] = 0; } _nmod_poly_add(h[i], h[i], hlen[i], h[2*i], hlen[2*i], mod); hlen[i] = FLINT_MAX(hlen[i], hlen[2*i]); } if ((n & WORD(1))) { hlen[i] = FLINT_MIN(N, hlen[2*i]); flint_mpn_copyi(h[i], h[2*i], hlen[i]); } _nmod_poly_mullow(temp, pow, powlen, pow, powlen, FLINT_MIN(N, 2 * powlen - 1), mod); powlen = FLINT_MIN(N, 2 * powlen - 1); { mp_ptr t = pow; pow = temp; temp = t; } } _nmod_poly_mullow(res, pow, powlen, h[1], hlen[1], FLINT_MIN(N, powlen + hlen[1] - 1), mod); _nmod_vec_add(res, res, h[0], hlen[0], mod); _nmod_vec_clear(v); flint_free(h); flint_free(hlen); } void nmod_poly_compose_series_divconquer(nmod_poly_t res, const nmod_poly_t poly1, const nmod_poly_t poly2, slong N) { const slong len1 = poly1->length; const slong len2 = FLINT_MIN(N, poly2->length); slong lenr; if (len1 == 0 || N == 0) { nmod_poly_zero(res); return; } if (len1 == 1 || len2 == 0) { nmod_poly_set_coeff_ui(res, 0, poly1->coeffs[0]); nmod_poly_truncate(res, 1); return; } lenr = FLINT_MIN(N, (len1 - 1) * (len2 - 1) + 1); if (res != poly1 && res != poly2) { nmod_poly_fit_length(res, lenr); _nmod_poly_compose_series_divconquer(res->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, N, poly1->mod); } else { nmod_poly_t t; nmod_poly_init2(t, poly1->mod.n, lenr); _nmod_poly_compose_series_divconquer(t->coeffs, poly1->coeffs, len1, poly2->coeffs, len2, N, poly1->mod); nmod_poly_swap(res, t); nmod_poly_clear(t); } res->length = lenr; _nmod_poly_normalise(res); } flint2-2.8.4/nmod_poly/compose_series_horner.c000066400000000000000000000057661414523752600215120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_compose_series_horner(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong n, nmod_t mod) { if (n == 1) { res[0] = poly1[0]; } else { slong i = len1 - 1; slong lenr; mp_ptr t = _nmod_vec_init(n); lenr = len2; _nmod_vec_scalar_mul_nmod(res, poly2, len2, poly1[i], mod); i--; res[0] = nmod_add(res[0], poly1[i], mod); while (i > 0) { i--; if (lenr + len2 - 1 < n) { _nmod_poly_mul(t, res, lenr, poly2, len2, mod); lenr = lenr + len2 - 1; } else { _nmod_poly_mullow(t, res, lenr, poly2, len2, n, mod); lenr = n; } _nmod_poly_add(res, t, lenr, poly1 + i, 1, mod); } _nmod_vec_zero(res + lenr, n - lenr); _nmod_vec_clear(t); } } void nmod_poly_compose_series_horner(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_printf("Exception (nmod_poly_compose_series_horner). Inner polynomial " "must have zero constant term.\n"); flint_abort(); } 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_horner(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_horner(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); } } flint2-2.8.4/nmod_poly/cos_series.c000066400000000000000000000035101414523752600172350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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, 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_printf("Exception (nmod_poly_cos_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/cosh_series.c000066400000000000000000000036651414523752600174200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf("Exception (nmod_poly_cosh_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/deflate.c000066400000000000000000000021131414523752600165010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" void nmod_poly_deflate(nmod_poly_t result, const nmod_poly_t input, ulong deflation) { slong res_length, i; if (deflation == 0) { flint_printf("Exception (nmod_poly_deflate). Division by zero.\n"); flint_abort(); } 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; } flint2-2.8.4/nmod_poly/deflation.c000066400000000000000000000021271414523752600170470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.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; } flint2-2.8.4/nmod_poly/derivative.c000066400000000000000000000022101414523752600172350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/nmod_poly/discriminant.c000066400000000000000000000025271414523752600175720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "mpn_extras.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); } flint2-2.8.4/nmod_poly/div.c000066400000000000000000000041571414523752600156710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_div(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { TMP_INIT; if (lenB < 15) { mp_ptr W; TMP_START; W = TMP_ALLOC(NMOD_DIV_BC_ITCH(lenA, lenB, mod)*sizeof(mp_limb_t)); _nmod_poly_div_basecase(Q, W, A, lenA, B, lenB, mod); TMP_END; } else if (lenB < 6000) _nmod_poly_div_divconquer(Q, A, lenA, B, lenB, mod); else _nmod_poly_div_newton(Q, A, lenA, B, lenB, mod); } 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_printf("Exception (nmod_poly_divrem). Division by zero.\n"); flint_abort(); } } 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; } flint2-2.8.4/nmod_poly/div_basecase.c000066400000000000000000000145611414523752600175170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_div_basecase_1(mp_ptr Q, mp_ptr W, mp_srcptr A, slong A_len, mp_srcptr B, slong B_len, nmod_t mod) { mp_limb_t lead_inv = n_invmod(B[B_len - 1], mod.n); slong len, coeff = A_len - B_len; mp_ptr R1 = W; mp_srcptr Btop = B + B_len - 1; flint_mpn_copyi(R1, A + B_len - 1, A_len - B_len + 1); while (coeff >= 0) { R1[coeff] = n_mod2_preinv(R1[coeff], mod.n, mod.ninv); while (coeff >= 0 && R1[coeff] == WORD(0)) { Q[coeff--] = WORD(0); if (coeff >= 0) R1[coeff] = n_mod2_preinv(R1[coeff], mod.n, mod.ninv); } if (coeff >= 0) { mp_limb_t c, * R_sub; Q[coeff] = n_mulmod2_preinv(R1[coeff], lead_inv, mod.n, mod.ninv); c = n_negmod(Q[coeff], mod.n); len = FLINT_MIN(B_len - 1, coeff); R_sub = R1 + coeff - len; if (len > 0) mpn_addmul_1(R_sub, Btop - len, len, c); coeff--; } } } void _nmod_poly_div_basecase_2(mp_ptr Q, mp_ptr W, mp_srcptr A, slong A_len, mp_srcptr B, slong B_len, nmod_t mod) { slong coeff, i, len; mp_limb_t lead_inv = n_invmod(B[B_len - 1], mod.n); mp_ptr B2, R2; mp_srcptr Btop; B2 = W; for (i = 0; i < B_len - 1; i++) { B2[2 * i] = B[i]; B2[2 * i + 1] = 0; } Btop = B2 + 2*(B_len - 1); R2 = W + 2*(B_len - 1); for (i = 0; i < A_len - B_len + 1; i++) { R2[2 * i] = A[B_len + i - 1]; R2[2 * i + 1] = 0; } coeff = A_len - B_len; while (coeff >= 0) { mp_limb_t r_coeff; r_coeff = n_ll_mod_preinv(R2[2 * coeff + 1], R2[2 * coeff], mod.n, mod.ninv); while (coeff >= 0 && r_coeff == WORD(0)) { Q[coeff--] = WORD(0); if (coeff >= 0) r_coeff = n_ll_mod_preinv(R2[2 * coeff + 1], R2[2 * coeff], mod.n, mod.ninv); } if (coeff >= 0) { mp_limb_t c, * R_sub; Q[coeff] = n_mulmod2_preinv(r_coeff, lead_inv, mod.n, mod.ninv); c = n_negmod(Q[coeff], mod.n); len = FLINT_MIN(B_len - 1, coeff); R_sub = R2 + 2 * (coeff - len); if (len > 0) mpn_addmul_1(R_sub, Btop - 2*len, 2 * len, c); coeff--; } } } void _nmod_poly_div_basecase_3(mp_ptr Q, mp_ptr W, mp_srcptr A, slong A_len, mp_srcptr B, slong B_len, nmod_t mod) { slong coeff, i, len; mp_limb_t lead_inv = n_invmod(B[B_len - 1], mod.n); mp_limb_t r_coeff; mp_ptr B3, R3; mp_srcptr Btop; B3 = W; for (i = 0; i < B_len - 1; i++) { B3[3 * i] = B[i]; B3[3 * i + 1] = 0; B3[3 * i + 2] = 0; } Btop = B3 + 3*(B_len - 1); R3 = W + 3*(B_len - 1); for (i = 0; i < A_len - B_len + 1; i++) { R3[3 * i] = A[B_len + i - 1]; R3[3 * i + 1] = 0; R3[3 * i + 2] = 0; } coeff = A_len - B_len; while (coeff >= 0) { r_coeff = n_lll_mod_preinv(R3[3 * coeff + 2], R3[3 * coeff + 1], R3[3 * coeff], mod.n, mod.ninv); while (coeff >= 0 && r_coeff == WORD(0)) { Q[coeff--] = WORD(0); if (coeff >= 0) r_coeff = n_lll_mod_preinv(R3[3 * coeff + 2], R3[3 * coeff + 1], R3[3 * coeff], mod.n, mod.ninv); } if (coeff >= 0) { mp_limb_t c, * R_sub; Q[coeff] = n_mulmod2_preinv(r_coeff, lead_inv, mod.n, mod.ninv); c = n_negmod(Q[coeff], mod.n); len = FLINT_MIN(B_len - 1, coeff); R_sub = R3 + 3 * (coeff - len); if (len > 0) mpn_addmul_1(R_sub, Btop - 3*len, 3 * len, c); coeff--; } } } void _nmod_poly_div_basecase(mp_ptr Q, mp_ptr W, mp_srcptr A, slong A_len, mp_srcptr B, slong B_len, nmod_t mod) { slong bits = 2 * (FLINT_BITS - mod.norm) + FLINT_BIT_COUNT(A_len - B_len + 1); if (bits <= FLINT_BITS) _nmod_poly_div_basecase_1(Q, W, A, A_len, B, B_len, mod); else if (bits <= 2 * FLINT_BITS) _nmod_poly_div_basecase_2(Q, W, A, A_len, B, B_len, mod); else _nmod_poly_div_basecase_3(Q, W, A, A_len, B, B_len, mod); } void nmod_poly_div_basecase(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) { mp_ptr Q_coeffs, W; nmod_poly_t t1; slong Alen, Blen; TMP_INIT; Blen = B->length; if (Blen == 0) { if (nmod_poly_modulus(B) == 1) { nmod_poly_set(Q, A); return; } else { flint_printf("Exception (nmod_poly_div_basecase). Division by zero.\n"); flint_abort(); } } Alen = A->length; if (Alen < Blen) { nmod_poly_zero(Q); return; } if (Q == A || Q == B) { nmod_poly_init2_preinv(t1, B->mod.n, B->mod.ninv, Alen - Blen + 1); Q_coeffs = t1->coeffs; } else { nmod_poly_fit_length(Q, Alen - Blen + 1); Q_coeffs = Q->coeffs; } TMP_START; W = TMP_ALLOC(NMOD_DIV_BC_ITCH(Alen, Blen, A->mod)*sizeof(mp_limb_t)); _nmod_poly_div_basecase(Q_coeffs, W, A->coeffs, Alen, B->coeffs, Blen, B->mod); if (Q == A || Q == B) { nmod_poly_swap(Q, t1); nmod_poly_clear(t1); } Q->length = Alen - Blen + 1; TMP_END; _nmod_poly_normalise(Q); } flint2-2.8.4/nmod_poly/div_divconquer.c000066400000000000000000000073321414523752600201260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" static void __nmod_poly_div_divconquer(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { 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; mp_srcptr p1 = A + n2; mp_srcptr d1 = B + n2; mp_ptr V = _nmod_vec_init(n1 - 1 + NMOD_DIVREM_DC_ITCH(n1, mod)); mp_ptr W = V + NMOD_DIVREM_DC_ITCH(n1, mod); _nmod_poly_div_divconquer_recursive(Q, W, V, p1, d1, n1, mod); _nmod_vec_clear(V); } else /* lenA = 2 * lenB - 1 */ { mp_ptr V = _nmod_vec_init(lenB - 1 + NMOD_DIVREM_DC_ITCH(lenB, mod)); mp_ptr W = V + NMOD_DIVREM_DC_ITCH(lenB, mod); _nmod_poly_div_divconquer_recursive(Q, W, V, A, B, lenB, mod); _nmod_vec_clear(V); } } /* needed due to partial overlap */ static void _nmod_vec_sub_dec(mp_ptr a, mp_srcptr b, mp_srcptr c, slong n, nmod_t mod) { slong i; for (i = n - 1; i >= 0; i--) a[i] = n_submod(b[i], c[i], mod.n); } void _nmod_poly_div_divconquer(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { if (lenA <= 2 * lenB - 1) { __nmod_poly_div_divconquer(Q, A, lenA, B, lenB, mod); } else /* lenA > 2 * lenB - 1 */ { mp_ptr S, T, V, R; slong shift, next, n = 2 * lenB - 1; S = _nmod_vec_init(2 * n + (lenB - 1) + NMOD_DIVREM_DC_ITCH(lenB, mod)); T = S + n; R = T + n; V = R + (lenB - 1); shift = lenA - n; _nmod_vec_set(S, A + shift, n); while (lenA >= n) { shift = lenA - n; _nmod_poly_divrem_divconquer_recursive(Q + shift, T, R, V, S, B, lenB, mod); next = FLINT_MIN(lenB, shift); _nmod_vec_sub_dec(S + next, S, T, lenB - 1, mod); _nmod_vec_set(S, A + shift - next, next); lenA -= lenB; } if (lenA >= lenB) __nmod_poly_div_divconquer(Q, S, lenA, B, lenB, mod); _nmod_vec_clear(S); } } void nmod_poly_div_divconquer(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) { nmod_poly_t tQ; mp_ptr q; slong Alen, Blen; Blen = B->length; if (Blen == 0) { if (nmod_poly_modulus(B) == 1) { nmod_poly_set(Q, A); return; } else { flint_printf("Exception (nmod_poly_div_divconquer). Division by zero.\n"); flint_abort(); } } Alen = A->length; if (Alen < Blen) { nmod_poly_zero(Q); return; } if (Q == A || Q == B) { nmod_poly_init2(tQ, A->mod.n, Alen - Blen + 1); q = tQ->coeffs; } else { nmod_poly_fit_length(Q, Alen - Blen + 1); q = Q->coeffs; } _nmod_poly_div_divconquer(q, A->coeffs, Alen, B->coeffs, Blen, A->mod); if (Q == A || Q == B) { nmod_poly_swap(tQ, Q); nmod_poly_clear(tQ); } Q->length = Alen - Blen + 1; } flint2-2.8.4/nmod_poly/div_divconquer_recursive.c000066400000000000000000000054411414523752600222140ustar00rootroot00000000000000/* Copyright (C) 2008, 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_div_divconquer_recursive(mp_ptr Q, mp_ptr W, mp_ptr V, mp_srcptr A, mp_srcptr B, slong lenB, nmod_t mod) { if (lenB <= NMOD_DIV_DIVCONQUER_CUTOFF) { _nmod_poly_div_basecase(Q, V, A, 2 * lenB - 1, B, lenB, mod); } else { const slong n2 = lenB / 2; const slong n1 = lenB - n2; mp_ptr W1 = W; mp_ptr W2 = W + n2; mp_srcptr p1 = A + 2 * n2; mp_srcptr p2; mp_srcptr d1 = B + n2; mp_srcptr d2 = B; mp_srcptr d3 = B + n1; mp_ptr q1 = Q + n2; mp_ptr q2 = Q; mp_ptr d1q1 = q2 + n2 - (n1 - 1); mp_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 */ _nmod_poly_divrem_divconquer_recursive(q1, d1q1, W1, V, p1, d1, n1, mod); /* Compute bottom n1 + n2 - 1 coeffs of d2q1 = d2 q1 */ d2q1 = W1; _nmod_poly_mullow(d2q1, q1, n1, d2, n2, n1 + n2 - 1, mod); /* 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) W1[0] = d2q1[n1 - 1]; _nmod_vec_add(W1 + n2 - (n1 - 1), d1q1, d2q1 + n2, n1 - 1, mod); /* 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; _nmod_vec_sub(t, A + n2 + (n1 - 1), t, n2, mod); p2 = t - (n2 - 1); /* Compute q2 = t div d3, a 2 n2 - 1 by n2 division, so q2 will have length n2; */ _nmod_poly_div_divconquer_recursive(q2, W2, V, p2, d3, n2, mod); /* Note Q = q1 x^n2 + q2 */ } } flint2-2.8.4/nmod_poly/div_newton.c000066400000000000000000000042671414523752600172650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_div_newton(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { const slong lenQ = lenA - lenB + 1; mp_ptr Arev, Brev; Arev = _nmod_vec_init(2 * lenQ); Brev = Arev + lenQ; _nmod_poly_reverse(Arev, A + (lenA - lenQ), lenQ, lenQ); if (lenB >= lenQ) { _nmod_poly_reverse(Brev, B + (lenB - lenQ), lenQ, lenQ); } else { _nmod_poly_reverse(Brev, B, lenB, lenB); flint_mpn_zero(Brev + lenB, lenQ - lenB); } /* todo: don't zero pad! */ _nmod_poly_div_series(Q, Arev, lenQ, Brev, lenQ, lenQ, mod); _nmod_poly_reverse(Q, Q, lenQ, lenQ); _nmod_vec_clear(Arev); } void nmod_poly_div_newton(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B) { const slong lenA = A->length, lenB = B->length, lenQ = lenA - lenB + 1; mp_ptr q; if (lenB == 0) { if (nmod_poly_modulus(B) == 1) { nmod_poly_set(Q, A); return; } else { flint_printf("Exception (nmod_poly_div_newton). Division by zero.\n"); flint_abort(); } } if (lenA < lenB) { nmod_poly_zero(Q); return; } if (Q == A || Q == B) { q = flint_malloc(lenQ * sizeof(mp_limb_t)); } else { nmod_poly_fit_length(Q, lenQ); q = Q->coeffs; } _nmod_poly_div_newton(q, A->coeffs, lenA, B->coeffs, lenB, B->mod); if (Q == A || Q == B) { flint_free(Q->coeffs); Q->coeffs = q; Q->alloc = lenQ; } Q->length = lenQ; } flint2-2.8.4/nmod_poly/div_newton_n_preinv.c000066400000000000000000000046671414523752600211710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #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_printf("Exception (nmod_poly_div_newton_n_preinv). Division by zero.\n"); flint_abort(); } } 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; } flint2-2.8.4/nmod_poly/div_root.c000066400000000000000000000027251414523752600167330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.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; } flint2-2.8.4/nmod_poly/div_series.c000066400000000000000000000036561414523752600172460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" 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 < 32 || Blen < 65 * FLINT_BIT_COUNT(mod.n)) { _nmod_poly_div_series_basecase(Q, A, Alen, B, Blen, n, mod); } else { mp_ptr Binv = _nmod_vec_init(n); _nmod_poly_inv_series(Binv, B, Blen, n, mod); _nmod_poly_mullow(Q, Binv, n, A, FLINT_MIN(n, Alen), n, mod); _nmod_vec_clear(Binv); } } 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_printf("Exception (nmod_poly_div_series). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/div_series_basecase.c000066400000000000000000000047171414523752600210730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" 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; slong i, j, l; int nlimbs; mp_limb_t s; Plen = FLINT_MIN(Plen, n); Qlen = FLINT_MIN(Qlen, n); q = Q[0]; if (q != 1) q = n_invmod(q, mod.n); if (Qlen == 1) { _nmod_vec_scalar_mul_nmod(Qinv, P, Plen, q, mod); _nmod_vec_zero(Qinv + Plen, n - Plen); } else { Qinv[0] = n_mulmod2_preinv(q, P[0], mod.n, mod.ninv); 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 = n_submod(P[i], s, mod.n); else s = n_negmod(s, mod.n); if (q != 1) Qinv[i] = n_mulmod2_preinv(s, q, mod.n, mod.ninv); else Qinv[i] = s; } } } 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_printf("Exception (nmod_poly_div_series_basecase). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/divides.c000066400000000000000000000054461414523752600165400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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; } flint2-2.8.4/nmod_poly/divides_classical.c000066400000000000000000000061511414523752600205500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" /* 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; mp_ptr W; int res; TMP_INIT; TMP_START; W = TMP_ALLOC(NMOD_DIV_BC_ITCH(lenA, lenB, mod)*sizeof(mp_limb_t)); _nmod_poly_div_basecase(Q, W, 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); TMP_END; 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; } flint2-2.8.4/nmod_poly/divrem.c000066400000000000000000000052601414523752600163710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "mpn_extras.h" void _nmod_poly_divrem(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { TMP_INIT; if (lenA == lenB) _nmod_poly_divrem_q0(Q, R, A, B, lenB, mod); else if (lenA == lenB + 1) _nmod_poly_divrem_q1(Q, R, A, lenA, B, lenB, mod); else if (lenB < 15) { mp_ptr W; TMP_START; W = TMP_ALLOC(NMOD_DIVREM_BC_ITCH(lenA, lenB, mod)*sizeof(mp_limb_t)); _nmod_poly_divrem_basecase(Q, R, W, A, lenA, B, lenB, mod); TMP_END; } else if (lenB < 6000) _nmod_poly_divrem_divconquer(Q, R, A, lenA, B, lenB, mod); else _nmod_poly_divrem_newton(Q, R, A, lenA, B, lenB, mod); } 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_printf("Exception (nmod_poly_divrem). Division by zero."); flint_abort(); } } 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 == A || 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 == A || R == B) { nmod_poly_swap(R, tR); nmod_poly_clear(tR); } Q->length = lenA - lenB + 1; R->length = lenB - 1; _nmod_poly_normalise(R); } flint2-2.8.4/nmod_poly/divrem_basecase.c000066400000000000000000000146301414523752600202200ustar00rootroot00000000000000/* Copyright (C) 2010, 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_divrem_basecase_1(mp_ptr Q, mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { const mp_limb_t invL = n_invmod(B[lenB - 1], mod.n); 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_2(mp_ptr Q, mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { const mp_limb_t invL = n_invmod(B[lenB - 1], mod.n); 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_3(mp_ptr Q, mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { const mp_limb_t invL = n_invmod(B[lenB - 1], mod.n); 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(mp_ptr Q, mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { const slong bits = 2 * (FLINT_BITS - mod.norm) + FLINT_BIT_COUNT(lenA - lenB + 1); if (bits <= FLINT_BITS) _nmod_poly_divrem_basecase_1(Q, R, W, A, lenA, B, lenB, mod); else if (bits <= 2 * FLINT_BITS) _nmod_poly_divrem_basecase_2(Q, R, W, A, lenA, B, lenB, mod); else _nmod_poly_divrem_basecase_3(Q, R, W, A, lenA, B, lenB, 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; mp_ptr Q_coeffs, R_coeffs, W; nmod_poly_t t1, t2; TMP_INIT; if (lenB == 0) { if (nmod_poly_modulus(B) == 1) { nmod_poly_set(Q, A); nmod_poly_zero(R); return; } else { flint_printf("Exception (nmod_poly_divrem). Division by zero.\n"); flint_abort(); } } if (lenA < lenB) { nmod_poly_set(R, A); nmod_poly_zero(Q); return; } if (Q == A || Q == B) { nmod_poly_init2_preinv(t1, B->mod.n, B->mod.ninv, lenA - lenB + 1); Q_coeffs = t1->coeffs; } else { nmod_poly_fit_length(Q, lenA - lenB + 1); Q_coeffs = Q->coeffs; } if (R == A || R == B) { nmod_poly_init2_preinv(t2, B->mod.n, B->mod.ninv, lenB - 1); R_coeffs = t2->coeffs; } else { nmod_poly_fit_length(R, lenB - 1); R_coeffs = R->coeffs; } TMP_START; W = TMP_ALLOC(NMOD_DIVREM_BC_ITCH(lenA, lenB, A->mod)*sizeof(mp_limb_t)); _nmod_poly_divrem_basecase(Q_coeffs, R_coeffs, W, A->coeffs, lenA, B->coeffs, lenB, B->mod); if (Q == A || Q == B) { nmod_poly_swap(Q, t1); nmod_poly_clear(t1); } if (R == A || R == B) { nmod_poly_swap(R, t2); nmod_poly_clear(t2); } Q->length = lenA - lenB + 1; R->length = lenB - 1; TMP_END; _nmod_poly_normalise(R); } flint2-2.8.4/nmod_poly/divrem_divconquer.c000066400000000000000000000113641414523752600206320ustar00rootroot00000000000000/* Copyright (C) 2008, 2009, 2011 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" static void __nmod_poly_divrem_divconquer(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { 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; mp_srcptr p1 = A + n2; mp_srcptr d1 = B + n2; mp_srcptr d2 = B; mp_ptr V = _nmod_vec_init((n1 - 1) + lenB - 1 + NMOD_DIVREM_DC_ITCH(n1, mod)); mp_ptr W = V + NMOD_DIVREM_DC_ITCH(n1, mod); mp_ptr d1q1 = R + n2; mp_ptr d2q1 = W; _nmod_poly_divrem_divconquer_recursive(Q, d1q1, W, V, p1, d1, n1, mod); /* Compute d2q1 = Q d2, of length lenB - 1 */ if (n1 >= n2) _nmod_poly_mul(d2q1, Q, n1, d2, n2, mod); else _nmod_poly_mul(d2q1, d2, n2, Q, n1, mod); /* Compute BQ = d1q1 * x^n1 + d2q1, of length lenB - 1; then compute R = A - BQ */ flint_mpn_copyi(R, d2q1, n2); _nmod_vec_add(R + n2, R + n2, d2q1 + n2, n1 - 1, mod); _nmod_vec_sub(R, A, R, lenB - 1, mod); _nmod_vec_clear(V); } else /* lenA = 2 * lenB - 1 */ { mp_ptr V = _nmod_vec_init(lenB - 1 + NMOD_DIVREM_DC_ITCH(lenB, mod)); mp_ptr W = V + NMOD_DIVREM_DC_ITCH(lenB, mod); _nmod_poly_divrem_divconquer_recursive(Q, R, W, V, A, B, lenB, mod); _nmod_vec_sub(R, A, R, lenB - 1, mod); _nmod_vec_clear(V); } } void _nmod_poly_divrem_divconquer(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { if (lenA <= 2 * lenB - 1) { __nmod_poly_divrem_divconquer(Q, R, A, lenA, B, lenB, mod); } else /* lenA > 2 * lenB - 1 */ { slong shift, n = 2 * lenB - 1; mp_ptr S, QB, W, V, T; S = _nmod_vec_init(lenA + 2 * (lenB - 1) + n + NMOD_DIVREM_DC_ITCH(lenB, mod)); QB = S + lenA; W = QB + (lenB - 1); T = W + (lenB - 1); V = T + n; _nmod_vec_set(S, A, lenA); while (lenA >= n) { shift = lenA - n; _nmod_poly_divrem_divconquer_recursive(Q + shift, QB, W, V, S + shift, B, lenB, mod); _nmod_vec_sub(S + shift, S + shift, QB, lenB - 1, mod); lenA -= lenB; } if (lenA >= lenB) { __nmod_poly_divrem_divconquer(Q, T, S, lenA, B, lenB, mod); _nmod_vec_set(S, T, lenA); } _nmod_vec_set(R, S, lenB - 1); _nmod_vec_clear(S); } } void nmod_poly_divrem_divconquer(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B) { nmod_poly_t tQ, tR; mp_ptr q, r; slong lenA, lenB; lenA = A->length; lenB = B->length; if (lenB == 0) { if (nmod_poly_modulus(B) == 1) { nmod_poly_set(Q, A); nmod_poly_zero(R); return; } else { flint_printf("Exception (nmod_poly_divrem_divconquer). Division by zero.\n"); flint_abort(); } } if (lenA < lenB) { nmod_poly_set(R, A); nmod_poly_zero(Q); return; } 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; } if (R == A || R == B) { nmod_poly_init2(tR, A->mod.n, lenB - 1); r = tR->coeffs; } else { nmod_poly_fit_length(R, lenB - 1); r = R->coeffs; } _nmod_poly_divrem_divconquer(q, r, A->coeffs, lenA, B->coeffs, lenB, A->mod); if (Q == A || Q == B) { nmod_poly_swap(tQ, Q); nmod_poly_clear(tQ); } if (R == A || R == B) { nmod_poly_swap(tR, R); nmod_poly_clear(tR); } Q->length = lenA - lenB + 1; R->length = lenB - 1; _nmod_poly_normalise(R); } flint2-2.8.4/nmod_poly/divrem_divconquer_recursive.c000066400000000000000000000071721414523752600227230ustar00rootroot00000000000000/* Copyright (C) 2008, 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_divrem_divconquer_recursive(mp_ptr Q, mp_ptr BQ, mp_ptr W, mp_ptr V, mp_srcptr A, mp_srcptr B, slong lenB, nmod_t mod) { if (lenB <= NMOD_DIVREM_DIVCONQUER_CUTOFF) { mp_ptr t = V; mp_ptr w = t + 2*lenB - 1; flint_mpn_copyi(t + lenB - 1, A + lenB - 1, lenB); flint_mpn_zero(t, lenB - 1); _nmod_poly_divrem_basecase(Q, BQ, w, t, 2 * lenB - 1, B, lenB, mod); /* BQ = A - R */ _nmod_vec_neg(BQ, BQ, lenB - 1, mod); } else { const slong n2 = lenB / 2; const slong n1 = lenB - n2; mp_ptr W1 = W; mp_ptr W2 = W + n2; mp_srcptr p1 = A + 2 * n2; mp_srcptr p2; mp_srcptr d1 = B + n2; mp_srcptr d2 = B; mp_srcptr d3 = B + n1; mp_srcptr d4 = B; mp_ptr q1 = Q + n2; mp_ptr q2 = Q; mp_ptr dq1 = BQ + n2; mp_ptr d1q1 = BQ + n2 - (n1 - 1); mp_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; low(d1q1) = d1 q1 is of length n1 - 1 */ _nmod_poly_divrem_divconquer_recursive(q1, d1q1, W1, V, p1, d1, n1, mod); /* Compute bottom n1 + n2 - 1 coeffs of d2q1 = d2 q1 */ d2q1 = W1; _nmod_poly_mullow(d2q1, q1, n1, d2, n2, n1 + n2 - 1, mod); /* Compute dq1 = d1 q1 x^n2 + d2 q1, of length n1 + n2 - 1 Split it into a segment of length n1 - 1 at dq1 and a piece of length n2 at BQ. */ flint_mpn_copyi(dq1, d2q1, n1 - 1); if (n2 > n1 - 1) BQ[0] = d2q1[n1 - 1]; _nmod_vec_add(d1q1, d1q1, d2q1 + n2, n1 - 1, mod); /* 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; _nmod_vec_sub(t, A + n2 + (n1 - 1), BQ, n2, mod); p2 = t - (n2 - 1); /* Compute q2 = t div d3, a 2 n2 - 1 by n2 division, so q2 will have length n2; let low(d3q2) = d3 q2, of length n2 - 1 */ d3q2 = BQ; _nmod_poly_divrem_divconquer_recursive(q2, d3q2, W2, V, p2, d3, n2, mod); /* Compute d4q2 = d4 q2, of length n1 + n2 - 1 */ d4q2 = W1; _nmod_poly_mullow(d4q2, d4, n1, q2, n2, n1 + n2 - 1, mod); /* Compute dq2 = d3q2 x^n1 + d4q2, of length n1 + n2 - 1 */ _nmod_vec_add(BQ + n1, BQ + n1, d3q2, n2 - 1, mod); flint_mpn_copyi(BQ, d4q2, n2); _nmod_vec_add(BQ + n2, BQ + n2, d4q2 + n2, n1 - 1, mod); /* Note Q = q1 x^n2 + q2, and BQ = dq1 x^n2 + dq2 */ } } flint2-2.8.4/nmod_poly/divrem_newton.c000066400000000000000000000046171414523752600177700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_divrem_newton(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { const slong lenQ = lenA - lenB + 1; _nmod_poly_div_newton(Q, A, lenA, B, lenB, 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(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; 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_printf("Exception (nmod_poly_divrem_newton). Division by zero.\n"); flint_abort(); } } if (lenA < lenB) { nmod_poly_set(R, A); nmod_poly_zero(Q); return; } if (Q == A || Q == B) { 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 = _nmod_vec_init(lenB - 1); } else { nmod_poly_fit_length(R, lenB - 1); r = R->coeffs; } _nmod_poly_divrem_newton(q, r, A->coeffs, lenA, B->coeffs, lenB, B->mod); if (Q == A || Q == B) { _nmod_vec_clear(Q->coeffs); Q->coeffs = q; Q->alloc = lenA - lenB + 1; } if (R == A || R == B) { _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); } flint2-2.8.4/nmod_poly/divrem_newton_n_preinv.c000066400000000000000000000061041414523752600216610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.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) { _nmod_poly_divrem_q1(Q, R, A, lenA, B, lenB, 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_printf("Exception (nmod_poly_divrem_newton_n_preinv). Division by zero.\n"); flint_abort(); } } if (lenA < lenB) { nmod_poly_set(R, A); nmod_poly_zero(Q); return; } if (lenA > 2 * lenB - 2) { 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); } flint2-2.8.4/nmod_poly/divrem_q0.c000066400000000000000000000017601414523752600167720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_divrem_q0(mp_ptr Q, mp_ptr R, mp_srcptr A, mp_srcptr B, slong lenA, nmod_t mod) { const mp_limb_t invL = (B[lenA-1] == 1) ? 1 : n_invmod(B[lenA-1], mod.n); if (lenA == 1) { _nmod_vec_scalar_mul_nmod(Q, A, lenA, invL, mod); } else { Q[0] = n_mulmod2_preinv(A[lenA-1], invL, mod.n, mod.ninv); _nmod_vec_scalar_mul_nmod(R, B, lenA - 1, Q[0], mod); _nmod_vec_sub(R, A, R, lenA - 1, mod); } } flint2-2.8.4/nmod_poly/divrem_q1.c000066400000000000000000000031661414523752600167750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_divrem_q1(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { const mp_limb_t invL = (B[lenB-1] == 1) ? 1 : n_invmod(B[lenB-1], mod.n); if (lenB == 1) { _nmod_vec_scalar_mul_nmod(Q, A, lenA, invL, mod); } else { mp_limb_t t; Q[1] = n_mulmod2_preinv(A[lenA-1], invL, mod.n, mod.ninv); t = n_mulmod2_preinv(Q[1], B[lenB-2], mod.n, mod.ninv); t = n_submod(A[lenA-2], t, mod.n); Q[0] = n_mulmod2_preinv(t, invL, mod.n, mod.ninv); if (FLINT_BITS + 2 <= 2 * mod.norm) { FLINT_ASSERT(lenB > 1); mpn_mul_1(R, B, lenB - 1, Q[0]); if (lenB > 2) mpn_addmul_1(R + 1, B, lenB - 2, Q[1]); _nmod_vec_reduce(R, R, lenB - 1, mod); } else { _nmod_vec_scalar_mul_nmod(R, B, lenB - 1, Q[0], mod); if (lenB > 2) _nmod_vec_scalar_addmul_nmod(R + 1, B, lenB - 2, Q[1], mod); } _nmod_vec_sub(R, A, R, lenB - 1, mod); } } flint2-2.8.4/nmod_poly/equal_trunc.c000066400000000000000000000023661414523752600174310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #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; } flint2-2.8.4/nmod_poly/evaluate_fmpz.c000066400000000000000000000022361414523752600177450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" /* TODO: Add a divconquer method */ void _nmod_poly_evaluate_fmpz(fmpz_t rop, mp_srcptr poly, const slong len, const fmpz_t c) { fmpz_t t; slong m; if (len == 0) { fmpz_zero(rop); return; } if (len == 1 || c == 0) { fmpz_set_ui(rop, poly[0]); return; } m = len - 1; fmpz_init(t); fmpz_set_ui(rop, poly[m]); m--; for ( ; m >= 0; m--) { fmpz_mul(t, rop, c); fmpz_add_ui(rop, t, poly[m]); } fmpz_clear(t); } void nmod_poly_evaluate_fmpz(fmpz_t rop, const nmod_poly_t poly, const fmpz_t c) { _nmod_poly_evaluate_fmpz(rop, poly->coeffs, poly->length, c); } flint2-2.8.4/nmod_poly/evaluate_mat_horner.c000066400000000000000000000041331414523752600211250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "flint.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); } } flint2-2.8.4/nmod_poly/evaluate_mat_paterson_stockmeyer.c000066400000000000000000000041421414523752600237300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" #include "flint.h" #include "nmod_mat.h" 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); } flint2-2.8.4/nmod_poly/evaluate_nmod.c000066400000000000000000000020231414523752600177200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/nmod_poly/evaluate_nmod_vec.c000066400000000000000000000017331414523752600205640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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); } flint2-2.8.4/nmod_poly/evaluate_nmod_vec_fast.c000066400000000000000000000065351414523752600216060ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" /* 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); } flint2-2.8.4/nmod_poly/evaluate_nmod_vec_iter.c000066400000000000000000000016531414523752600216100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" 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); } flint2-2.8.4/nmod_poly/exp_series.c000066400000000000000000000106061414523752600172510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #define NMOD_POLY_NEWTON_EXP_CUTOFF 4000 /* c_k x^k -> c_k x^k / (m+k) */ void _nmod_poly_integral_offset(mp_ptr res, mp_srcptr poly, slong len, slong m, nmod_t mod) { slong k; mp_limb_t t; t = 1; for (k = len - 1; k >= 0; k--) { res[k] = n_mulmod2_preinv(poly[k], t, mod.n, mod.ninv); t = n_mulmod2_preinv(t, m + k, mod.n, mod.ninv); } if (t >= mod.n) t = n_mod2_preinv(t, mod.n, mod.ninv); t = n_invmod(t, mod.n); for (k = 0; k < len; k++) { res[k] = n_mulmod2_preinv(res[k], t, mod.n, mod.ninv); t = n_mulmod2_preinv(t, m + k, mod.n, mod.ninv); } } void _nmod_poly_exp_series_newton(mp_ptr f, mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) { slong a[FLINT_BITS]; slong i, m, l, r; mp_ptr t, hprime; 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. */ inverse = (g != NULL); if (!inverse) g = _nmod_vec_init(n); hlen = FLINT_MIN(hlen, n); t = _nmod_vec_init(n); hprime = _nmod_vec_init(hlen - 1); _nmod_poly_derivative(hprime, h, hlen, mod); for (i = 1; (WORD(1) << i) < n; i++); a[i = 0] = n; while (n >= NMOD_POLY_NEWTON_EXP_CUTOFF || i == 0) a[++i] = (n = (n + 1) / 2); /* f := exp(h) + O(x^n), g := exp(-h) + O(x^n) */ _nmod_poly_exp_series_basecase(f, h, hlen, n, mod); _nmod_poly_inv_series(g, f, n, n, mod); 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) _nmod_poly_mullow(t, hprime, l, f, m, r, mod); else _nmod_poly_mullow(t, f, m, hprime, l, r, mod); _nmod_poly_mullow(g + m, g, n - m, t + m - 1, r + 1 - m, n - m, mod); _nmod_poly_integral_offset(g + m, g + m, n - m, m, mod); _nmod_poly_mullow(f + m, f, n - m, g + m, n - m, n - m, mod); /* g := exp(-h) + O(x^n); not needed if we only want exp(x) */ if (i != 0 || inverse) { _nmod_poly_mullow(t, f, n, g, m, n, mod); _nmod_poly_mullow(g + m, g, m, t + m, n - m, n - m, mod); _nmod_vec_neg(g + m, g + m, n - m, mod); } } _nmod_vec_clear(hprime); _nmod_vec_clear(t); if (!inverse) _nmod_vec_clear(g); } void _nmod_poly_exp_series(mp_ptr f, mp_srcptr h, slong hlen, slong n, nmod_t mod) { hlen = FLINT_MIN(hlen, n); if (hlen >= 2 && n > 2 && _nmod_vec_is_zero(h + 1, hlen - 2)) _nmod_poly_exp_series_monomial_ui(f, h[hlen - 1], hlen - 1, n, mod); else if (hlen < NMOD_POLY_NEWTON_EXP_CUTOFF) _nmod_poly_exp_series_basecase(f, h, hlen, n, mod); else _nmod_poly_exp_series_newton(f, NULL, h, hlen, n, mod); } void _nmod_poly_exp_expinv_series(mp_ptr f, mp_ptr g, mp_srcptr h, slong hlen, slong n, nmod_t mod) { hlen = FLINT_MIN(hlen, n); if (hlen < NMOD_POLY_NEWTON_EXP_CUTOFF) { _nmod_poly_exp_series_basecase(f, h, hlen, n, mod); _nmod_poly_inv_series(g, f, n, n, mod); } else { _nmod_poly_exp_series_newton(f, g, h, hlen, 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_printf("Exception (nmod_poly_exp_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/exp_series_basecase.c000066400000000000000000000036041414523752600210770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_exp_series_basecase(mp_ptr f, mp_srcptr h, slong hlen, slong n, nmod_t mod) { slong j, k, l; mp_ptr a; mp_limb_t s; int nlimbs; TMP_INIT; f[0] = 1; if (hlen < 2) { _nmod_vec_zero(f + 1, n - 1); return; } if (n < 2) return; f[1] = h[1]; TMP_START; a = TMP_ALLOC(FLINT_MIN(n, hlen) * sizeof(mp_limb_t)); for (k = 1; k < FLINT_MIN(n, hlen); k++) a[k] = n_mulmod2_preinv(h[k], k, mod.n, mod.ninv); nlimbs = _nmod_vec_dot_bound_limbs(FLINT_MIN(n, hlen), mod); for (k = 2; k < n; k++) { l = FLINT_MIN(k, hlen - 1); NMOD_VEC_DOT(s, j, l, a[1 + j], f[k - 1 - j], mod, nlimbs) f[k] = n_mulmod2_preinv(s, n_invmod(k, mod.n), mod.n, mod.ninv); } TMP_END; } void nmod_poly_exp_series_basecase(nmod_poly_t f, const nmod_poly_t h, slong n) { slong hlen = h->length; if (hlen > 0 && h->coeffs[0] != 0) { flint_printf("Exception (nmod_poly_exp_series_basecase). Constant term != 0.\n"); flint_abort(); } 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_basecase(f->coeffs, h->coeffs, hlen, n, f->mod); f->length = n; _nmod_poly_normalise(f); } flint2-2.8.4/nmod_poly/exp_series_monomial_ui.c000066400000000000000000000045771414523752600216530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_exp_series_monomial_ui(mp_ptr res, mp_limb_t coeff, ulong power, slong n, nmod_t mod) { slong k, r; mp_limb_t rfac; mp_limb_t a; r = (n - 1) / power; rfac = n_factorial_mod2_preinv(r, mod.n, mod.ninv); rfac = n_invmod(rfac, mod.n); if (power > 1) _nmod_vec_zero(res, n); res[0] = UWORD(1); if (coeff == UWORD(1)) { a = rfac; for (k = r; k >= 1; k--) { res[k * power] = a; a = n_mulmod2_preinv(a, k, mod.n, mod.ninv); } } else { a = coeff; for (k = power; k < n; k += power) { res[k] = a; a = n_mulmod2_preinv(a, coeff, mod.n, mod.ninv); } a = rfac; for (k = r; k >= 1; k--) { res[k * power] = n_mulmod2_preinv(res[k * power], a, mod.n, mod.ninv); a = n_mulmod2_preinv(a, k, mod.n, mod.ninv); } } } void nmod_poly_exp_series_monomial_ui(nmod_poly_t res, mp_limb_t coeff, ulong power, slong n) { if (n == 0) { nmod_poly_zero(res); return; } if (coeff == UWORD(0)) { nmod_poly_fit_length(res, 1); res->coeffs[0] = UWORD(1); res->length = 1; return; } if (power == 0) { flint_printf("Exception (nmod_poly_exp_series_monomial_ui). \n" "Constant term != 0.\n"); flint_abort(); } if (coeff != UWORD(1)) coeff = n_mod2_preinv(coeff, res->mod.n, res->mod.ninv); if (n == 1 || power >= n) { nmod_poly_fit_length(res, 1); res->coeffs[0] = UWORD(1); res->length = 1; } nmod_poly_fit_length(res, n); _nmod_poly_exp_series_monomial_ui(res->coeffs, coeff, power, n, res->mod); res->length = n; _nmod_poly_normalise(res); } flint2-2.8.4/nmod_poly/find_distinct_nonzero_roots.c000066400000000000000000000102071414523752600227210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "ulong_extras.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_div(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; } flint2-2.8.4/nmod_poly/fit_length.c000066400000000000000000000013451414523752600172260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #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); } } flint2-2.8.4/nmod_poly/fprintf_pretty.c000066400000000000000000000044561414523752600201700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "nmod_poly.h" 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; } flint2-2.8.4/nmod_poly/fread.c000066400000000000000000000017731414523752600161710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_poly.h" 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; } flint2-2.8.4/nmod_poly/gcd.c000066400000000000000000000041521414523752600156370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" slong _nmod_poly_gcd(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { const slong cutoff = FLINT_BIT_COUNT(mod.n) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; if (lenA < 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); } } } flint2-2.8.4/nmod_poly/gcd_euclidean.c000066400000000000000000000061301414523752600176460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "mpn_extras.h" 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); } } } flint2-2.8.4/nmod_poly/gcd_hgcd.c000066400000000000000000000100321414523752600166160ustar00rootroot00000000000000/* Copyright (C) 2011 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "mpn_extras.h" #define __set(B, lenB, A, lenA) \ do { \ _nmod_vec_set((B), (A), (lenA)); \ (lenB) = (lenA); \ } while (0) #define __rem(R, lenR, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ _nmod_poly_rem((R), (A), (lenA), (B), (lenB), mod); \ (lenR) = (lenB) - 1; \ MPN_NORM((R), (lenR)); \ } \ else \ { \ _nmod_vec_set((R), (A), (lenA)); \ (lenR) = (lenA); \ } \ } while (0) /* XXX: Incidentally, this implementation currently supports aliasing. But since this may change in the future, no function other than nmod_poly_gcd_hgcd() should rely on this. */ slong _nmod_poly_gcd_hgcd(mp_ptr G, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { const slong cutoff = FLINT_BIT_COUNT(mod.n) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; mp_ptr J = _nmod_vec_init(2 * lenB); mp_ptr R = J + lenB; slong lenG, lenJ, lenR; __rem(R, lenR, A, lenA, B, lenB); if (lenR == 0) { __set(G, lenG, B, lenB); } else { _nmod_poly_hgcd(NULL, NULL, G, &(lenG), J, &(lenJ), B, lenB, R, lenR, mod); while (lenJ != 0) { __rem(R, lenR, G, lenG, J, lenJ); if (lenR == 0) { __set(G, lenG, J, lenJ); break; } if (lenJ < cutoff) { lenG = _nmod_poly_gcd_euclidean(G, J, lenJ, R, lenR, mod); break; } _nmod_poly_hgcd(NULL, NULL, G, &(lenG), J, &(lenJ), J, lenJ, R, lenR, mod); } } _nmod_vec_clear(J); 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); } } } #undef __set #undef __rem flint2-2.8.4/nmod_poly/gcdinv.c000066400000000000000000000054611414523752600163600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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) { printf("Exception (nmod_poly_gcdinv). lenB < 2.\n"); flint_abort(); } 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); } } } flint2-2.8.4/nmod_poly/get_str.c000066400000000000000000000024201414523752600165450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #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; } flint2-2.8.4/nmod_poly/get_str_pretty.c000066400000000000000000000053611414523752600201630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" 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; } flint2-2.8.4/nmod_poly/hgcd.c000066400000000000000000000565561414523752600160260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "mpn_extras.h" /* We define a whole bunch of macros here which essentially provide the nmod_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) = (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 { \ _nmod_vec_set((B), (A), (lenA)); \ (lenB) = (lenA); \ } while (0) #define __swap MPN_SWAP #define __add(C, lenC, A, lenA, B, lenB) \ do { \ _nmod_poly_add((C), (A), (lenA), (B), (lenB), mod); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ MPN_NORM((C), (lenC)); \ } while (0) #define __sub(C, lenC, A, lenA, B, lenB) \ do { \ _nmod_poly_sub((C), (A), (lenA), (B), (lenB), mod); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ MPN_NORM((C), (lenC)); \ } while (0) #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) #define __divrem(Q, lenQ, R, lenR, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ _nmod_poly_divrem((Q), (R), (A), (lenA), (B), (lenB), mod); \ (lenQ) = (lenA) - (lenB) + 1; \ (lenR) = (lenB) - 1; \ MPN_NORM((R), (lenR)); \ } \ else \ { \ _nmod_vec_set((R), (A), (lenA)); \ (lenQ) = 0; \ (lenR) = (lenA); \ } \ } while (0) static __inline__ void __mat_one(mp_ptr *M, slong *lenM) { M[0][0] = WORD(1); M[3][0] = WORD(1); lenM[0] = 1; lenM[1] = 0; lenM[2] = 0; lenM[3] = 1; } /* 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 void __mat_mul_classical(mp_ptr *C, slong *lenC, mp_ptr *A, slong *lenA, mp_ptr *B, slong *lenB, mp_ptr T, nmod_t mod) { slong lenT; __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); } /* 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 void __mat_mul_strassen(mp_ptr *C, slong *lenC, mp_ptr *A, slong *lenA, mp_ptr *B, slong *lenB, mp_ptr T0, mp_ptr T1, nmod_t mod) { slong lenT0, lenT1; __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); } /* 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 void __mat_mul(mp_ptr *C, slong *lenC, mp_ptr *A, slong *lenA, mp_ptr *B, slong *lenB, mp_ptr T0, mp_ptr T1, nmod_t mod) { 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) { __mat_mul_classical(C, lenC, A, lenA, B, lenB, T0, mod); } else { __mat_mul_strassen(C, lenC, A, lenA, B, lenB, T0, T1, mod); } } /* 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. */ slong _nmod_poly_hgcd_recursive_iter(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 Q, mp_ptr *T, mp_ptr *t, nmod_t mod, nmod_poly_res_t res) { const slong m = lena / 2; slong sgn = 1; __mat_one(M, lenM); __set(*A, *lenA, a, lena); __set(*B, *lenB, b, lenb); while (*lenB >= m + 1) { slong lenQ, lenT, lent; if (res) res->lc = (*B)[*lenB - 1]; __divrem(Q, lenQ, *T, lenT, *A, *lenA, *B, *lenB); if (res) { if (lenT >= m + 1) { if (lenT >= 1) { res->lc = n_powmod2_preinv(res->lc, *lenA - lenT, mod.n, mod.ninv); res->res = n_mulmod2_preinv(res->res, res->lc, mod.n, mod.ninv); if ((((*lenA + res->off) | (*lenB + res->off)) & 1) == 0) res->res = nmod_neg(res->res, mod); } else { if (*lenB == 1) { res->lc = n_powmod2_preinv(res->lc, *lenA - 1, mod.n, mod.ninv); res->res = n_mulmod2_preinv(res->res, res->lc, mod.n, mod.ninv); } else res->res = 0; } } 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; } return sgn; } /* 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. The res struct, if not NULL, passes information required to compute the sign changes and powers of leading terms used to compute the resultant. */ 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) { const slong m = lena / 2; if (lenb < m + 1) { if (flag) { __mat_one(M, lenM); } __set(A, *lenA, a, lena); __set(B, *lenB, b, lenb); return 1; } else { /* Readonly pointers */ mp_ptr a0, b0, s, t, a4, b4, c0, d0; slong lena0, lenb0, lens, lent, lena4, lenb4, lenc0, lend0; /* Pointers to independently allocated memory */ mp_ptr a2, b2, a3, b3, q, d, T0, T1; slong lena2, lenb2, lena3, lenb3, lenq, lend, lenT0; mp_ptr R[4], S[4]; slong lenR[4], lenS[4]; slong sgnR, sgnS; a2 = P; b2 = a2 + lena; a3 = b2 + lena; b3 = a3 + lena; q = b3 + lena; d = q + (lena + 1)/2; T0 = d + lena; T1 = T0 + lena; R[0] = T1 + (lena + 1)/2; R[1] = R[0] + (lena + 1)/2; R[2] = R[1] + (lena + 1)/2; R[3] = R[2] + (lena + 1)/2; S[0] = R[3] + (lena + 1)/2; S[1] = S[0] + (lena + 1)/2; S[2] = S[1] + (lena + 1)/2; S[3] = S[2] + (lena + 1)/2; P += 6 * lena + 10 * (lena + 1)/2; __attach_shift(a0, lena0, (mp_ptr) a, lena, m); __attach_shift(b0, lenb0, (mp_ptr) b, lenb, m); if (res) { res->lc = b[lenb - 1]; res->len0 -= m; res->len1 -= m; res->off += m; } if (lena0 < NMOD_POLY_HGCD_CUTOFF) sgnR = _nmod_poly_hgcd_recursive_iter(R, lenR, &a3, &lena3, &b3, &lenb3, a0, lena0, b0, lenb0, q, &T0, &T1, mod, res); else sgnR = _nmod_poly_hgcd_recursive(R, lenR, a3, &lena3, b3, &lenb3, a0, lena0, b0, lenb0, P, mod, 1, res); if (res) { res->off -= m; res->len0 += m; res->len1 += m; } __attach_truncate(s, lens, (mp_ptr) a, lena, m); __attach_truncate(t, lent, (mp_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); flint_mpn_zero(b2 + lenb2, m + lenb3 - lenb2); __attach_shift(b4, lenb4, b2, lenb2, m); __add(b4, lenb4, b4, lenb4, b3, lenb3); lenb2 = FLINT_MAX(m + lenb3, lenb2); MPN_NORM(b2, lenb2); __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); flint_mpn_zero(a2 + lena2, m + lena3 - lena2); __attach_shift(a4, lena4, a2, lena2, m); __add(a4, lena4, a4, lena4, a3, lena3); lena2 = FLINT_MAX(m + lena3, lena2); MPN_NORM(a2, lena2); 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]); } return sgnR; } else { slong k = 2 * m - lenb2 + 1; if (res) { if (lenb2 < lenb) /* ensure something happened */ { if (lenb2 >= 1) { res->lc = n_powmod2_preinv(res->lc, res->len0 - lenb2, mod.n, mod.ninv); res->res = n_mulmod2_preinv(res->res, res->lc, mod.n, mod.ninv); if ((((res->len0 + res->off) | (res->len1 + res->off)) & 1) == 0) res->res = nmod_neg(res->res, mod); } else { if (res->len1 == 1) { res->lc = n_powmod2_preinv(res->lc, res->len0 - 1, mod.n, mod.ninv); res->res = n_mulmod2_preinv(res->res, res->lc, mod.n, mod.ninv); } else res->res = 0; } } res->lc = b2[lenb2 - 1]; 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) { if (lend >= m + 1) { if (lend >= 1) { res->lc = n_powmod2_preinv(res->lc, lena2 - lend, mod.n, mod.ninv); res->res = n_mulmod2_preinv(res->res, res->lc, mod.n, mod.ninv); if ((((lena2 + res->off) | (lenb2 + res->off)) & 1) == 0) res->res = nmod_neg(res->res, mod); } else { if (lenb2 == 1) { res->lc = n_powmod2_preinv(res->lc, lena2 - 1, mod.n, mod.ninv); res->res = n_mulmod2_preinv(res->res, res->lc, mod.n, mod.ninv); } else res->res = 0; } res->len0 = lenb2; res->len1 = lend; } res->len0 -= k; res->len1 -= k; res->off += k; } if (lenc0 < NMOD_POLY_HGCD_CUTOFF) sgnS = _nmod_poly_hgcd_recursive_iter(S, lenS, &a3, &lena3, &b3, &lenb3, c0, lenc0, d0, lend0, a2, &T0, &T1, mod, res); /* a2 as temp */ else sgnS = _nmod_poly_hgcd_recursive(S, lenS, a3, &lena3, b3, &lenb3, c0, lenc0, d0, lend0, P, mod, 1, res); if (res) { 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); flint_mpn_zero(B + *lenB, k + lenb3 - *lenB); __attach_shift(b4, lenb4, B, *lenB, k); __add(b4, lenb4, b4, lenb4, b3, lenb3); *lenB = FLINT_MAX(k + lenb3, *lenB); MPN_NORM(B, *lenB); __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); flint_mpn_zero(A + *lenA, k + lena3 - *lenA); __attach_shift(a4, lena4, A, *lenA, k); __add(a4, lena4, a4, lena4, a3, lena3); *lenA = FLINT_MAX(k + lena3, *lenA); MPN_NORM(A, *lenA); 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, mod); } return - (sgnR * sgnS); } } } /* 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) { const slong lenW = 22 * lena + 16 * (FLINT_CLOG2(lena) + 1); slong sgnM; mp_ptr W; W = _nmod_vec_init(lenW); if (M == NULL) { sgnM = _nmod_poly_hgcd_recursive(NULL, NULL, A, lenA, B, lenB, a, lena, b, lenb, W, mod, 0, NULL); } else { sgnM = _nmod_poly_hgcd_recursive(M, lenM, A, lenA, B, lenB, a, lena, b, lenb, W, mod, 1, NULL); } _nmod_vec_clear(W); 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; } flint2-2.8.4/nmod_poly/inflate.c000066400000000000000000000024211414523752600165210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "ulong_extras.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; } } flint2-2.8.4/nmod_poly/init.c000066400000000000000000000015551414523752600160510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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; count_leading_zeros(poly->mod.norm, n); } void nmod_poly_init(nmod_poly_t poly, mp_limb_t n) { nmod_poly_init_preinv(poly, n, n_preinvert_limb(n)); } flint2-2.8.4/nmod_poly/init2.c000066400000000000000000000020221414523752600161210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" 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; count_leading_zeros(poly->mod.norm, 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); } flint2-2.8.4/nmod_poly/inlines.c000066400000000000000000000012041414523752600165360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define NMOD_POLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" flint2-2.8.4/nmod_poly/integral.c000066400000000000000000000034051414523752600167070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.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); } flint2-2.8.4/nmod_poly/interpolate_nmod_vec.c000066400000000000000000000024041414523752600213000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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); } } flint2-2.8.4/nmod_poly/interpolate_nmod_vec_barycentric.c000066400000000000000000000034771414523752600237000ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" 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); } } flint2-2.8.4/nmod_poly/interpolate_nmod_vec_fast.c000066400000000000000000000062061414523752600223210ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" 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); } } flint2-2.8.4/nmod_poly/interpolate_nmod_vec_newton.c000066400000000000000000000043001414523752600226670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" 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); } } flint2-2.8.4/nmod_poly/inv_series_basecase.c000066400000000000000000000037631414523752600211050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_inv_series_basecase(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod) { mp_limb_t q; Qlen = FLINT_MIN(Qlen, n); q = Q[0]; if (q != 1) q = n_invmod(q, mod.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] = n_negmod(s, mod.n); else Qinv[i] = n_negmod(n_mulmod2_preinv(s, q, mod.n, mod.ninv), mod.n); } } } 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_printf("Exception (nmod_poly_inv_series_basecase). Division by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/inv_series_newton.c000066400000000000000000000051541414523752600206450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" #define MULLOW(z, x, xn, y, yn, nn, mod) \ if ((xn) >= (yn)) \ _nmod_poly_mullow(z, x, xn, y, yn, nn, mod); \ else \ _nmod_poly_mullow(z, y, yn, x, xn, nn, mod); \ void _nmod_poly_inv_series_newton(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod) { slong cutoff; Qlen = FLINT_MIN(Qlen, n); if (Qlen < 16 || mod.n <= 3) cutoff = 16; else cutoff = 25 * FLINT_BIT_COUNT(mod.n); if (Qlen < cutoff) { _nmod_poly_inv_series_basecase(Qinv, Q, Qlen, n, mod); } else { slong *a, i, m, Qnlen, Wlen, W2len; mp_ptr W; for (i = 1; (WORD(1) << i) < n; i++) ; W = flint_malloc(n * sizeof(mp_limb_t) + i * sizeof(slong)); a = (slong *) (W + n); a[i = 0] = n; while (n >= cutoff) a[++i] = (n = (n + 1) / 2); _nmod_poly_inv_series_basecase(Qinv, Q, Qlen, n, mod); 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, mod); MULLOW(Qinv + m, Qinv, m, W + m, W2len, n - m, mod); _nmod_vec_neg(Qinv + m, Qinv + m, n - m, mod); } flint_free(W); } } void nmod_poly_inv_series_newton(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) { slong Qlen = Q->length; Qlen = FLINT_MIN(Qlen, n); if (Qlen == 0) { flint_printf("Exception (nmod_poly_inv_series_newton). Division by zero.\n"); flint_abort(); } if (Qinv != Q) { nmod_poly_fit_length(Qinv, n); _nmod_poly_inv_series_newton(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_newton(t->coeffs, Q->coeffs, Qlen, n, Qinv->mod); nmod_poly_swap(Qinv, t); nmod_poly_clear(t); } Qinv->length = n; _nmod_poly_normalise(Qinv); } flint2-2.8.4/nmod_poly/invmod.c000066400000000000000000000040551414523752600164000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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) { printf("Exception (nmod_poly_invmod). lenP < 2.\n"); flint_abort(); } 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; } flint2-2.8.4/nmod_poly/invsqrt_series.c000066400000000000000000000052251414523752600201640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "ulong_extras.h" static void __nmod_poly_invsqrt_series_prealloc(mp_ptr g, mp_srcptr h, mp_ptr t, mp_ptr u, slong n, nmod_t mod) { const int alloc = (t == NULL); const slong m = (n + 1) / 2; mp_limb_t c; if (n == 1) { g[0] = UWORD(1); return; } if (alloc) { t = _nmod_vec_init(n); u = _nmod_vec_init(n); } __nmod_poly_invsqrt_series_prealloc(g, h, t, u, m, mod); _nmod_vec_zero(g + m, n - m); _nmod_poly_mul(t, g, m, g, m, mod); if (2*m - 1 < n) t[n-1] = UWORD(0); _nmod_poly_mullow(u, t, n, g, n, n, mod); _nmod_poly_mullow(t, u, n, h, n, n, mod); c = n_invmod(mod.n - 2, mod.n); _nmod_vec_scalar_mul_nmod(g + m, t + m, n - m, c, mod); if (alloc) { _nmod_vec_clear(t); _nmod_vec_clear(u); } } void _nmod_poly_invsqrt_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod) { __nmod_poly_invsqrt_series_prealloc(g, h, NULL, NULL, n, mod); } void nmod_poly_invsqrt_series(nmod_poly_t g, const nmod_poly_t h, slong n) { const slong hlen = h->length; mp_ptr g_coeffs, h_coeffs; nmod_poly_t t1; if (n == 0 || h->length == 0 || h->coeffs[0] == 0) { flint_printf("Exception (nmod_poly_invsqrt). Division by zero.\n"); flint_abort(); } if (h->coeffs[0] != UWORD(1)) { flint_printf("Exception (nmod_poly_invsqrt_series). Constant term != 1.\n"); flint_abort(); } if (hlen < n) { h_coeffs = _nmod_vec_init(n); flint_mpn_copyi(h_coeffs, h->coeffs, hlen); flint_mpn_zero(h_coeffs + hlen, n - hlen); } else h_coeffs = h->coeffs; if (h == g && hlen >= 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_invsqrt_series(g_coeffs, h_coeffs, n, h->mod); if (h == g && hlen >= n) { nmod_poly_swap(g, t1); nmod_poly_clear(t1); } g->length = n; if (hlen < n) _nmod_vec_clear(h_coeffs); _nmod_poly_normalise(g); } flint2-2.8.4/nmod_poly/log_series.c000066400000000000000000000027701414523752600172410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_log_series(mp_ptr res, mp_srcptr f, slong flen, slong n, nmod_t mod) { flen = FLINT_MIN(flen, n); if (flen == 1) { res[0] = 1; _nmod_vec_zero(res + 1, n - 1); } else { mp_ptr tmp = _nmod_vec_init(2 * n); _nmod_poly_derivative(tmp, f, flen, mod); _nmod_poly_div_series(tmp + n, tmp, flen - 1, f, FLINT_MIN(flen, n - 1), n - 1, mod); _nmod_poly_integral(res, tmp + n, n, mod); _nmod_vec_clear(tmp); } } 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_printf("Exception (nmod_poly_log_series). Constant term != 1.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/log_series_monomial_ui.c000066400000000000000000000043411414523752600216250ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_log_series_monomial_ui(mp_ptr res, mp_limb_t coeff, ulong power, slong n, nmod_t mod) { slong j, k, rlen; mp_limb_t a; _nmod_vec_zero(res, n); if (power >= n) return; rlen = (n - 1) / power; a = coeff; coeff = n_negmod(coeff, mod.n); /* Construct geometric series */ if (coeff == UWORD(1)) { for (j = 0; j < rlen; j++) res[j] = a; } else if (a == UWORD(1)) { for (j = 0; j < rlen; j++) res[j] = (j % 2) ? coeff : a; } else { for (j = 0; j < rlen; j++) { res[j] = a; a = n_mulmod2_preinv(a, coeff, mod.n, mod.ninv); } } /* Integrate */ _nmod_poly_integral(res, res, rlen + 1, mod); /* Expand */ if (power != 1) { for (j = rlen * power + 1; j < n; j++) res[j] = UWORD(0); for (j = rlen; j > 0; j--) { res[j * power] = res[j]; for (k = power; k > 0; k--) res[j * power - k] = UWORD(0); } } } void nmod_poly_log_series_monomial_ui(nmod_poly_t res, mp_limb_t coeff, ulong power, slong n) { if (power == 0) { flint_printf("Exception (nmod_poly_log_series_monomial_ui). \n" "Constant term != 1.\n"); flint_abort(); } if (coeff != UWORD(1)) coeff = n_mod2_preinv(coeff, res->mod.n, res->mod.ninv); if (n <= 1 || coeff == UWORD(0)) { nmod_poly_zero(res); return; } nmod_poly_fit_length(res, n); _nmod_poly_log_series_monomial_ui(res->coeffs, coeff, power, n, res->mod); res->length = n; _nmod_poly_normalise(res); } flint2-2.8.4/nmod_poly/make_monic.c000066400000000000000000000022331414523752600172020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.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_printf("Exception (nmod_poly_make_monic). Division by zero.\n"); flint_abort(); } nmod_poly_fit_length(output, input->length); _nmod_poly_make_monic(output->coeffs, input->coeffs, input->length, input->mod); output->length = input->length; } flint2-2.8.4/nmod_poly/mul.c000066400000000000000000000047531414523752600157060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" 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 = FLINT_BITS - (slong) mod.norm; cutoff_len = FLINT_MIN(len1, 2 * len2); 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); } flint2-2.8.4/nmod_poly/mul_KS.c000066400000000000000000000066331414523752600163020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.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) mpn_sqr(res, mpn1, limbs1); else 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); } flint2-2.8.4/nmod_poly/mul_KS2.c000066400000000000000000000155611414523752600163640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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 */ mpn_mul(v3m, v1m, k1, v2m, k2); 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) */ mpn_sqr(v3m, v1m, k1); 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); } flint2-2.8.4/nmod_poly/mul_KS4.c000066400000000000000000000272261414523752600163670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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 */ mpn_mul(v3pn, v1pn, k1, v2pn, k2); 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 */ mpn_sqr(v3pn, v1pn, k1); 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 */ mpn_mul(v3pr, v1pr, k1, v2pr, k2); 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 */ mpn_sqr(v3pr, v1pr, k1); 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); } flint2-2.8.4/nmod_poly/mul_classical.c000066400000000000000000000106331414523752600177160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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); } flint2-2.8.4/nmod_poly/mulhigh.c000066400000000000000000000045171414523752600165440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #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); } flint2-2.8.4/nmod_poly/mulhigh_classical.c000066400000000000000000000112121414523752600205500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.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); } flint2-2.8.4/nmod_poly/mullow.c000066400000000000000000000046441414523752600164270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" 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; } bits = FLINT_BITS - (slong) mod.norm; 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); } flint2-2.8.4/nmod_poly/mullow_KS.c000066400000000000000000000070241414523752600170170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.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) mpn_sqr(res, mpn1, limbs1); else 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); } flint2-2.8.4/nmod_poly/mullow_classical.c000066400000000000000000000115111414523752600204340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.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); } flint2-2.8.4/nmod_poly/mulmod.c000066400000000000000000000042731414523752600164030ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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_printf("Exception (nmod_poly_mulmod). Divide by zero.\n"); flint_abort(); } 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); } } flint2-2.8.4/nmod_poly/mulmod_preinv.c000066400000000000000000000052501414523752600177620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #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_printf("Exception (nmod_poly_mulmod_preinv). Divide by zero.\n"); flint_abort(); } if (lenf <= len1 || lenf <= len2) { flint_printf("Exception (nmod_poly_mulmod_preinv). Input larger than modulus.\n"); flint_abort(); } 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); } } flint2-2.8.4/nmod_poly/multi_crt.c000066400000000000000000000304321414523752600171040ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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 = (const nmod_poly_struct **) TMP_ALLOC(len*sizeof(nmod_poly_struct *)); for (i = 0; i < len; i++) { m[i] = moduli + i; } success = nmod_poly_multi_crt_precompute_p(P, (const nmod_poly_struct * const *) m, len); 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); } } } flint2-2.8.4/nmod_poly/neg.c000066400000000000000000000013441414523752600156530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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; } flint2-2.8.4/nmod_poly/pow.c000066400000000000000000000037701414523752600157140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.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); } flint2-2.8.4/nmod_poly/pow_binexp.c000066400000000000000000000070021414523752600172510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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); } flint2-2.8.4/nmod_poly/pow_trunc.c000066400000000000000000000045611414523752600171260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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); } flint2-2.8.4/nmod_poly/pow_trunc_binexp.c000066400000000000000000000075151414523752600204750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" 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); } flint2-2.8.4/nmod_poly/power_sums.c000066400000000000000000000045601414523752600173100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.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_printf ("Exception (nmod_poly_power_sums_naive). Zero polynomial.\n"); abort(); } 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); } } flint2-2.8.4/nmod_poly/power_sums_naive.c000066400000000000000000000051231414523752600204660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" 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_printf ("Exception (nmod_poly_power_sums_naive). Zero polynomial.\n"); abort(); } 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); } } flint2-2.8.4/nmod_poly/power_sums_schoenhage.c000066400000000000000000000045501414523752600214730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" 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_printf ("Exception (nmod_poly_power_sums_schoenhage). Zero polynomial.\n"); abort(); } 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); } } flint2-2.8.4/nmod_poly/power_sums_to_poly.c000066400000000000000000000032371414523752600210550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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); } } flint2-2.8.4/nmod_poly/power_sums_to_poly_naive.c000066400000000000000000000043661414523752600222430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" 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); } } flint2-2.8.4/nmod_poly/power_sums_to_poly_schoenhage.c000066400000000000000000000036111414523752600232350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" 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); } } flint2-2.8.4/nmod_poly/powers_mod_bsgs_threaded.c000066400000000000000000000145221414523752600221400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.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_printf("Exception (nmod_poly_powers_mod_naive). Divide by zero.\n"); flint_abort(); } 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_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); } flint2-2.8.4/nmod_poly/powers_mod_naive.c000066400000000000000000000065501414523752600204460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.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 _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_printf("Exception (nmod_poly_powers_mod_naive). Divide by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/powmod_fmpz_binexp.c000066400000000000000000000076361414523752600210220ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.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_printf("Exception (nmod_poly_powmod_fmpz_binexp). Divide by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/powmod_fmpz_binexp_preinv.c000066400000000000000000000105311414523752600223710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.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_printf("Exception (nmod_poly_powmod_fmpz_binexp_preinv). Divide by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/powmod_mpz_binexp.c000066400000000000000000000103401414523752600206360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" static __inline__ mp_limb_t n_powmod2_mpz(mp_limb_t a, mpz_srcptr exp, mp_limb_t n, mp_limb_t ninv) { if (mpz_fits_slong_p(exp)) { return n_powmod2_preinv(a, flint_mpz_get_si(exp), n, ninv); } else { mpz_t t, m; mp_limb_t y; mpz_init(t); mpz_init(m); flint_mpz_set_ui(t, a); flint_mpz_set_ui(m, n); mpz_powm(t, t, exp, m); y = flint_mpz_get_ui(t); mpz_clear(t); mpz_clear(m); return y; } } void _nmod_poly_powmod_mpz_binexp(mp_ptr res, mp_srcptr poly, mpz_srcptr e, mp_srcptr f, slong lenf, nmod_t mod) { mp_ptr T, Q; slong lenT, lenQ; slong i; if (lenf == 2) { res[0] = n_powmod2_mpz(poly[0], e, mod.n, mod.ninv); return; } lenT = 2 * lenf - 3; lenQ = lenT - lenf + 1; T = _nmod_vec_init(lenT + lenQ); Q = T + lenT; _nmod_vec_set(res, poly, lenf - 1); for (i = mpz_sizeinbase(e, 2) - 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 (mpz_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_mpz_binexp(nmod_poly_t res, const nmod_poly_t poly, mpz_srcptr 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_printf("Exception (nmod_poly_powmod). Divide by zero.\n"); flint_abort(); } if (lenf == 1) { nmod_poly_zero(res); return; } if (mpz_sgn(e) < 0) { flint_printf("Exception (nmod_poly_powmod). Negative exp not implemented.\n"); flint_abort(); } 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_mpz_binexp(res, r, e, f); nmod_poly_clear(t); nmod_poly_clear(r); return; } if (mpz_fits_ulong_p(e)) { ulong exp = flint_mpz_get_ui(e); if (exp <= 2) { if (exp == 0) { nmod_poly_fit_length(res, 1); res->coeffs[0] = 1; res->length = 1; } else if (exp == 1) { nmod_poly_set(res, poly); } else nmod_poly_mulmod(res, poly, poly, f); return; } } if (len == 0) { nmod_poly_zero(res); 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) || res == f) { nmod_poly_t t; nmod_poly_init2(t, poly->mod.n, trunc); _nmod_poly_powmod_mpz_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_mpz_binexp(res->coeffs, p, e, f->coeffs, lenf, poly->mod); } if (pcopy) _nmod_vec_clear(p); res->length = trunc; _nmod_poly_normalise(res); } flint2-2.8.4/nmod_poly/powmod_mpz_binexp_preinv.c000066400000000000000000000112771414523752600222330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" static __inline__ mp_limb_t n_powmod2_mpz(mp_limb_t a, mpz_srcptr exp, mp_limb_t n, mp_limb_t ninv) { if (mpz_fits_slong_p(exp)) { return n_powmod2_preinv(a, flint_mpz_get_si(exp), n, ninv); } else { mpz_t t, m; mp_limb_t y; mpz_init(t); mpz_init(m); flint_mpz_set_ui(t, a); flint_mpz_set_ui(m, n); mpz_powm(t, t, exp, m); y = flint_mpz_get_ui(t); mpz_clear(t); mpz_clear(m); return y; } } void _nmod_poly_powmod_mpz_binexp_preinv(mp_ptr res, mp_srcptr poly, mpz_srcptr e, mp_srcptr f, slong lenf, mp_srcptr finv, slong lenfinv, nmod_t mod) { mp_ptr T, Q; slong lenT, lenQ; slong i; if (lenf == 2) { res[0] = n_powmod2_mpz(poly[0], e, mod.n, mod.ninv); return; } lenT = 2 * lenf - 3; lenQ = lenT - lenf + 1; T = _nmod_vec_init(lenT + lenQ); Q = T + lenT; _nmod_vec_set(res, poly, lenf - 1); for (i = mpz_sizeinbase(e, 2) - 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 (mpz_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_mpz_binexp_preinv(nmod_poly_t res, const nmod_poly_t poly, mpz_srcptr 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_printf("Exception (nmod_poly_powmod_mpz_binexp_preinv). Divide by zero.\n"); flint_abort(); } if (lenf == 1) { nmod_poly_zero(res); return; } if (mpz_sgn(e) < 0) { flint_printf("Exception (nmod_poly_powmod_mpz_binexp_preinv). Negative exp not implemented.\n"); flint_abort(); } 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_mpz_binexp(res, r, e, f); nmod_poly_clear(t); nmod_poly_clear(r); return; } if (mpz_fits_ulong_p(e)) { ulong exp = flint_mpz_get_ui(e); if (exp <= 2) { if (exp == 0) { nmod_poly_fit_length(res, 1); res->coeffs[0] = 1; res->length = 1; } else if (exp == 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 (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) || res == f || res == finv) { nmod_poly_t t; nmod_poly_init2(t, poly->mod.n, trunc); _nmod_poly_powmod_mpz_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_mpz_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); } flint2-2.8.4/nmod_poly/powmod_ui_binexp.c000066400000000000000000000070131414523752600204500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" 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_printf("Exception (nmod_poly_powmod_ui_binexp). Divide by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/powmod_ui_binexp_preinv.c000066400000000000000000000075351414523752600220440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" 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_printf("Exception (nmod_poly_powmod_ui_binexp_preinv). Divide by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/powmod_x_fmpz_preinv.c000066400000000000000000000116551414523752600213630ustar00rootroot00000000000000/* Copyright (C) 2010 Sebastian Pancratz Copyright (C) 2010 William Hart 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "long_extras.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_printf("Exception (nmod_poly_powmod_x_fmpz_preinv). Divide by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/powmod_x_ui_preinv.c000066400000000000000000000115031414523752600210140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "long_extras.h" 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_printf("Exception (nmod_poly_powmod_x_ui_preinv). Divide by zero.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/product_roots_nmod_vec.c000066400000000000000000000033041414523752600216600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "ulong_extras.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; } flint2-2.8.4/nmod_poly/profile/000077500000000000000000000000001414523752600163745ustar00rootroot00000000000000flint2-2.8.4/nmod_poly/profile/p-evaluate_mat.c000066400000000000000000000044661414523752600214560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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() { FLINT_TEST_INIT(state); slong dim, len, i; int result; nmod_mat_t A, B, C; nmod_poly_t poly; mp_limb_t n = n_randtest_not_zero(state); clock_t horner_begin, paterson_begin; double horner_time, paterson_time; 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; } flint2-2.8.4/nmod_poly/profile/p-gcd.c000066400000000000000000000114311414523752600175320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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) { FLINT_TEST_INIT(state); 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; 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 EXIT_SUCCESS; } flint2-2.8.4/nmod_poly/profile/p-mul.c000066400000000000000000000042311414523752600175720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; FLINT_TEST_INIT(state); nmod_poly_t a, b, c; mp_limb_t 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) 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 #include #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; FLINT_TEST_INIT(state); nmod_poly_t a, b, c, d, dinv; mp_limb_t 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) 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 #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.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 = 3, attempts; while (i <= len/2) { attempts = 0; while (i == len/2 || attempts < 2*len) { nmod_poly_randtest_monic_sparse(poly, state, len, i); if (!nmod_poly_is_zero(poly) && nmod_poly_is_irreducible(poly)) return; attempts++; } i++; } } 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); } flint2-2.8.4/nmod_poly/randtest_monic_primitive.c000066400000000000000000000016121414523752600222010ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/nmod_poly/realloc.c000066400000000000000000000017471414523752600165320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #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); } } flint2-2.8.4/nmod_poly/rem.c000066400000000000000000000037231414523752600156700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_rem(mp_ptr R, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { TMP_INIT; if (lenA - lenB == 1) { _nmod_poly_rem_q1(R, A, lenA, B, lenB, mod); } else if (lenA < NMOD_DIVREM_DIVCONQUER_CUTOFF) { mp_ptr W; TMP_START; W = TMP_ALLOC(NMOD_DIVREM_BC_ITCH(lenA, lenB, mod)*sizeof(mp_limb_t)); _nmod_poly_rem_basecase(R, W, A, lenA, B, lenB, mod); TMP_END; } else { mp_ptr Q = _nmod_vec_init(lenA - lenB + 1); _nmod_poly_divrem(Q, R, A, lenA, B, lenB, mod); _nmod_vec_clear(Q); } } 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_printf("Exception (nmod_poly_rem). Division by zero.\n"); flint_abort(); } if (lenA < lenB) { nmod_poly_set(R, A); return; } if (R == A || 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 == A || R == B) { nmod_poly_swap(R, tR); nmod_poly_clear(tR); } R->length = lenB - 1; _nmod_poly_normalise(R); } flint2-2.8.4/nmod_poly/rem_basecase.c000066400000000000000000000122271414523752600175150ustar00rootroot00000000000000/* Copyright (C) 2010, 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_rem_basecase_1(mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { if (lenB > 1) { const mp_limb_t invL = n_invmod(B[lenB - 1], mod.n); slong iR; mp_ptr R1 = W; flint_mpn_copyi(R1, A, lenA); for (iR = lenA - 1; iR >= lenB - 1; iR--) { if (R1[iR] != 0) { const mp_limb_t q = n_mulmod2_preinv(R1[iR], invL, mod.n, mod.ninv); const mp_limb_t c = n_negmod(q, mod.n); mpn_addmul_1(R1 + iR - lenB + 1, B, lenB - 1, c); } } _nmod_vec_reduce(R, R1, lenB - 1, mod); } } void _nmod_poly_rem_basecase_2(mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { if (lenB > 1) { const mp_limb_t invL = n_invmod(B[lenB - 1], mod.n); slong iR, i; mp_ptr B2 = W, R2 = W + 2*(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; iR--) { const mp_limb_t r = n_ll_mod_preinv(R2[2 * iR + 1], R2[2 * iR], mod.n, mod.ninv); if (r != 0) { const mp_limb_t q = n_mulmod2_preinv(r, invL, mod.n, mod.ninv); const mp_limb_t c = n_negmod(q, mod.n); mpn_addmul_1(R2 + 2 * (iR - lenB + 1), B2, 2 * lenB - 2, c); } } 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_rem_basecase_3(mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { if (lenB > 1) { const mp_limb_t invL = n_invmod(B[lenB - 1], mod.n); slong iR, i; mp_ptr B3 = W, R3 = W + 3*(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; iR--) { const mp_limb_t r = n_lll_mod_preinv(R3[3*iR + 2], R3[3*iR + 1], R3[3*iR], mod.n, mod.ninv); if (r != 0) { const mp_limb_t q = n_mulmod2_preinv(r, invL, mod.n, mod.ninv); const mp_limb_t c = n_negmod(q, mod.n); mpn_addmul_1(R3 + 3 * (iR - lenB + 1), B3, 3 * lenB - 3, c); } } 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_rem_basecase(mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { const slong bits = 2 * (FLINT_BITS - mod.norm) + FLINT_BIT_COUNT(lenA - lenB + 1); if (bits <= FLINT_BITS) _nmod_poly_rem_basecase_1(R, W, A, lenA, B, lenB, mod); else if (bits <= 2 * FLINT_BITS) _nmod_poly_rem_basecase_2(R, W, A, lenA, B, lenB, mod); else _nmod_poly_rem_basecase_3(R, W, A, lenA, B, lenB, mod); } void nmod_poly_rem_basecase(nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B) { const slong lenA = A->length, lenB = B->length; mp_ptr r, W; nmod_poly_t t; TMP_INIT; if (lenB == 0) { flint_printf("Exception (nmod_poly_rem_basecase). Division by zero.\n"); flint_abort(); } if (lenA < lenB) { nmod_poly_set(R, A); return; } if (R == A || R == B) { nmod_poly_init2_preinv(t, B->mod.n, B->mod.ninv, lenB - 1); r = t->coeffs; } else { nmod_poly_fit_length(R, lenB - 1); r = R->coeffs; } TMP_START; W = TMP_ALLOC(NMOD_DIVREM_BC_ITCH(lenA, lenB, A->mod)*sizeof(mp_limb_t)); _nmod_poly_rem_basecase(r, W, A->coeffs, lenA, B->coeffs, lenB, B->mod); if (R == A || R == B) { nmod_poly_swap(R, t); nmod_poly_clear(t); } R->length = lenB - 1; TMP_END; _nmod_poly_normalise(R); } flint2-2.8.4/nmod_poly/rem_q1.c000066400000000000000000000037141414523752600162710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.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; } } } flint2-2.8.4/nmod_poly/remove.c000066400000000000000000000020211414523752600163700ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/nmod_poly/resultant_euclidean.c000066400000000000000000000061671414523752600211440ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "mpn_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" 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; } flint2-2.8.4/nmod_poly/resultant_hgcd.c000066400000000000000000000142261414523752600201130ustar00rootroot00000000000000/* Copyright (C) 2011 William Hart Copyright (C) 2011, 2012 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "mpn_extras.h" #define __set(B, lenB, A, lenA) \ do { \ _nmod_vec_set((B), (A), (lenA)); \ (lenB) = (lenA); \ } while (0) #define __rem(R, lenR, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ _nmod_poly_rem((R), (A), (lenA), (B), (lenB), mod); \ (lenR) = (lenB) - 1; \ MPN_NORM((R), (lenR)); \ } \ else \ { \ _nmod_vec_set((R), (A), (lenA)); \ (lenR) = (lenA); \ } \ } while (0) /* XXX: Currently supports aliasing between {A,a} and {B,b}. */ slong _nmod_poly_hgcd_res(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, mp_limb_t * r) { const slong lenW = 22 * lena + 16 * (FLINT_CLOG2(lena) + 1); slong sgnM; nmod_poly_res_t res; mp_ptr W; res->res = *r; res->lc = b[lenb - 1]; res->len0 = lena; res->len1 = lenb; res->off = 0; W = _nmod_vec_init(lenW); if (M == NULL) { sgnM = _nmod_poly_hgcd_recursive(NULL, NULL, A, lenA, B, lenB, a, lena, b, lenb, W, mod, 0, res); } else { sgnM = _nmod_poly_hgcd_recursive(M, lenM, A, lenA, B, lenB, a, lena, b, lenb, W, mod, 1, res); } if (*lenB < lenb) /* make sure something happened */ { if (*lenB >= 1) { res->lc = n_powmod2_preinv(res->lc, res->len0 - *lenB, mod.n, mod.ninv); res->res = n_mulmod2_preinv(res->res, res->lc, mod.n, mod.ninv); if (((res->len0 | res->len1) & 1) == 0) res->res = nmod_neg(res->res, mod); } else { if (res->len1 == 1) { res->lc = n_powmod2_preinv(res->lc, res->len0 - 1, mod.n, mod.ninv); res->res = n_mulmod2_preinv(res->res, res->lc, mod.n, mod.ninv); } else res->res = 0; } } *r = res->res; _nmod_vec_clear(W); return sgnM; } /* XXX: Incidentally, this implementation currently supports aliasing. But since this may change in the future, no function other than nmod_poly_resultant_hgcd() should rely on this. */ mp_limb_t _nmod_poly_resultant_hgcd(mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { const slong cutoff = FLINT_BIT_COUNT(mod.n) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; mp_ptr G = _nmod_vec_init(FLINT_MIN(lenA, lenB)); mp_ptr J = _nmod_vec_init(2 * lenB); mp_ptr R = J + lenB; mp_limb_t res = 1; slong lenG, lenJ, lenR; mp_limb_t lc = B[lenB - 1]; __rem(R, lenR, A, lenA, B, lenB); if (lenR == 0) { if (lenB == 1) { lc = n_powmod2_preinv(lc, lenA - 1, mod.n, mod.ninv); res = n_mulmod2_preinv(res, lc, mod.n, mod.ninv); } else res = 0; } else { lc = n_powmod2_preinv(lc, lenA - lenR, mod.n, mod.ninv); res = n_mulmod2_preinv(res, lc, mod.n, mod.ninv); if (((lenA | lenB) & 1) == 0) res = nmod_neg(res, mod); _nmod_poly_hgcd_res(NULL, NULL, G, &(lenG), J, &(lenJ), B, lenB, R, lenR, mod, &res); while (lenJ != 0) { lc = J[lenJ - 1]; __rem(R, lenR, G, lenG, J, lenJ); if (lenR == 0) { if (lenJ == 1) { lc = n_powmod2_preinv(lc, lenG - 1, mod.n, mod.ninv); res = n_mulmod2_preinv(res, lc, mod.n, mod.ninv); } else res = 0; break; } else { lc = n_powmod2_preinv(lc, lenG - lenR, mod.n, mod.ninv); res = n_mulmod2_preinv(res, lc, mod.n, mod.ninv); if (((lenG | lenJ) & 1) == 0) res = nmod_neg(res, mod); } if (lenJ < cutoff) { mp_limb_t r = _nmod_poly_resultant_euclidean(J, lenJ, R, lenR, mod); res = n_mulmod2_preinv(res, r, mod.n, mod.ninv); break; } _nmod_poly_hgcd_res(NULL, NULL, G, &(lenG), J, &(lenJ), J, lenJ, R, lenR, mod, &res); } } _nmod_vec_clear(J); _nmod_vec_clear(G); return res; } mp_limb_t nmod_poly_resultant_hgcd(const nmod_poly_t A, const nmod_poly_t B) { mp_limb_t res; if (A->length == 0 || B->length == 0) { return 0; } if (A->length < B->length) { res = nmod_poly_resultant_hgcd(B, A); if (((A->length | B->length) & 1) == 0) res = nmod_neg(res, A->mod); } else /* lenA >= lenB >= 0 */ { slong lenA = A->length, lenB = B->length; /* lenA >= lenB >= 1 */ res = _nmod_poly_resultant_hgcd(A->coeffs, lenA, B->coeffs, lenB, A->mod); } return res; } #undef __set #undef __rem flint2-2.8.4/nmod_poly/reverse.c000066400000000000000000000024501414523752600165540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/nmod_poly/revert_series.c000066400000000000000000000034761414523752600177730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_revert_series(mp_ptr Qinv, mp_srcptr Q, slong n, nmod_t mod) { _nmod_poly_revert_series_lagrange_fast(Qinv, Q, n, mod); } void nmod_poly_revert_series(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) { mp_ptr Qinv_coeffs, Q_coeffs; nmod_poly_t t1; slong Qlen; Qlen = Q->length; if (Qlen < 2 || Q->coeffs[0] != 0 || Q->coeffs[1] == 0) { flint_printf("Exception (nmod_poly_revert_series). Input must have \n" "zero constant and an invertible coefficient of x^1.\n"); flint_abort(); } if (Qlen < n) { Q_coeffs = _nmod_vec_init(n); flint_mpn_copyi(Q_coeffs, Q->coeffs, Qlen); flint_mpn_zero(Q_coeffs + Qlen, n - Qlen); } else Q_coeffs = Q->coeffs; if (Q == Qinv && Qlen >= n) { nmod_poly_init2(t1, Q->mod.n, n); Qinv_coeffs = t1->coeffs; } else { nmod_poly_fit_length(Qinv, n); Qinv_coeffs = Qinv->coeffs; } _nmod_poly_revert_series(Qinv_coeffs, Q_coeffs, n, Q->mod); if (Q == Qinv && Qlen >= n) { nmod_poly_swap(Qinv, t1); nmod_poly_clear(t1); } Qinv->length = n; if (Qlen < n) _nmod_vec_clear(Q_coeffs); _nmod_poly_normalise(Qinv); } flint2-2.8.4/nmod_poly/revert_series_lagrange.c000066400000000000000000000045661414523752600216340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_revert_series_lagrange(mp_ptr Qinv, mp_srcptr Q, slong n, nmod_t mod) { slong i; mp_ptr R, S, T, tmp; if (n >= 1) Qinv[0] = UWORD(0); if (n >= 2) Qinv[1] = n_invmod(Q[1], mod.n); if (n <= 2) return; R = _nmod_vec_init(n - 1); S = _nmod_vec_init(n - 1); T = _nmod_vec_init(n - 1); _nmod_poly_inv_series(R, Q + 1, n - 1, n - 1, mod); _nmod_vec_set(S, R, n - 1); for (i = 2; i < n; i++) { _nmod_poly_mullow(T, S, n - 1, R, n - 1, n - 1, mod); Qinv[i] = nmod_div(T[i - 1], i, mod); tmp = S; S = T; T = tmp; } _nmod_vec_clear(R); _nmod_vec_clear(S); _nmod_vec_clear(T); } void nmod_poly_revert_series_lagrange(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) { mp_ptr Qinv_coeffs, Q_coeffs; nmod_poly_t t1; slong Qlen; Qlen = Q->length; if (Qlen < 2 || Q->coeffs[0] != 0 || Q->coeffs[1] == 0) { flint_printf("Exception (nmod_poly_revert_series_lagrange). Input must \n" "have zero constant and an invertible coefficient of x^1.\n"); flint_abort(); } if (Qlen < n) { Q_coeffs = _nmod_vec_init(n); flint_mpn_copyi(Q_coeffs, Q->coeffs, Qlen); flint_mpn_zero(Q_coeffs + Qlen, n - Qlen); } else Q_coeffs = Q->coeffs; if (Q == Qinv && Qlen >= n) { nmod_poly_init2(t1, Q->mod.n, n); Qinv_coeffs = t1->coeffs; } else { nmod_poly_fit_length(Qinv, n); Qinv_coeffs = Qinv->coeffs; } _nmod_poly_revert_series_lagrange(Qinv_coeffs, Q_coeffs, n, Q->mod); if (Q == Qinv && Qlen >= n) { nmod_poly_swap(Qinv, t1); nmod_poly_clear(t1); } Qinv->length = n; if (Qlen < n) _nmod_vec_clear(Q_coeffs); _nmod_poly_normalise(Qinv); } flint2-2.8.4/nmod_poly/revert_series_lagrange_fast.c000066400000000000000000000060421414523752600226400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" /* pointer to (x/Q)^i */ #define Ri(ii) (R + (n-1)*((ii)-1)) void _nmod_poly_revert_series_lagrange_fast(mp_ptr Qinv, mp_srcptr Q, slong n, nmod_t mod) { slong i, j, k, m; mp_ptr R, S, T, tmp; if (n >= 1) Qinv[0] = UWORD(0); if (n >= 2) Qinv[1] = n_invmod(Q[1], mod.n); if (n <= 2) return; m = n_sqrt(n); R = _nmod_vec_init((n - 1) * m); S = _nmod_vec_init(n - 1); T = _nmod_vec_init(n - 1); _nmod_poly_inv_series(Ri(1), Q + 1, n - 1, n - 1, mod); for (i = 2; i <= m; i++) _nmod_poly_mullow(Ri(i), Ri(i-1), n - 1, Ri(1), n - 1, n - 1, mod); for (i = 2; i < m; i++) Qinv[i] = nmod_div(Ri(i)[i-1], i, mod); _nmod_vec_set(S, Ri(m), n - 1); for (i = m; i < n; i += m) { Qinv[i] = nmod_div(S[i-1], i, mod); for (j = 1; j < m && i + j < n; j++) { mp_limb_t s; int nlimbs = _nmod_vec_dot_bound_limbs(i + j, mod); NMOD_VEC_DOT(s, k, i + j, S[k], Ri(j)[i+j-1-k], mod, nlimbs); Qinv[i+j] = nmod_div(s, i+j, mod); } if (i + 1 < n) { _nmod_poly_mullow(T, S, n - 1, Ri(m), n - 1, n - 1, mod); tmp = S; S = T; T = tmp; } } _nmod_vec_clear(R); _nmod_vec_clear(S); _nmod_vec_clear(T); } void nmod_poly_revert_series_lagrange_fast(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) { mp_ptr Qinv_coeffs, Q_coeffs; nmod_poly_t t1; slong Qlen; Qlen = Q->length; if (Qlen < 2 || Q->coeffs[0] != 0 || Q->coeffs[1] == 0) { flint_printf("Exception (nmod_poly_revert_series_lagrange_fast). Input must \n" "have zero constant and an invertible coefficient of x^1.\n"); flint_abort(); } if (Qlen < n) { Q_coeffs = _nmod_vec_init(n); flint_mpn_copyi(Q_coeffs, Q->coeffs, Qlen); flint_mpn_zero(Q_coeffs + Qlen, n - Qlen); } else Q_coeffs = Q->coeffs; if (Q == Qinv && Qlen >= n) { nmod_poly_init2(t1, Q->mod.n, n); Qinv_coeffs = t1->coeffs; } else { nmod_poly_fit_length(Qinv, n); Qinv_coeffs = Qinv->coeffs; } _nmod_poly_revert_series_lagrange_fast(Qinv_coeffs, Q_coeffs, n, Q->mod); if (Q == Qinv && Qlen >= n) { nmod_poly_swap(Qinv, t1); nmod_poly_clear(t1); } Qinv->length = n; if (Qlen < n) _nmod_vec_clear(Q_coeffs); _nmod_poly_normalise(Qinv); } flint2-2.8.4/nmod_poly/revert_series_newton.c000066400000000000000000000055221414523752600213570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" #define FLINT_REVERSE_NEWTON_CUTOFF 15 void _nmod_poly_revert_series_newton(mp_ptr Qinv, mp_srcptr Q, slong n, nmod_t mod) { slong *a, i, k; mp_ptr T, U, V; if (n >= 1) Qinv[0] = UWORD(0); if (n >= 2) Qinv[1] = n_invmod(Q[1], mod.n); if (n <= 2) return; T = _nmod_vec_init(n); U = _nmod_vec_init(n); V = _nmod_vec_init(n); k = n; for (i = 1; (WORD(1) << i) < k; i++); a = (slong *) flint_malloc(i * sizeof(slong)); a[i = 0] = k; while (k >= FLINT_REVERSE_NEWTON_CUTOFF) a[++i] = (k = (k + 1) / 2); _nmod_poly_revert_series_lagrange(Qinv, Q, k, mod); _nmod_vec_zero(Qinv + k, n - k); for (i--; i >= 0; i--) { k = a[i]; _nmod_poly_compose_series(T, Q, k, Qinv, k, k, mod); _nmod_poly_derivative(U, T, k, mod); U[k - 1] = UWORD(0); T[1] = UWORD(0); _nmod_poly_div_series(V, T, k, U, k, k, mod); _nmod_poly_derivative(T, Qinv, k, mod); _nmod_poly_mullow(U, V, k, T, k, k, mod); _nmod_vec_sub(Qinv, Qinv, U, k, mod); } flint_free(a); _nmod_vec_clear(T); _nmod_vec_clear(U); _nmod_vec_clear(V); } void nmod_poly_revert_series_newton(nmod_poly_t Qinv, const nmod_poly_t Q, slong n) { mp_ptr Qinv_coeffs, Q_coeffs; nmod_poly_t t1; slong Qlen; Qlen = Q->length; if (Qlen < 2 || Q->coeffs[0] != 0 || Q->coeffs[1] == 0) { flint_printf("Exception (nmod_poly_revert_series_newton). Input must have \n" "zero constant and an invertible coefficient of x^1.\n"); flint_abort(); } if (Qlen < n) { Q_coeffs = _nmod_vec_init(n); flint_mpn_copyi(Q_coeffs, Q->coeffs, Qlen); flint_mpn_zero(Q_coeffs + Qlen, n - Qlen); } else Q_coeffs = Q->coeffs; if (Q == Qinv && Qlen >= n) { nmod_poly_init2(t1, Q->mod.n, n); Qinv_coeffs = t1->coeffs; } else { nmod_poly_fit_length(Qinv, n); Qinv_coeffs = Qinv->coeffs; } _nmod_poly_revert_series_newton(Qinv_coeffs, Q_coeffs, n, Q->mod); if (Q == Qinv && Qlen >= n) { nmod_poly_swap(Qinv, t1); nmod_poly_clear(t1); } Qinv->length = n; if (Qlen < n) _nmod_vec_clear(Q_coeffs); _nmod_poly_normalise(Qinv); } flint2-2.8.4/nmod_poly/scalar_mul_nmod.c000066400000000000000000000016601414523752600202420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" 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 */ } flint2-2.8.4/nmod_poly/set_coeff_ui.c000066400000000000000000000022731414523752600175360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.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; } } } flint2-2.8.4/nmod_poly/set_str.c000066400000000000000000000024271414523752600165700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #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; } flint2-2.8.4/nmod_poly/set_trunc.c000066400000000000000000000016571414523752600171170ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void nmod_poly_set_trunc(nmod_poly_t res, const nmod_poly_t poly, slong n) { if (poly == res) { nmod_poly_truncate(res, n); } else { slong rlen; rlen = FLINT_MIN(n, 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); } } flint2-2.8.4/nmod_poly/shift_left.c000066400000000000000000000015301414523752600172260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #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) { nmod_poly_fit_length(res, poly->length + k); _nmod_poly_shift_left(res->coeffs, poly->coeffs, poly->length, k); res->length = poly->length + k; } flint2-2.8.4/nmod_poly/shift_right.c000066400000000000000000000016611414523752600174160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" 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; } } flint2-2.8.4/nmod_poly/sin_series.c000066400000000000000000000033561414523752600172520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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, 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_printf("Exception (nmod_poly_sin_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/sinh_series.c000066400000000000000000000035561414523752600174240ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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_printf("Exception (nmod_poly_sinh_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/sqrt.c000066400000000000000000000046251414523752600161000ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.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, mod); else { _nmod_vec_scalar_mul_nmod(t, p, slen, n_invmod(d, mod.n), mod); _nmod_poly_sqrt_series(s, t, 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; } flint2-2.8.4/nmod_poly/sqrt_series.c000066400000000000000000000036211414523752600174450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" void _nmod_poly_sqrt_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod) { mp_ptr t = _nmod_vec_init(n); _nmod_poly_invsqrt_series(t, h, n, mod); _nmod_poly_mullow(g, t, n, h, n, n, mod); _nmod_vec_clear(t); } void nmod_poly_sqrt_series(nmod_poly_t g, const nmod_poly_t h, slong n) { mp_ptr g_coeffs, h_coeffs; nmod_poly_t t1; slong hlen; hlen = h->length; if (n == 0) { flint_printf("Exception (nmod_poly_sqrt_series). Division by zero.\n"); flint_abort(); } if (h->length == 0 || h->coeffs[0] != UWORD(1)) { flint_printf("Exception (nmod_poly_sqrt_series). Requires constant term 1.\n"); flint_abort(); } if (hlen < n) { h_coeffs = _nmod_vec_init(n); flint_mpn_copyi(h_coeffs, h->coeffs, hlen); flint_mpn_zero(h_coeffs + hlen, n - hlen); } else h_coeffs = h->coeffs; if (h == g && hlen >= 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_sqrt_series(g_coeffs, h_coeffs, n, h->mod); if (h == g && hlen >= n) { nmod_poly_swap(g, t1); nmod_poly_clear(t1); } g->length = n; if (hlen < n) _nmod_vec_clear(h_coeffs); _nmod_poly_normalise(g); } flint2-2.8.4/nmod_poly/sub.c000066400000000000000000000027331414523752600156760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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 */ } flint2-2.8.4/nmod_poly/sub_series.c000066400000000000000000000021231414523752600172410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #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); } flint2-2.8.4/nmod_poly/sub_ui.c000066400000000000000000000017621414523752600163740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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, 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); } } flint2-2.8.4/nmod_poly/tan_series.c000066400000000000000000000044021414523752600172340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" void _nmod_poly_tan_series(mp_ptr g, mp_srcptr h, slong n, nmod_t mod) { slong m; mp_ptr t, u; if (n <= 3) { g[0] = UWORD(0); if (n >= 2) g[1] = h[1]; if (n >= 3) g[2] = h[2]; return; } m = (n + 1) / 2; _nmod_poly_tan_series(g, h, m, mod); _nmod_vec_zero(g + m, n - m); t = _nmod_vec_init(n); u = _nmod_vec_init(n); _nmod_poly_mul(u, g, m, g, m, mod); u[0] = UWORD(1); if (2*m - 1 < n) u[n-1] = UWORD(0); _nmod_poly_atan_series(t, g, n, mod); _nmod_vec_sub(t + m, h + m, t + m, n - m, mod); _nmod_poly_mullow(g + m, u, n, t + m, n - m, n - m, mod); _nmod_vec_clear(t); _nmod_vec_clear(u); } void nmod_poly_tan_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_printf("Exception (nmod_poly_tan_series). Constant term != 0.\n"); flint_abort(); } 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_tan_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); } flint2-2.8.4/nmod_poly/tanh_series.c000066400000000000000000000032161414523752600174060ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #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_printf("Exception (nmod_poly_tanh_series). Constant term != 0.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly/taylor_shift.c000066400000000000000000000017241414523752600176130ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.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); } flint2-2.8.4/nmod_poly/taylor_shift_convolution.c000066400000000000000000000036401414523752600222510ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" 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); } flint2-2.8.4/nmod_poly/taylor_shift_horner.c000066400000000000000000000023461414523752600211710ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" 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); } flint2-2.8.4/nmod_poly/test/000077500000000000000000000000001414523752600157135ustar00rootroot00000000000000flint2-2.8.4/nmod_poly/test/t-add.c000066400000000000000000000045511414523752600170550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-add_series.c000066400000000000000000000073471414523752600204350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add_series...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-asin_series.c000066400000000000000000000060671414523752600206350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("asin_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-asinh_series.c000066400000000000000000000060571414523752600210040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("asinh_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-atan_series.c000066400000000000000000000060541414523752600206220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("atan_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-atanh_series.c000066400000000000000000000060471414523752600207740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("atanh_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-berlekamp_massey.c000066400000000000000000000133241414523752600216460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_poly.h" int main(void) { slong i, j, k, l; FLINT_TEST_INIT(state); flint_printf("berlekamp_massey...."); fflush(stdout); { 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"); 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"); 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); flint_abort(); } /* Check berlekamp-massey does its job - 2k coeffcients 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-bit_pack.c000066400000000000000000000057521414523752600201050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("bit_pack/bit_unpack...."); fflush(stdout); /* 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"); 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"); abort(); } fmpz_clear(f); nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-compose.c000066400000000000000000000113761414523752600177750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("compose...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(r1); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-compose_divconquer.c000066400000000000000000000067771414523752600222450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("compose_divconquer...."); fflush(stdout); /* 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_divconquer(r1, a, b); nmod_poly_compose_divconquer(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"); 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_divconquer(r1, a, b); nmod_poly_compose_divconquer(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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(r1); } /* Compare with compose_horner */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, r1, r2; 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_init(r2, n); nmod_poly_randtest(a, state, n_randint(state, 30)); nmod_poly_randtest(b, state, n_randint(state, 15)); nmod_poly_compose_divconquer(r1, a, b); nmod_poly_compose_horner(r2, a, b); result = nmod_poly_equal(r1, r2); 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(r2), flint_printf("\n\n"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(r1); nmod_poly_clear(r2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-compose_horner.c000066400000000000000000000060241414523752600213440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("compose_horner...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(r1); nmod_poly_clear(r2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-compose_mod.c000066400000000000000000000115551414523752600206330ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose_mod...."); fflush(stdout); 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"); 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-compose_mod_brent_kung.c000066400000000000000000000121051414523752600230410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung...."); fflush(stdout); 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"); 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-compose_mod_brent_kung_precomp_preinv.c000066400000000000000000000156631414523752600261650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung_precomp_preinv...."); fflush(stdout); 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-compose_mod_brent_kung_precomp_preinv_threaded.c000066400000000000000000000201701414523752600300120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #include #define ulong mp_limb_t #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "thread_support.h" int main(void) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i; #endif FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung_precomp_preinv_threaded...."); fflush(stdout); #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) /* 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; #else FLINT_TEST_CLEANUP(state); flint_printf("SKIPPED\n"); return 0; #endif } flint2-2.8.4/nmod_poly/test/t-compose_mod_brent_kung_preinv.c000066400000000000000000000170141414523752600244300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung_preinv...."); fflush(stdout); 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"); 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"); 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(cinv); nmod_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-compose_mod_brent_kung_vec_preinv.c000066400000000000000000000057151414523752600252720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung_vec_preinv...."); fflush(stdout); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-compose_mod_brent_kung_vec_preinv_threaded.c000066400000000000000000000066231414523752600271310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "thread_support.h" int main(void) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i; slong max_threads = 5; #endif FLINT_TEST_INIT(state); flint_printf("compose_mod_brent_kung_vec_preinv_threaded...."); fflush(stdout); #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); #else FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); #endif return 0; } flint2-2.8.4/nmod_poly/test/t-compose_mod_horner.c000066400000000000000000000116451414523752600222100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose_mod_horner...."); fflush(stdout); 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"); 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-compose_series.c000066400000000000000000000076631414523752600213530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_series...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); nmod_poly_clear(s); nmod_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-compose_series_brent_kung.c000066400000000000000000000077651414523752600235740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_series_brent_kung...."); fflush(stdout); /* 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, 40)); nmod_poly_randtest(h, state, n_randint(state, 20)); nmod_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); nmod_poly_compose_series_brent_kung(f, g, h, n); nmod_poly_compose_series_brent_kung(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"); 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, 40)); nmod_poly_randtest(h, state, n_randint(state, 20)); nmod_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); nmod_poly_compose_series_brent_kung(f, g, h, n); nmod_poly_compose_series_brent_kung(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"); 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, 40)); nmod_poly_randtest(h, state, n_randint(state, 20)); nmod_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); nmod_poly_compose(s, g, h); nmod_poly_truncate(s, n); nmod_poly_compose_series_brent_kung(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"); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); nmod_poly_clear(s); nmod_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-compose_series_divconquer.c000066400000000000000000000073251414523752600236050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("compose_series_divconquer...."); fflush(stdout); /* Aliasing */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong N = n_randint(state, 50); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 30)); nmod_poly_randtest(b, state, n_randint(state, 15)); nmod_poly_compose_series_divconquer(c, a, b, N); nmod_poly_compose_series_divconquer(a, a, b, N); result = nmod_poly_equal(c, a); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(a), flint_printf("\n\n"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Aliasing */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, c; mp_limb_t n = n_randtest_not_zero(state); slong N = n_randint(state, 50); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_randtest(a, state, n_randint(state, 30)); nmod_poly_randtest(b, state, n_randint(state, 15)); nmod_poly_compose_series_divconquer(c, a, b, N); nmod_poly_compose_series_divconquer(b, a, b, N); result = nmod_poly_equal(c, b); if (!result) { flint_printf("FAIL:\n"); flint_printf("a->length = %wd, n = %wu\n", a->length, a->mod.n); nmod_poly_print(c), flint_printf("\n\n"); nmod_poly_print(b), flint_printf("\n\n"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } /* Compare with compose */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, r1, r2; mp_limb_t n = n_randtest_not_zero(state); slong N = n_randint(state, 50); nmod_poly_init(a, n); nmod_poly_init(b, 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, 15)); nmod_poly_compose_series_divconquer(r1, a, b, N); nmod_poly_compose(r2, a, b); nmod_poly_truncate(r2, N); result = nmod_poly_equal(r1, r2); 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(r2), flint_printf("\n\n"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(r1); nmod_poly_clear(r2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/nmod_poly/test/t-compose_series_horner.c000066400000000000000000000077351414523752600227300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("compose_series_horner...."); fflush(stdout); /* 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, 40)); nmod_poly_randtest(h, state, n_randint(state, 20)); nmod_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); nmod_poly_compose_series_horner(f, g, h, n); nmod_poly_compose_series_horner(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"); 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, 40)); nmod_poly_randtest(h, state, n_randint(state, 20)); nmod_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); nmod_poly_compose_series_horner(f, g, h, n); nmod_poly_compose_series_horner(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"); 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, 40)); nmod_poly_randtest(h, state, n_randint(state, 20)); nmod_poly_set_coeff_ui(h, 0, 0); n = n_randint(state, 20); nmod_poly_compose(s, g, h); nmod_poly_truncate(s, n); nmod_poly_compose_series_horner(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"); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); nmod_poly_clear(s); nmod_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-cos_series.c000066400000000000000000000062041414523752600204600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("cos_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-cosh_series.c000066400000000000000000000062401414523752600206300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("cosh_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-deflate.c000066400000000000000000000062131414523752600177260ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("deflate...."); fflush(stdout); 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"); 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"); 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"); 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"); abort(); } nmod_poly_deflate(poly2, poly2, infl); if (!nmod_poly_equal(poly3, poly2)) { flint_printf("FAIL: aliasing\n"); abort(); } } nmod_poly_clear(poly1); nmod_poly_clear(poly2); nmod_poly_clear(poly3); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-derivative.c000066400000000000000000000051571414523752600204720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, j, result = 1; fmpz_t t; FLINT_TEST_INIT(state); flint_printf("derivative...."); fflush(stdout); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-discriminant.c000066400000000000000000000055701414523752600210130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("discriminant...."); fflush(stdout); /* 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); 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); abort(); } nmod_poly_clear(f); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-div.c000066400000000000000000000074121414523752600171060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div...."); fflush(stdout); /* 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-div_basecase.c000066400000000000000000000076731414523752600207450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_basecase...."); fflush(stdout); /* Check result of div against divrem */ for (i = 0; i < 500 * 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, 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_div_basecase(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); 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 < 500 * 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, 200)); do { nmod_poly_randtest(b, state, n_randint(state, 200)); } while (b->length == 0); nmod_poly_div_basecase(q, a, b); nmod_poly_div_basecase(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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } /* Check aliasing of b and q */ for (i = 0; i < 500 * 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, 200)); do { nmod_poly_randtest(b, state, n_randint(state, 200)); } while (b->length == 0); nmod_poly_div_basecase(q, a, b); nmod_poly_div_basecase(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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-div_divconquer.c000066400000000000000000000075171414523752600213530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_divconquer...."); fflush(stdout); /* Check result of div against divrem */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, q2, 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(q2, 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_divconquer(q, r, a, b); nmod_poly_div_divconquer(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); 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_divconquer(q, a, b); nmod_poly_div_divconquer(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); 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_divconquer(q, a, b); nmod_poly_div_divconquer(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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-div_newton.c000066400000000000000000000074671414523752600205120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_newton...."); fflush(stdout); /* Check result of div against divrem */ for (i = 0; i < 100 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q, q2, 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(q2, 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_divconquer(q, r, a, b); nmod_poly_div_newton(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); 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_newton(q, a, b); nmod_poly_div_newton(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); 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_newton(q, a, b); nmod_poly_div_newton(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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-div_newton_n_preinv.c000066400000000000000000000142141414523752600223760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_newton_n_preinv...."); fflush(stdout); /* 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); 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-div_root.c000066400000000000000000000062131414523752600201470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_root...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(P); nmod_poly_clear(Q1); nmod_poly_clear(Q2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-div_series.c000066400000000000000000000100721414523752600204540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_series...."); fflush(stdout); /* 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); 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); 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); abort(); } nmod_poly_clear(q); nmod_poly_clear(a); nmod_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-div_series_basecase.c000066400000000000000000000101601414523752600223000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div_series_basecase...."); fflush(stdout); /* 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); 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); 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); abort(); } nmod_poly_clear(q); nmod_poly_clear(a); nmod_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-divides.c000066400000000000000000000124541414523752600177550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divides...."); fflush(stdout); /* 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); 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-divides_classical.c000066400000000000000000000125561414523752600217760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divides_classical...."); fflush(stdout); /* 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); 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-divrem.c000066400000000000000000000217341414523752600176150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divrem...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); nmod_poly_clear(prod); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-divrem_basecase.c000066400000000000000000000150131414523752600214340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divrem_basecase...."); fflush(stdout); /* 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); 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); 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-divrem_divconquer.c000066400000000000000000000144511414523752600220520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divrem_divconquer...."); fflush(stdout); /* 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(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_divconquer(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); 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_divconquer(q, r, a, b); nmod_poly_divrem_divconquer(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); 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_divconquer(q, r, a, b); nmod_poly_divrem_divconquer(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); 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_divconquer(q, r, a, b); nmod_poly_divrem_divconquer(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); 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_divconquer(q, r, a, b); nmod_poly_divrem_divconquer(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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-divrem_newton.c000066400000000000000000000144071414523752600212060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divrem_newton...."); fflush(stdout); /* 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_newton(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); 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_newton(q, r, a, b); nmod_poly_divrem_newton(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); 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_newton(q, r, a, b); nmod_poly_divrem_newton(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); 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_newton(q, r, a, b); nmod_poly_divrem_newton(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); 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_newton(q, r, a, b); nmod_poly_divrem_newton(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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q); nmod_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-divrem_newton_n_preinv.c000066400000000000000000000255011414523752600231030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divrem_newton_n_preinv...."); fflush(stdout); /* 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_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"); 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); 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, 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); 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); 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); 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(binv); nmod_poly_clear(q); nmod_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-equal_trunc.c000066400000000000000000000053631414523752600206510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("equal_trunc...."); fflush(stdout); /* 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-evaluate_mat_horner.c000066400000000000000000000061401414523752600223450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "fmpz.h" #include "nmod_mat.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("evaluate_mat_horner...."); fflush(stdout); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-evaluate_mat_paterson_stockmeyer.c000066400000000000000000000062411414523752600251520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "fmpz.h" #include "nmod_mat.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("evaluate_mat_paterson_stockmeyer...."); fflush(stdout); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-evaluate_nmod.c000066400000000000000000000051271414523752600211500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, j, result = 1; FLINT_TEST_INIT(state); flint_printf("evaluate_nmod...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-evaluate_nmod_vec_fast.c000066400000000000000000000036161414523752600230230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("evaluate_nmod_vec_fast...."); fflush(stdout); 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"); abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); _nmod_vec_clear(x); _nmod_vec_clear(y); _nmod_vec_clear(z); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-exp_series.c000066400000000000000000000076001414523752600204710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("exp_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-exp_series_basecase.c000066400000000000000000000073001414523752600223140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("exp_series_basecase...."); fflush(stdout); /* 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; 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(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, 100)); nmod_poly_set_coeff_ui(A, 0, UWORD(0)); nmod_poly_randtest(B, state, n_randint(state, 100)); nmod_poly_set_coeff_ui(B, 0, UWORD(0)); 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_basecase(expA, A, n); nmod_poly_exp_series_basecase(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"); 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); 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_exp_series_basecase(B, A, n); nmod_poly_exp_series_basecase(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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-exp_series_monomial_ui.c000066400000000000000000000037431414523752600230650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("exp_series_monomial_ui...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t A, expA, res; slong n; mp_limb_t mod; ulong power; mp_limb_t coeff; mod = n_randtest_prime(state, 0); n = n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(expA, mod); nmod_poly_init(res, mod); coeff = n_randlimb(state) % mod; power = 1 + n_randint(state, 2*n + 1); nmod_poly_set_coeff_ui(A, power, coeff); nmod_poly_exp_series(expA, A, n); nmod_poly_exp_series_monomial_ui(res, coeff, power, n); result = nmod_poly_equal(expA, res); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("power = %wu, coeff = %wu\n", power, coeff); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("exp(A): "); nmod_poly_print(expA), flint_printf("\n\n"); flint_printf("res: "); nmod_poly_print(res), flint_printf("\n\n"); abort(); } nmod_poly_clear(A); nmod_poly_clear(expA); nmod_poly_clear(res); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-find_distinct_nonzero_roots.c000066400000000000000000000055311414523752600241450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_poly.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("find_distinct_nonzero_roots...."); fflush(stdout); 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); 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); flint_abort(); } if (nmod_poly_evaluate_nmod(a, r->coeffs[j]) != 0) { flint_printf("FAIL\ncheck root is a root i = %wd\n", i); 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); flint_abort(); } } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-fread_print.c000066400000000000000000000037631414523752600206260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result, r1; FLINT_TEST_INIT(state); flint_printf("fread_print...."); #if !defined( _MSC_VER ) fflush(stdout); /* 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"); 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"); abort(); } fclose(f); if (remove("nmod_poly_test")) { flint_printf("Error, unable to delete file nmod_poly_test\n"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); #else flint_printf("SKIPPED\n"); #endif return 0; } flint2-2.8.4/nmod_poly/test/t-gcd.c000066400000000000000000000100441414523752600170540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd...."); fflush(stdout); /* 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-gcd_euclidean.c000066400000000000000000000077751414523752600211060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd_euclidean...."); fflush(stdout); /* 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-gcd_hgcd.c000066400000000000000000000100141414523752600200360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd_hgcd...."); fflush(stdout); /* 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-gcdinv.c000066400000000000000000000100501414523752600175660ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); printf("gcdinv...."); fflush(stdout); /* 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-get_set_coeff_ui.c000066400000000000000000000027231414523752600216150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; ulong j; FLINT_TEST_INIT(state); flint_printf("get/set_coeff_ui...."); fflush(stdout); /* 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"); abort(); } nmod_poly_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-get_set_str.c000066400000000000000000000030441414523752600206430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result, r1; FLINT_TEST_INIT(state); flint_printf("get/set_str...."); fflush(stdout); /* 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"); abort(); } flint_free(str); nmod_poly_clear(a); nmod_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-hgcd.c000066400000000000000000000170751414523752600172370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "mpn_extras.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) int main(void) { slong i, j, result; FLINT_TEST_INIT(state); flint_printf("hgcd...."); fflush(stdout); /* 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"); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } #undef __mul flint2-2.8.4/nmod_poly/test/t-inflate.c000066400000000000000000000043731414523752600177510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("inflate...."); fflush(stdout); 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"); 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"); abort(); } nmod_poly_clear(poly1); nmod_poly_clear(poly2); nmod_poly_clear(poly3); nmod_poly_clear(xp); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-init_realloc_clear.c000066400000000000000000000030031414523752600221260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/init2/realloc/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-integral.c000066400000000000000000000050111414523752600201220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("integral...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-interpolate_nmod_vec.c000066400000000000000000000035271414523752600225270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("interpolate_nmod_vec...."); fflush(stdout); 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"); abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); _nmod_vec_clear(x); _nmod_vec_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-interpolate_nmod_vec_barycentric.c000066400000000000000000000036021414523752600251060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("interpolate_nmod_vec_barycentric...."); fflush(stdout); 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"); abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); _nmod_vec_clear(x); _nmod_vec_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-interpolate_nmod_vec_fast.c000066400000000000000000000035541414523752600235440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("interpolate_nmod_vec_fast...."); fflush(stdout); 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"); abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); _nmod_vec_clear(x); _nmod_vec_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-interpolate_nmod_vec_newton.c000066400000000000000000000035701414523752600241170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("interpolate_nmod_vec_newton...."); fflush(stdout); 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"); abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); _nmod_vec_clear(x); _nmod_vec_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-inv_series_basecase.c000066400000000000000000000054511414523752600223210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("inv_series_basecase...."); fflush(stdout); /* 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); 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); abort(); } nmod_poly_clear(q); nmod_poly_clear(qinv); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-inv_series_newton.c000066400000000000000000000054531414523752600220670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("inv_series_newton...."); fflush(stdout); /* 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); 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); abort(); } nmod_poly_clear(q); nmod_poly_clear(qinv); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-invmod.c000066400000000000000000000125251414523752600176210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); printf("invmod...."); fflush(stdout); /* 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); 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(u); } FLINT_TEST_CLEANUP(state); printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-invsqrt_series.c000066400000000000000000000054071414523752600214060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("invsqrt_series...."); fflush(stdout); /* 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); 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); abort(); } nmod_poly_clear(g); nmod_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-log_series.c000066400000000000000000000072131414523752600204560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("log_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-log_series_monomial_ui.c000066400000000000000000000040231414523752600230420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("log_series_monomial_ui...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_poly_t A, logA, res; slong n; mp_limb_t mod; ulong power; mp_limb_t coeff; mod = n_randtest_prime(state, 0); n = n_randtest(state) % 100; n = FLINT_MIN(n, mod); nmod_poly_init(A, mod); nmod_poly_init(logA, mod); nmod_poly_init(res, mod); coeff = n_randlimb(state) % mod; power = 1 + n_randint(state, 2*n + 1); nmod_poly_set_coeff_ui(A, 0, UWORD(1)); nmod_poly_set_coeff_ui(A, power, coeff); nmod_poly_log_series(logA, A, n); nmod_poly_log_series_monomial_ui(res, coeff, power, n); result = nmod_poly_equal(logA, res); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, mod = %wu\n", n, mod); flint_printf("power = %wu, coeff = %wu\n", power, coeff); flint_printf("A: "); nmod_poly_print(A), flint_printf("\n\n"); flint_printf("log(A): "); nmod_poly_print(logA), flint_printf("\n\n"); flint_printf("res: "); nmod_poly_print(res), flint_printf("\n\n"); abort(); } nmod_poly_clear(A); nmod_poly_clear(logA); nmod_poly_clear(res); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-make_monic.c000066400000000000000000000051061414523752600204240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("make_monic...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(a); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-mul.c000066400000000000000000000065271414523752600171270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_clear(a1); nmod_poly_clear(a2); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-mul_KS.c000066400000000000000000000062351414523752600175200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_KS...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_clear(a1); nmod_poly_clear(a2); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-mul_KS2.c000066400000000000000000000121571414523752600176020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" #pragma GCC diagnostic ignored "-Woverlength-strings" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_KS2...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } #endif FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-mul_KS4.c000066400000000000000000000121071414523752600175770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" #pragma GCC diagnostic ignored "-Woverlength-strings" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_KS4...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } #endif FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-mul_classical.c000066400000000000000000000105711414523752600211370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_classical...."); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } nmod_poly_clear(a1); nmod_poly_clear(a2); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-mulhigh.c000066400000000000000000000034331414523752600177600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulhigh...."); fflush(stdout); /* 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-mulhigh_classical.c000066400000000000000000000104041414523752600217720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulhigh_classical...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-mullow.c000066400000000000000000000031161414523752600176400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow...."); fflush(stdout); /* 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-mullow_KS.c000066400000000000000000000071451414523752600202430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow_KS...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_clear(a1); nmod_poly_clear(a2); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-mullow_classical.c000066400000000000000000000101071414523752600216540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mullow_classical...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-mulmod.c000066400000000000000000000135231414523752600176210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulmod...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-mulmod_preinv.c000066400000000000000000000215151414523752600212040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulmod_preinv...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-multi_crt.c000066400000000000000000000342151414523752600203270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_mpoly.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("crt...."); fflush(stdout); /* 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"); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); } printf("PASS\n"); FLINT_TEST_CLEANUP(state); return 0; } flint2-2.8.4/nmod_poly/test/t-neg.c000066400000000000000000000026671414523752600171040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg...."); fflush(stdout); /* 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-pow.c000066400000000000000000000052151414523752600171300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("pow...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-pow_binexp.c000066400000000000000000000053751414523752600205040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("pow_binexp...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-pow_trunc.c000066400000000000000000000056201414523752600203430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow_trunc...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-pow_trunc_binexp.c000066400000000000000000000056541414523752600217170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow_trunc_binexp...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-power_sums.c000066400000000000000000000054451414523752600205330ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("power_sums...."); /* 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); nmod_poly_clear(e); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-power_sums_naive.c000066400000000000000000000155341414523752600217150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" int main(void) { int l, result; mp_limb_t i, j, k, tot; FLINT_TEST_INIT(state); flint_printf("power_sums_naive...."); /* 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"); 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-power_sums_schoenhage.c000066400000000000000000000153661414523752600227220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" int main(void) { int l, result; mp_limb_t i, j, k, tot; FLINT_TEST_INIT(state); flint_printf("power_sums_schoenhage...."); /* 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"); 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-powers_mod_bsgs.c000066400000000000000000000052301414523752600215140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int i, result, max_threads = 5; #endif FLINT_TEST_INIT(state); flint_printf("powers_mod_bsgs...."); fflush(stdout); #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) /* 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); #else FLINT_TEST_CLEANUP(state); flint_printf("SKIPPED\n"); #endif return 0; } flint2-2.8.4/nmod_poly/test/t-powers_mod_naive.c000066400000000000000000000046011414523752600216610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powers_mod_naive...."); fflush(stdout); /* 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-powmod_fmpz_binexp.c000066400000000000000000000122471414523752600222340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_fmpz_binexp...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_clear(exp); nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(res2); nmod_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-powmod_fmpz_binexp_preinv.c000066400000000000000000000160411414523752600236130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_fmpz_binexp_preinv...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-powmod_mpz_binexp.c000066400000000000000000000110531414523752600220600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_mpz_binexp...."); fflush(stdout); /* Aliasing of res and a */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f; mp_limb_t n; ulong exp; mpz_t expz; n = n_randtest_prime(state, 0); exp = n_randlimb(state); flint_mpz_init_set_ui(expz, exp); 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_mpz_binexp(res1, a, expz, f); nmod_poly_powmod_mpz_binexp(a, a, expz, f); result = (nmod_poly_equal(res1, a)); if (!result) { flint_printf("FAIL:\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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(t); mpz_clear(expz); } /* Aliasing of res and f */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f; mp_limb_t n; ulong exp; mpz_t expz; n = n_randtest_prime(state, 0); exp = n_randlimb(state); flint_mpz_init_set_ui(expz, exp); 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_mpz_binexp(res1, a, expz, f); nmod_poly_powmod_mpz_binexp(f, a, expz, f); result = (nmod_poly_equal(res1, f)); if (!result) { flint_printf("FAIL:\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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(t); mpz_clear(expz); } /* No aliasing */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, res2, t, f; mp_limb_t n; ulong exp; mpz_t expz; n = n_randtest_prime(state, 0); exp = n_randlimb(state); 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)); flint_mpz_init_set_ui(expz, exp); nmod_poly_powmod_mpz_binexp(res1, a, expz, f); nmod_poly_powmod_ui_binexp(res2, a, exp, 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("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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(res2); nmod_poly_clear(t); mpz_clear(expz); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-powmod_mpz_binexp_preinv.c000066400000000000000000000152751414523752600234550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_mpz_binexp_preinv...."); fflush(stdout); /* Aliasing of res and a */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f, finv; mp_limb_t n; ulong exp; mpz_t expz; n = n_randtest_prime(state, 0); exp = n_randlimb(state); flint_mpz_init_set_ui(expz, exp); 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_mpz_binexp_preinv(res1, a, expz, f, finv); nmod_poly_powmod_mpz_binexp_preinv(a, a, expz, f, finv); result = (nmod_poly_equal(res1, a)); if (!result) { flint_printf("FAIL:\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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); mpz_clear(expz); } /* Aliasing of res and f */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f, finv; mp_limb_t n; ulong exp; mpz_t expz; n = n_randtest_prime(state, 0); exp = n_randlimb(state); flint_mpz_init_set_ui(expz, exp); 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_mpz_binexp_preinv(res1, a, expz, f, finv); nmod_poly_powmod_mpz_binexp_preinv(f, a, expz, f, finv); result = (nmod_poly_equal(res1, f)); if (!result) { flint_printf("FAIL:\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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); mpz_clear(expz); } /* Aliasing of res and finv */ for (i = 0; i < 25 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, t, f, finv; mp_limb_t n; ulong exp; mpz_t expz; n = n_randtest_prime(state, 0); exp = n_randlimb(state); flint_mpz_init_set_ui(expz, exp); 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_mpz_binexp_preinv(res1, a, expz, f, finv); nmod_poly_powmod_mpz_binexp_preinv(finv, a, expz, f, finv); result = (nmod_poly_equal(res1, finv)); if (!result) { flint_printf("FAIL:\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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); mpz_clear(expz); } /* No aliasing */ for (i = 0; i < 50 * flint_test_multiplier(); i++) { nmod_poly_t a, res1, res2, t, f, finv; mp_limb_t n; ulong exp; mpz_t expz; n = n_randtest_prime(state, 0); exp = n_randlimb(state); 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)); flint_mpz_init_set_ui(expz, exp); nmod_poly_reverse(finv, f, f->length); nmod_poly_inv_series(finv, finv, f->length); nmod_poly_powmod_mpz_binexp_preinv(res1, a, expz, 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("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"); 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); mpz_clear(expz); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-powmod_ui_binexp.c000066400000000000000000000111221414523752600216640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_ui_binexp...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(res2); nmod_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-powmod_ui_binexp_preinv.c000066400000000000000000000154101414523752600232530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_ui_binexp_preinv...."); fflush(stdout); /* 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-powmod_x_fmpz_binexp.c000066400000000000000000000122601414523752600225560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_x_fmpz_preinv...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } fmpz_clear(exp); nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-powmod_x_ui_binexp.c000066400000000000000000000115061414523752600222210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_x_ui_preinv...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_clear(f); nmod_poly_clear(finv); nmod_poly_clear(res1); nmod_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-product_roots_nmod_vec.c000066400000000000000000000035401414523752600231020ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("product_roots_nmod_vec...."); fflush(stdout); 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"); abort(); } nmod_poly_clear(P); nmod_poly_clear(Q); nmod_poly_clear(tmp); _nmod_vec_clear(x); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-rem.c000066400000000000000000000123741414523752600171120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("rem...."); fflush(stdout); /* 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); 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q0); nmod_poly_clear(r0); nmod_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-rem_basecase.c000066400000000000000000000100551414523752600207320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("rem_basecase...."); fflush(stdout); /* Check result of divrem */ for (i = 0; i < 500 * flint_test_multiplier(); i++) { nmod_poly_t a, b, q0, r0, r; 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(q0, n); nmod_poly_init(r0, 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(q0, r0, a, b); nmod_poly_rem_basecase(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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(q0); nmod_poly_clear(r0); nmod_poly_clear(r); } /* Check aliasing of a and r */ for (i = 0; i < 500 * 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, 200)); do { nmod_poly_randtest(b, state, n_randint(state, 200)); } while (b->length == 0); nmod_poly_rem_basecase(r, a, b); nmod_poly_rem_basecase(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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(r); } /* Check aliasing of b and r */ for (i = 0; i < 500 * 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, 200)); do { nmod_poly_randtest(b, state, n_randint(state, 200)); } while (b->length == 0); nmod_poly_rem_basecase(r, a, b); nmod_poly_rem_basecase(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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-resultant.c000066400000000000000000000061431414523752600203450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("resultant...."); fflush(stdout); /* 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); 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); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-resultant_euclidean.c000066400000000000000000000062371414523752600223620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("resultant_euclidean...."); fflush(stdout); /* 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); 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); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-resultant_hgcd.c000066400000000000000000000062021414523752600213260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("resultant_hgcd...."); fflush(stdout); /* 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); 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); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-reverse.c000066400000000000000000000044771414523752600200070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("reverse...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-revert_series.c000066400000000000000000000054501414523752600212050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revert_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-revert_series_lagrange.c000066400000000000000000000055151414523752600230470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revert_series_lagrange...."); fflush(stdout); /* 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_lagrange(f, g, n); nmod_poly_revert_series_lagrange(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"); 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_lagrange(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"); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-revert_series_lagrange_fast.c000066400000000000000000000055411414523752600240630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revert_series_lagrange_fast...."); fflush(stdout); /* 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_lagrange_fast(f, g, n); nmod_poly_revert_series_lagrange_fast(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"); 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_lagrange_fast(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"); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-revert_series_newton.c000066400000000000000000000055051414523752600226000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revert_series_newton...."); fflush(stdout); /* 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_newton(f, g, n); nmod_poly_revert_series_newton(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"); 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_newton(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"); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-scalar_mul_nmod.c000066400000000000000000000047211414523752600214630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_nmod...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(d1); nmod_poly_clear(d2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-set_trunc.c000066400000000000000000000036261414523752600203350ustar00rootroot00000000000000/* Copyright (C) 2014 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("set_trunc...."); fflush(stdout); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-shift_left_right.c000066400000000000000000000050331414523752600216450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("shift_left_right...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-sin_series.c000066400000000000000000000053241414523752600204670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("sin_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-sinh_series.c000066400000000000000000000053421414523752600206370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("sinh_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-sqrt.c000066400000000000000000000077501414523752600173220ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("sqrt... "); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-sqrt_series.c000066400000000000000000000053211414523752600206640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrt_series...."); fflush(stdout); /* 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); 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); abort(); } nmod_poly_clear(g); nmod_poly_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-sub.c000066400000000000000000000065421414523752600171200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-sub_series.c000066400000000000000000000073471414523752600204760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add_series...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(d); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-tan_series.c000066400000000000000000000052431414523752600204600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("tan_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-tanh_series.c000066400000000000000000000053431414523752600206310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result = 1; FLINT_TEST_INIT(state); flint_printf("tanh_series...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(A); nmod_poly_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-taylor_shift.c000066400000000000000000000066731414523752600210430ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("taylor_shift...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h1); nmod_poly_clear(h2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-taylor_shift_convolution.c000066400000000000000000000051541414523752600234730ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("taylor_shift_convolution...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h1); nmod_poly_clear(h2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-taylor_shift_horner.c000066400000000000000000000047041414523752600224110ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("taylor_shift_horner...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h1); nmod_poly_clear(h2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-xgcd.c000066400000000000000000000215001414523752600172430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("xgcd...."); fflush(stdout); /* 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); 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 < 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) % 600); nmod_poly_randtest(b, state, n_randtest(state) % 600); 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); 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) % 600); nmod_poly_randtest(b, state, n_randtest(state) % 600); 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); 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) % 600); nmod_poly_randtest(b, state, n_randtest(state) % 600); 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); 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) % 600); nmod_poly_randtest(b, state, n_randtest(state) % 600); 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); 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) % 600); nmod_poly_randtest(b, state, n_randtest(state) % 600); 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); 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) % 600); nmod_poly_randtest(b, state, n_randtest(state) % 600); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-xgcd_euclidean.c000066400000000000000000000213351414523752600212620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("xgcd_euclidean...."); fflush(stdout); /* 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); 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); 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); 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); 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); 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); 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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/test/t-xgcd_hgcd.c000066400000000000000000000215341414523752600202370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("xgcd_hgcd...."); fflush(stdout); /* 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); 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 < 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_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); 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_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); 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_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); 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_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); 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_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); 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_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); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly/tree.c000066400000000000000000000046641414523752600160510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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); } } flint2-2.8.4/nmod_poly/xgcd.c000066400000000000000000000101711414523752600160250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "mpn_extras.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) { const slong cutoff = FLINT_BIT_COUNT(mod.n) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; if (lenA < cutoff) return _nmod_poly_xgcd_euclidean(G, S, T, A, lenA, B, lenB, mod); else return _nmod_poly_xgcd_hgcd(G, S, T, A, lenA, B, lenB, 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) { 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); } } } } flint2-2.8.4/nmod_poly/xgcd_euclidean.c000066400000000000000000000146161414523752600200460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "mpn_extras.h" 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); } } } } flint2-2.8.4/nmod_poly/xgcd_hgcd.c000066400000000000000000000270451414523752600170220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "mpn_extras.h" /* We define a whole bunch of macros here which essentially provide the nmod_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 __set(B, lenB, A, lenA) \ do { \ _nmod_vec_set((B), (A), (lenA)); \ (lenB) = (lenA); \ } while (0) #define __add(C, lenC, A, lenA, B, lenB) \ do { \ _nmod_poly_add((C), (A), (lenA), (B), (lenB), mod); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ MPN_NORM((C), (lenC)); \ } while (0) #define __sub(C, lenC, A, lenA, B, lenB) \ do { \ _nmod_poly_sub((C), (A), (lenA), (B), (lenB), mod); \ (lenC) = FLINT_MAX((lenA), (lenB)); \ MPN_NORM((C), (lenC)); \ } while (0) #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) #define __divrem(Q, lenQ, R, lenR, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ _nmod_poly_divrem((Q), (R), (A), (lenA), (B), (lenB), mod); \ (lenQ) = (lenA) - (lenB) + 1; \ (lenR) = (lenB) - 1; \ MPN_NORM((R), (lenR)); \ } \ else \ { \ _nmod_vec_set((R), (A), (lenA)); \ (lenQ) = 0; \ (lenR) = (lenA); \ } \ } while (0) #define __div(Q, lenQ, A, lenA, B, lenB) \ do { \ if ((lenA) >= (lenB)) \ { \ _nmod_poly_div((Q), (A), (lenA), (B), (lenB), mod); \ (lenQ) = (lenA) - (lenB) + 1; \ } \ else \ { \ (lenQ) = 0; \ } \ } while (0) 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) { const slong cutoff = FLINT_BIT_COUNT(mod.n) <= 8 ? NMOD_POLY_SMALL_GCD_CUTOFF : NMOD_POLY_GCD_CUTOFF; slong lenG, lenS, lenT; if (lenB == 1) { G[0] = B[0]; T[0] = 1; lenG = 1; lenS = 0; lenT = 1; } else { mp_ptr q = _nmod_vec_init(lenA + lenB); mp_ptr r = q + lenA; slong lenq, lenr; __divrem(q, lenq, r, lenr, A, lenA, B, lenB); if (lenr == 0) { __set(G, lenG, B, lenB); T[0] = 1; lenS = 0; lenT = 1; } else { mp_ptr h, j, v, w, R[4], X; slong lenh, lenj, lenv, lenw, lenR[4]; int sgnR; lenh = lenj = lenB; lenv = lenw = lenA + lenB - 2; lenR[0] = lenR[1] = lenR[2] = lenR[3] = (lenB + 1) / 2; X = _nmod_vec_init(2 * lenh + 2 * lenv + 4 * lenR[0]); h = X; j = h + lenh; v = j + lenj; w = v + lenv; R[0] = w + lenw; R[1] = R[0] + lenR[0]; R[2] = R[1] + lenR[1]; R[3] = R[2] + lenR[2]; sgnR = _nmod_poly_hgcd(R, lenR, h, &lenh, j, &lenj, B, lenB, r, lenr, mod); if (sgnR > 0) { _nmod_vec_neg(S, R[1], lenR[1], mod); _nmod_vec_set(T, R[0], lenR[0]); } else { _nmod_vec_set(S, R[1], lenR[1]); _nmod_vec_neg(T, R[0], lenR[0], mod); } lenS = lenR[1]; lenT = lenR[0]; while (lenj != 0) { __divrem(q, lenq, r, lenr, h, lenh, j, lenj); __mul(v, lenv, q, lenq, T, lenT); { slong l; _nmod_vec_swap(S, T, FLINT_MAX(lenS, lenT)); l = lenS; lenS = lenT; lenT = l; } if (lenr != 0) /* prevent overflow of T on last iteration */ __sub(T, lenT, T, lenT, v, lenv); else { __set(G, lenG, j, lenj); goto cofactor; } if (lenj < cutoff) { mp_ptr u0 = R[0], u1 = R[1]; slong lenu0 = lenr - 1, lenu1 = lenj - 1; lenG = _nmod_poly_xgcd_euclidean(G, u0, u1, j, lenj, r, lenr, mod); MPN_NORM(u0, lenu0); MPN_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; } sgnR = _nmod_poly_hgcd(R, lenR, h, &lenh, j, &lenj, j, lenj, r, lenr, mod); __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 > WORD(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); _nmod_vec_clear(X); } _nmod_vec_clear(q); } flint_mpn_zero(S + lenS, lenB - 1 - lenS); flint_mpn_zero(T + lenT, lenA - 1 - lenT); 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(FLINT_MAX(lenB - 1, 2)); } else { nmod_poly_fit_length(S, FLINT_MAX(lenB - 1, 2)); s = S->coeffs; } if (T == A || T == B) { t = _nmod_vec_init(FLINT_MAX(lenA - 1, 2)); } else { nmod_poly_fit_length(T, FLINT_MAX(lenA - 1, 2)); 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 = FLINT_MAX(lenB - 1, 2); } if (T == A || T == B) { flint_free(T->coeffs); T->coeffs = t; T->alloc = FLINT_MAX(lenA - 1, 2); } 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); } } } } #undef __set #undef __add #undef __sub #undef __mul #undef __divrem #undef __div flint2-2.8.4/nmod_poly_factor.h000066400000000000000000000114611414523752600164460ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define NMOD_POLY_FACTOR_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "fmpz.h" #ifdef __cplusplus extern "C" { #endif typedef struct { nmod_poly_struct *p; slong *exp; slong num; slong alloc; } nmod_poly_factor_struct; 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 ****************************************************************/ typedef nmod_poly_factor_struct nmod_poly_factor_t[1]; FLINT_DLL void nmod_poly_factor_init(nmod_poly_factor_t fac); FLINT_DLL void nmod_poly_factor_clear(nmod_poly_factor_t fac); FLINT_DLL void nmod_poly_factor_realloc(nmod_poly_factor_t fac, slong alloc); FLINT_DLL void nmod_poly_factor_fit_length(nmod_poly_factor_t fac, slong len); FLINT_DLL 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; } FLINT_DLL void nmod_poly_factor_insert(nmod_poly_factor_t fac, const nmod_poly_t poly, slong exp); FLINT_DLL void nmod_poly_factor_print(const nmod_poly_factor_t fac); FLINT_DLL void nmod_poly_factor_concat(nmod_poly_factor_t res, const nmod_poly_factor_t fac); FLINT_DLL void nmod_poly_factor_pow(nmod_poly_factor_t fac, slong exp); FLINT_DLL void nmod_poly_factor_equal_deg(nmod_poly_factor_t factors, const nmod_poly_t pol, slong d); FLINT_DLL int nmod_poly_factor_equal_deg_prob(nmod_poly_t factor, flint_rand_t state, const nmod_poly_t pol, slong d); FLINT_DLL void nmod_poly_factor_distinct_deg(nmod_poly_factor_t res, const nmod_poly_t poly, slong * const *degs); FLINT_DLL ulong nmod_poly_remove(nmod_poly_t f, const nmod_poly_t p); FLINT_DLL void nmod_poly_factor_distinct_deg_threaded(nmod_poly_factor_t res, const nmod_poly_t poly, slong * const *degs); FLINT_DLL int nmod_poly_is_irreducible(const nmod_poly_t f); FLINT_DLL int nmod_poly_is_irreducible_rabin(const nmod_poly_t f); FLINT_DLL int nmod_poly_is_irreducible_ddf(const nmod_poly_t f); FLINT_DLL int _nmod_poly_is_squarefree(mp_srcptr f, slong len, nmod_t mod); FLINT_DLL int nmod_poly_is_squarefree(const nmod_poly_t f); FLINT_DLL void nmod_poly_factor_cantor_zassenhaus(nmod_poly_factor_t res, const nmod_poly_t f); FLINT_DLL void nmod_poly_factor_berlekamp(nmod_poly_factor_t factors, const nmod_poly_t f); FLINT_DLL void nmod_poly_factor_kaltofen_shoup(nmod_poly_factor_t res, const nmod_poly_t poly); FLINT_DLL void nmod_poly_factor_squarefree(nmod_poly_factor_t res, const nmod_poly_t f); FLINT_DLL mp_limb_t nmod_poly_factor_with_berlekamp(nmod_poly_factor_t result, const nmod_poly_t input); FLINT_DLL mp_limb_t nmod_poly_factor_with_cantor_zassenhaus(nmod_poly_factor_t result, const nmod_poly_t input); FLINT_DLL mp_limb_t nmod_poly_factor_with_kaltofen_shoup(nmod_poly_factor_t result, const nmod_poly_t input); FLINT_DLL mp_limb_t nmod_poly_factor(nmod_poly_factor_t result, const nmod_poly_t input); FLINT_DLL void _nmod_poly_interval_poly_worker(void* arg_ptr); /* Roots *********************************************************************/ FLINT_DLL void nmod_poly_roots(nmod_poly_factor_t r, const nmod_poly_t f, int with_multiplicity); FLINT_DLL int nmod_poly_roots_factored(nmod_poly_factor_t r, const nmod_poly_t f, int with_multiplicity, const n_factor_t * n); /* Inlines *******************************************************************/ FLINT_DLL void nmod_poly_factor_get_nmod_poly(nmod_poly_t z, nmod_poly_factor_t fac, slong i); #ifdef __cplusplus } #endif #endif flint2-2.8.4/nmod_poly_factor/000077500000000000000000000000001414523752600162725ustar00rootroot00000000000000flint2-2.8.4/nmod_poly_factor/clear.c000066400000000000000000000014051414523752600175240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_poly.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); } flint2-2.8.4/nmod_poly_factor/concat.c000066400000000000000000000014111414523752600177020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_poly.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]); } flint2-2.8.4/nmod_poly_factor/factor.c000066400000000000000000000114351414523752600177200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.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_preinv(monic_input, input->mod.n, input->mod.ninv); 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_preinv(def, input->mod.n, input->mod.ninv); 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_preinv(pol, input->mod.n, input->mod.ninv); 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); if (n < 10 + 50 / bits) return __nmod_poly_factor_deflation(result, input, ZASSENHAUS); else return __nmod_poly_factor_deflation(result, input, KALTOFEN); } flint2-2.8.4/nmod_poly_factor/factor_berlekamp.c000066400000000000000000000136001414523752600217360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "nmod_mat.h" #include "ulong_extras.h" #include "profiler.h" #include "perm.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) = UWORD(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(x, p); nmod_poly_init(x_p, p); 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(x_pi, p); nmod_poly_init(x_pi2, p); 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(basis[i], p); 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(factor, p); nmod_poly_init(b, p); nmod_poly_init(power, p); nmod_poly_init(g, p); 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(Q, p); nmod_poly_div(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); } flint2-2.8.4/nmod_poly_factor/factor_cantor_zassenhaus.c000066400000000000000000000032111414523752600235230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.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_preinv(h, f->mod.n, f->mod.ninv); nmod_poly_init_preinv(g, f->mod.n, f->mod.ninv); nmod_poly_init_preinv(v, f->mod.n, f->mod.ninv); nmod_poly_init_preinv(x, f->mod.n, f->mod.ninv); 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); } flint2-2.8.4/nmod_poly_factor/factor_distinct_deg.c000066400000000000000000000144021414523752600224350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "nmod_poly.h" 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_t *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_preinv(v, poly->mod.n, poly->mod.ninv); 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_preinv(f, poly->mod.n, poly->mod.ninv); nmod_poly_init_preinv(g, poly->mod.n, poly->mod.ninv); nmod_poly_init_preinv(vinv, poly->mod.n, poly->mod.ninv); nmod_poly_init_preinv(tmp, poly->mod.n, poly->mod.ninv); if (!(h = flint_malloc((2 * m + l + 1) * sizeof(nmod_poly_struct)))) { flint_printf("Exception (nmod_poly_factor_distinct_deg):\n"); flint_printf("Not enough memory.\n"); flint_abort(); } 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_preinv(h[i], poly->mod.n, poly->mod.ninv); 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); } flint2-2.8.4/nmod_poly_factor/factor_distinct_deg_threaded.c000066400000000000000000000530571414523752600243060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "nmod_poly.h" 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; A->rows[0][0] = UWORD(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] = UWORD(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 = (nmod_poly_struct *) flint_malloc((2*m + l + num_threads + 2)* sizeof(nmod_poly_struct)); if (h == NULL) { flint_printf("Exception (nmod_poly_factor_distinct_deg):\n"); flint_printf("Not enough memory.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly_factor/factor_equal_deg.c000066400000000000000000000024401414523752600217220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "ulong_extras.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_preinv(f, pol->mod.n, pol->mod.ninv); flint_randinit(state); while (!nmod_poly_factor_equal_deg_prob(f, state, pol, d)) {}; flint_randclear(state); nmod_poly_init_preinv(g, pol->mod.n, pol->mod.ninv); nmod_poly_div(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); } } flint2-2.8.4/nmod_poly_factor/factor_equal_deg_prob.c000066400000000000000000000050201414523752600227410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "ulong_extras.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; mpz_t exp; int res = 1; slong i; if (pol->length <= 1) { flint_printf("Exception (nmod_poly_factor_equal_deg_prob). \n"); flint_printf("Input polynomial is linear.\n"); flint_abort(); } nmod_poly_init_preinv(a, pol->mod.n, pol->mod.ninv); 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_preinv(b, pol->mod.n, pol->mod.ninv); nmod_poly_init_preinv(polinv, pol->mod.n, pol->mod.ninv); nmod_poly_reverse(polinv, pol, pol->length); nmod_poly_inv_series(polinv, polinv, polinv->length); mpz_init(exp); if (pol->mod.n > 2) { /* compute a^{(p^d-1)/2} rem pol */ flint_mpz_ui_pow_ui(exp, pol->mod.n, d); flint_mpz_sub_ui(exp, exp, 1); mpz_tdiv_q_2exp(exp, exp, 1); nmod_poly_powmod_mpz_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_preinv(c, pol->mod.n, pol->mod.ninv); 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); } mpz_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; } flint2-2.8.4/nmod_poly_factor/factor_kaltofen_shoup.c000066400000000000000000000043631414523752600230230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.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_preinv(v, poly->mod.n, poly->mod.ninv); nmod_poly_make_monic(v, poly); if (poly->length <= 2) { nmod_poly_factor_insert (res, v, 1); nmod_poly_clear (v); return; } if (!(degs = flint_malloc(nmod_poly_degree(poly) * sizeof(slong)))) { flint_printf("Exception (nmod_poly_factor_kaltofen_shoup): \n"); flint_printf("Not enough memory.\n"); flint_abort(); } /* 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); } flint2-2.8.4/nmod_poly_factor/factor_squarefree.c000066400000000000000000000067501414523752600221460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "ulong_extras.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); 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(g_1, p); nmod_poly_init(f_d, p); nmod_poly_init(g, p); 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(h, p); 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_div(g_1, f, g); i = 1; nmod_poly_init(h, p); nmod_poly_init(z, p); /* Case 2 */ while (!nmod_poly_is_one(g_1)) { nmod_poly_gcd(h, g_1, g); nmod_poly_div(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_div(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(g_p, p); 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); } flint2-2.8.4/nmod_poly_factor/fit_length.c000066400000000000000000000013571414523752600205670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.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); } } flint2-2.8.4/nmod_poly_factor/init.c000066400000000000000000000016001414523752600173760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_poly.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); } flint2-2.8.4/nmod_poly_factor/inlines.c000066400000000000000000000013421414523752600200770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define NMOD_POLY_FACTOR_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "nmod_poly.h" void nmod_poly_factor_get_nmod_poly(nmod_poly_t z, nmod_poly_factor_t fac, slong i) { nmod_poly_set(z, fac->p + i); } flint2-2.8.4/nmod_poly_factor/insert.c000066400000000000000000000026011414523752600177410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.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++; } flint2-2.8.4/nmod_poly_factor/is_irreducible.c000066400000000000000000000013731414523752600214260ustar00rootroot00000000000000/* 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 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" 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; } flint2-2.8.4/nmod_poly_factor/is_irreducible_ddf.c000066400000000000000000000105201414523752600222350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "nmod_poly.h" int nmod_poly_is_irreducible_ddf(const nmod_poly_t poly) { nmod_poly_t f, v, vinv, tmp; nmod_poly_t *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_preinv(f, poly->mod.n, poly->mod.ninv); nmod_poly_init_preinv(v, poly->mod.n, poly->mod.ninv); nmod_poly_init_preinv(vinv, poly->mod.n, poly->mod.ninv); nmod_poly_init_preinv(tmp, poly->mod.n, poly->mod.ninv); if (!(h = flint_malloc((2 * m + l + 1) * sizeof(nmod_poly_struct)))) { flint_printf("Exception (nmod_poly_is_irreducible_ddf):\n"); flint_printf("Not enough memory.\n"); flint_abort(); } 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_preinv(h[i], poly->mod.n, poly->mod.ninv); 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; } flint2-2.8.4/nmod_poly_factor/is_irreducible_rabin.c000066400000000000000000000047711414523752600226060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "ulong_extras.h" 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; } flint2-2.8.4/nmod_poly_factor/is_squarefree.c000066400000000000000000000021011414523752600212650ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "mpn_extras.h" #include "ulong_extras.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); } flint2-2.8.4/nmod_poly_factor/pow.c000066400000000000000000000013001414523752600172350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.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; } flint2-2.8.4/nmod_poly_factor/print.c000066400000000000000000000014441414523752600175750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_poly.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]); } } flint2-2.8.4/nmod_poly_factor/profile/000077500000000000000000000000001414523752600177325ustar00rootroot00000000000000flint2-2.8.4/nmod_poly_factor/profile/p-factor.c000066400000000000000000000233161414523752600216160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include #include "flint.h" #include "nmod_poly.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) { FLINT_TEST_INIT(state); 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_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 EXIT_SUCCESS; } flint2-2.8.4/nmod_poly_factor/profile/p-factorbench.c000066400000000000000000000030731414523752600226140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include #include "flint.h" #include "nmod_poly.h" int main (void) { double t; nmod_poly_t f, g, h; for (int 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)) { flint_printf ("i= %d\n", i); nmod_poly_factor_t factors; 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 EXIT_SUCCESS; } flint2-2.8.4/nmod_poly_factor/profile/p-roots.c000066400000000000000000000032461414523752600215060ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.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) << (FLINT_BITS - 2), 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; } flint2-2.8.4/nmod_poly_factor/realloc.c000066400000000000000000000035171414523752600200650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.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; } } flint2-2.8.4/nmod_poly_factor/roots.c000066400000000000000000000137711414523752600176150ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/nmod_poly_factor/roots_factored.c000066400000000000000000000207451414523752600214630ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly.h" #include "nmod_poly_factor.h" #include "long_extras.h" #include "ulong_extras.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; } flint2-2.8.4/nmod_poly_factor/set.c000066400000000000000000000022421414523752600172310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.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; } } } flint2-2.8.4/nmod_poly_factor/test/000077500000000000000000000000001414523752600172515ustar00rootroot00000000000000flint2-2.8.4/nmod_poly_factor/test/t-factor.c000066400000000000000000000164371414523752600211470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor...."); fflush(stdout); /* 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], prod1; 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; 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)); exp[i] = n_randint(state, 30) + 1; prod1 *= exp[i]; 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); 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"); 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], prod1; 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; 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, 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; prod1 *= exp[i]; 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_factor/test/t-factor_berlekamp.c000066400000000000000000000050721414523752600231620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor_berlekamp...."); fflush(stdout); 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); abort(); } nmod_poly_clear(quot); nmod_poly_clear(rem); nmod_poly_clear(pol1); nmod_poly_clear(poly); nmod_poly_factor_clear(res); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_factor/test/t-factor_cantor_zassenhaus.c000066400000000000000000000071751414523752600247600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor_cantor_zassenhaus...."); fflush(stdout); 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 prod1, 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; 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(!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; prod1 *= exp[i]; 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"); } if (!result) 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_factor/test/t-factor_distinct_deg.c000066400000000000000000000077071414523752600236670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "ulong_extras.h" #define MAX_DEG 7 int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor_distinct_deg...."); fflush(stdout); 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."); 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]]); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_factor/test/t-factor_distinct_deg_threaded.c000066400000000000000000000103041414523752600255120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "ulong_extras.h" #include "flint.h" #define MAX_DEG 7 int main(void) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int iter; #endif FLINT_TEST_INIT(state); flint_printf("factor_distinct_deg_threaded...."); fflush(stdout); #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) 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]]); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; #else FLINT_TEST_CLEANUP(state); flint_printf("SKIPPED\n"); return 0; #endif } flint2-2.8.4/nmod_poly_factor/test/t-factor_kaltofen_shoup.c000066400000000000000000000070431414523752600242410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor_kaltofen_shoup...."); fflush(stdout); 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); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_factor/test/t-factor_squarefree.c000066400000000000000000000066371414523752600233720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("factor_squarefree...."); fflush(stdout); 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"); abort(); } nmod_poly_clear(quot); nmod_poly_clear(rem); nmod_poly_clear(pol1); nmod_poly_clear(poly); nmod_poly_factor_clear(res); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_factor/test/t-interval_threaded.c000066400000000000000000000113001414523752600233350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) int iter; #endif FLINT_TEST_INIT(state); flint_printf("interval_threaded...."); fflush(stdout); #if FLINT_USES_PTHREAD && (FLINT_USES_TLS || FLINT_REENTRANT) 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); #else FLINT_TEST_CLEANUP(state); flint_printf("SKIPPED\n"); #endif return 0; } flint2-2.8.4/nmod_poly_factor/test/t-is_irreducible.c000066400000000000000000000050211414523752600226400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("is_irreducible...."); fflush(stdout); 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"); 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"); abort(); } nmod_poly_clear(poly); nmod_poly_clear(poly2); nmod_poly_clear(poly3); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_factor/test/t-is_irreducible_ddf.c000066400000000000000000000050471414523752600234650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("is_irreducible_ddf...."); fflush(stdout); 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"); 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"); abort(); } nmod_poly_clear(poly); nmod_poly_clear(poly2); nmod_poly_clear(poly3); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_factor/test/t-is_irreducible_rabin.c000066400000000000000000000052331414523752600240200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("is_irreducible_rabin...."); fflush(stdout); 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"); 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"); abort(); } nmod_poly_clear(poly); nmod_poly_clear(poly2); nmod_poly_clear(poly3); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_factor/test/t-is_squarefree.c000066400000000000000000000045331414523752600225200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "ulong_extras.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("is_squarefree...."); fflush(stdout); 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"); abort(); } nmod_poly_clear(poly); nmod_poly_clear(t); nmod_poly_clear(Q); nmod_poly_clear(R); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_factor/test/t-roots.c000066400000000000000000000063351414523752600210330ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #include "ulong_extras.h" 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"); flint_abort(); } if (roots->p[i].coeffs[1] != 1) { flint_printf("FAIL:\ncheck root is monic\n"); 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"); flint_abort(); } if (roots->exp[i] != (want_mult ? multiplicity : 1)) { flint_printf("FAIL:\ncheck root multiplicity\n"); flint_abort(); } } nmod_poly_roots(roots, q, want_mult); if (roots->num > 0) { flint_printf("FAIL:\ncheck missing roots\n"); flint_abort(); } nmod_poly_clear(q); nmod_poly_clear(qt); nmod_poly_clear(r); } int main(void) { slong i, j, k, l; FLINT_TEST_INIT(state); flint_printf("roots...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_factor/test/t-roots_factored.c000066400000000000000000000123761414523752600227040ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_poly_factor.h" #include "ulong_extras.h" 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"); 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"); flint_abort(); } if (roots->p[i].coeffs[1] != 1) { flint_printf("FAILED:\ncheck root is monic\n"); 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"); flint_abort(); } if (roots->exp[i] != (want_mult ? multiplicity : 1)) { flint_printf("FAILED:\ncheck root multiplicity\n"); 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"); flint_abort(); } found = 1; } } if (!found) { flint_printf("FAILED:\ncheck missing roots\n"); flint_abort(); } } } nmod_poly_clear(q); nmod_poly_clear(qt); nmod_poly_clear(r); } int main(void) { slong i, j, k, l; FLINT_TEST_INIT(state); flint_printf("roots_factored...."); fflush(stdout); 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"); flint_abort(); } if (roots->num != n_sqrtmodn(&sqrt, a, &nfac)) { flint_printf("FAILED:\ncheck root count against n_sqrtmodn\n"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat.h000066400000000000000000000203501414523752600157460ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 FLINT_DLL #else #define NMOD_POLY_MAT_INLINE static __inline__ #endif #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_mat.h" #ifdef __cplusplus extern "C" { #endif /* Types *********************************************************************/ 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]; 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 *********************************************************/ FLINT_DLL void nmod_poly_mat_init(nmod_poly_mat_t mat, slong rows, slong cols, mp_limb_t n); FLINT_DLL void nmod_poly_mat_init_set(nmod_poly_mat_t mat, const nmod_poly_mat_t src); FLINT_DLL void nmod_poly_mat_swap(nmod_poly_mat_t mat1, nmod_poly_mat_t 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++) nmod_poly_swap(nmod_poly_mat_entry(mat2, i, j), nmod_poly_mat_entry(mat1, i, j)); } FLINT_DLL void nmod_poly_mat_set(nmod_poly_mat_t mat1, const nmod_poly_mat_t mat2); FLINT_DLL void nmod_poly_mat_clear(nmod_poly_mat_t mat); /* Basic properties **********************************************************/ NMOD_POLY_MAT_INLINE mp_limb_t nmod_poly_mat_modulus(const nmod_poly_mat_t mat) { return mat->modulus; } /* Comparison ****************************************************************/ FLINT_DLL int nmod_poly_mat_equal(const nmod_poly_mat_t mat1, const nmod_poly_mat_t mat2); FLINT_DLL int nmod_poly_mat_is_zero(const nmod_poly_mat_t mat); FLINT_DLL 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 *********************************************************/ FLINT_DLL void nmod_poly_mat_zero(nmod_poly_mat_t mat); FLINT_DLL void nmod_poly_mat_one(nmod_poly_mat_t mat); /* Random matrices ***********************************************************/ FLINT_DLL void nmod_poly_mat_randtest(nmod_poly_mat_t mat, flint_rand_t state, slong len); FLINT_DLL void nmod_poly_mat_randtest_sparse(nmod_poly_mat_t A, flint_rand_t state, slong len, float density); /* Windows and concatenation */ FLINT_DLL 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); FLINT_DLL void nmod_poly_mat_window_clear(nmod_poly_mat_t window); FLINT_DLL void nmod_poly_mat_concat_horizontal(nmod_poly_mat_t res, const nmod_poly_mat_t mat1, const nmod_poly_mat_t mat2); FLINT_DLL 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 **********************************************************/ FLINT_DLL void nmod_poly_mat_print(const nmod_poly_mat_t mat, const char * x); /* Norms *********************************************************************/ FLINT_DLL slong nmod_poly_mat_max_length(const nmod_poly_mat_t A); /* Scalar arithmetic *********************************************************/ FLINT_DLL void nmod_poly_mat_scalar_mul_nmod_poly(nmod_poly_mat_t B, const nmod_poly_mat_t A, const nmod_poly_t c); FLINT_DLL void nmod_poly_mat_scalar_mul_nmod(nmod_poly_mat_t B, const nmod_poly_mat_t A, mp_limb_t c); /* Matrix arithmetic *********************************************************/ FLINT_DLL void nmod_poly_mat_add(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B); FLINT_DLL void nmod_poly_mat_sub(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B); FLINT_DLL void nmod_poly_mat_neg(nmod_poly_mat_t B, const nmod_poly_mat_t A); FLINT_DLL void nmod_poly_mat_mul(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B); FLINT_DLL void nmod_poly_mat_mul_interpolate(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B); FLINT_DLL void nmod_poly_mat_mul_classical(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B); FLINT_DLL void nmod_poly_mat_mul_KS(nmod_poly_mat_t C, const nmod_poly_mat_t A, const nmod_poly_mat_t B); FLINT_DLL void nmod_poly_mat_sqr(nmod_poly_mat_t B, const nmod_poly_mat_t A); FLINT_DLL void nmod_poly_mat_sqr_classical(nmod_poly_mat_t B, const nmod_poly_mat_t A); FLINT_DLL void nmod_poly_mat_sqr_KS(nmod_poly_mat_t B, const nmod_poly_mat_t A); FLINT_DLL void nmod_poly_mat_sqr_interpolate(nmod_poly_mat_t B, const nmod_poly_mat_t A); FLINT_DLL void nmod_poly_mat_pow(nmod_poly_mat_t B, const nmod_poly_mat_t A, ulong exp); /* Evaluation ****************************************************************/ FLINT_DLL void nmod_poly_mat_evaluate_nmod(nmod_mat_t B, const nmod_poly_mat_t A, mp_limb_t x); /* Row reduction *************************************************************/ FLINT_DLL slong nmod_poly_mat_find_pivot_any(const nmod_poly_mat_t mat, slong start_row, slong end_row, slong c); FLINT_DLL slong nmod_poly_mat_find_pivot_partial(const nmod_poly_mat_t mat, slong start_row, slong end_row, slong c); FLINT_DLL 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); FLINT_DLL slong nmod_poly_mat_rref(nmod_poly_mat_t B, nmod_poly_t den, const nmod_poly_mat_t A); /* Trace *********************************************************************/ FLINT_DLL void nmod_poly_mat_trace(nmod_poly_t trace, const nmod_poly_mat_t mat); /* Determinant and rank ******************************************************/ FLINT_DLL void nmod_poly_mat_det(nmod_poly_t det, const nmod_poly_mat_t A); FLINT_DLL void nmod_poly_mat_det_fflu(nmod_poly_t det, const nmod_poly_mat_t A); FLINT_DLL void nmod_poly_mat_det_interpolate(nmod_poly_t det, const nmod_poly_mat_t A); FLINT_DLL slong nmod_poly_mat_rank(const nmod_poly_mat_t A); /* Inverse *******************************************************************/ FLINT_DLL int nmod_poly_mat_inv(nmod_poly_mat_t Ainv, nmod_poly_t den, const nmod_poly_mat_t A); /* Nullspace *****************************************************************/ FLINT_DLL slong nmod_poly_mat_nullspace(nmod_poly_mat_t res, const nmod_poly_mat_t mat); /* Solving *******************************************************************/ FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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 flint2-2.8.4/nmod_poly_mat/000077500000000000000000000000001414523752600155755ustar00rootroot00000000000000flint2-2.8.4/nmod_poly_mat/add.c000066400000000000000000000014731414523752600164760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/nmod_poly_mat/clear.c000066400000000000000000000013571414523752600170350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/nmod_poly_mat/concat_horizontal.c000066400000000000000000000020021414523752600214530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } } } flint2-2.8.4/nmod_poly_mat/concat_vertical.c000066400000000000000000000020001414523752600210710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly_mat.h" 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)); } } } flint2-2.8.4/nmod_poly_mat/det.c000066400000000000000000000024011414523752600165120ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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); } } flint2-2.8.4/nmod_poly_mat/det_fflu.c000066400000000000000000000016771414523752600175440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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" 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); } } flint2-2.8.4/nmod_poly_mat/det_interpolate.c000066400000000000000000000026431414523752600211300ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" 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); } flint2-2.8.4/nmod_poly_mat/equal.c000066400000000000000000000015101414523752600170450ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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; } flint2-2.8.4/nmod_poly_mat/evaluate_nmod.c000066400000000000000000000014131414523752600205630ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/nmod_poly_mat/fflu.c000066400000000000000000000044721414523752600167040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_div(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; } flint2-2.8.4/nmod_poly_mat/find_pivot_any.c000066400000000000000000000014001414523752600207440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/nmod_poly_mat/find_pivot_partial.c000066400000000000000000000020761414523752600216230ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/nmod_poly_mat/init.c000066400000000000000000000023461414523752600167110ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/nmod_poly_mat/init_set.c000066400000000000000000000011611414523752600175560ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/nmod_poly_mat/inlines.c000066400000000000000000000010721414523752600174020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define NMOD_POLY_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "nmod_poly_mat.h" flint2-2.8.4/nmod_poly_mat/inv.c000066400000000000000000000043231414523752600165370ustar00rootroot00000000000000/* 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 2.1 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; } } flint2-2.8.4/nmod_poly_mat/is_one.c000066400000000000000000000017321414523752600172200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/nmod_poly_mat/is_zero.c000066400000000000000000000013571414523752600174210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/nmod_poly_mat/max_length.c000066400000000000000000000014101414523752600200630ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/nmod_poly_mat/mul.c000066400000000000000000000026321414523752600165410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.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); } } flint2-2.8.4/nmod_poly_mat/mul_KS.c000066400000000000000000000034461414523752600171420ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/nmod_poly_mat/mul_classical.c000066400000000000000000000032401414523752600205530ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/nmod_poly_mat/mul_interpolate.c000066400000000000000000000070441414523752600211510ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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_printf("Exception (nmod_poly_mat_mul_interpolate). \n" "Characteristic is too small.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly_mat/neg.c000066400000000000000000000013221414523752600165100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/nmod_poly_mat/nullspace.c000066400000000000000000000036621414523752600177360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/nmod_poly_mat/one.c000066400000000000000000000012221414523752600165170ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } flint2-2.8.4/nmod_poly_mat/pow.c000066400000000000000000000026661414523752600165600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } } flint2-2.8.4/nmod_poly_mat/print.c000066400000000000000000000017101414523752600170740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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"); } flint2-2.8.4/nmod_poly_mat/randtest.c000066400000000000000000000013121414523752600175620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/nmod_poly_mat/randtest_sparse.c000066400000000000000000000020461414523752600211440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "ulong_extras.h" 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)); } } } } flint2-2.8.4/nmod_poly_mat/rank.c000066400000000000000000000015121414523752600166730ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/nmod_poly_mat/rref.c000066400000000000000000000052371414523752600167060ustar00rootroot00000000000000/* 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 2.1 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_div(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; } flint2-2.8.4/nmod_poly_mat/scalar_mul_nmod.c000066400000000000000000000015361414523752600211050ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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); } flint2-2.8.4/nmod_poly_mat/scalar_mul_nmod_poly.c000066400000000000000000000015271414523752600221500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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); } flint2-2.8.4/nmod_poly_mat/set.c000066400000000000000000000014021414523752600165310ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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)); } } flint2-2.8.4/nmod_poly_mat/solve.c000066400000000000000000000012221414523752600170660ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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); } flint2-2.8.4/nmod_poly_mat/solve_fflu.c000066400000000000000000000023411414523752600201050ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/nmod_poly_mat/solve_fflu_precomp.c000066400000000000000000000045441414523752600216410ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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) { /* Not implemented */ flint_abort(); } else { slong i, j; if (perm == NULL) flint_abort(); 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_div(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_div(XX(i, k), XX(i, k), LU(i, i)); } } nmod_poly_clear(T); } flint2-2.8.4/nmod_poly_mat/sqr.c000066400000000000000000000023021414523752600165430ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_poly.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); } } flint2-2.8.4/nmod_poly_mat/sqr_KS.c000066400000000000000000000027341414523752600171510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" #include "fmpz_mat.h" 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); /* Should use fmpz_mat_sqr */ fmpz_mat_mul(BB, AA, 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); } flint2-2.8.4/nmod_poly_mat/sqr_classical.c000066400000000000000000000027521414523752600205720ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" 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); } flint2-2.8.4/nmod_poly_mat/sqr_interpolate.c000066400000000000000000000056751414523752600211710ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_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_printf("Exception (nmod_poly_mat_sqr_interpolate). \n" "Characteristic is too small.\n"); flint_abort(); } 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); } flint2-2.8.4/nmod_poly_mat/sub.c000066400000000000000000000015171414523752600165360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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)); } flint2-2.8.4/nmod_poly_mat/swap.c000066400000000000000000000012211414523752600167070ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" void nmod_poly_mat_swap(nmod_poly_mat_t A, nmod_poly_mat_t B) { if (A != B) { nmod_poly_mat_struct tmp; tmp = *A; *A = *B; *B = tmp; } } flint2-2.8.4/nmod_poly_mat/test/000077500000000000000000000000001414523752600165545ustar00rootroot00000000000000flint2-2.8.4/nmod_poly_mat/test/t-add.c000066400000000000000000000105751414523752600177210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("add...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-concat_horizontal.c000066400000000000000000000037601414523752600227070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "ulong_extras.h" int main(void) { nmod_poly_mat_t A, B, C; nmod_poly_mat_t window1, window2; slong i; FLINT_TEST_INIT(state); flint_printf("concat_horizontal...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-concat_vertical.c000066400000000000000000000037201414523752600223230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "ulong_extras.h" int main(void) { nmod_poly_mat_t A, B, C; nmod_poly_mat_t window1, window2; slong i; FLINT_TEST_INIT(state); flint_printf("concat_vertical...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-det.c000066400000000000000000000050051414523752600177350ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("det...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-det_interpolate.c000066400000000000000000000033141414523752600223440ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("det_interpolate...."); fflush(stdout); 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"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-init_clear.c000066400000000000000000000023551414523752600212770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-inv.c000066400000000000000000000077741414523752600177740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("inv...."); fflush(stdout); /* 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"); 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"); abort(); } } else { if (!nmod_poly_equal(den, det)) { nmod_poly_neg(det, det); flint_printf("FAIL: den != det(A)\n"); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-mul.c000066400000000000000000000112111414523752600177520ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mul...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-mul_KS.c000066400000000000000000000105471414523752600203620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mul_KS...."); fflush(stdout); 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"); 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"); 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"); abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-mul_interpolate.c000066400000000000000000000123341414523752600223670ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("mul_interpolate...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-neg.c000066400000000000000000000054461414523752600177430ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("neg...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-nullspace.c000066400000000000000000000041731414523752600211540ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("nullspace...."); fflush(stdout); 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"); abort(); } if (nmod_poly_mat_rank(N) != nullity) { flint_printf("FAIL: wrong rank(N) != nullity!\n"); abort(); } nmod_poly_mat_mul(AN, A, N); if (!nmod_poly_mat_is_zero(AN)) { flint_printf("FAIL: A * N != 0\n"); abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(N); nmod_poly_mat_clear(AN); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-one.c000066400000000000000000000036071414523752600177500ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("one/is_one...."); fflush(stdout); 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"); 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"); abort(); } } nmod_poly_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-pow.c000066400000000000000000000054031414523752600177700ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("pow...."); fflush(stdout); 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"); 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"); abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-rank.c000066400000000000000000000041361414523752600201200ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("rank...."); fflush(stdout); 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); abort(); } nmod_mat_clear(Ax); nmod_poly_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-rref.c000066400000000000000000000111361414523752600201210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly_mat.h" #include "perm.h" #include "ulong_extras.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; } int main(void) { slong iter; FLINT_TEST_INIT(state); flint_printf("rref...."); fflush(stdout); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-solve_fflu.c000066400000000000000000000067111414523752600213320ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("solve...."); fflush(stdout); 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"); 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"); abort(); } } if (solved != !nmod_poly_is_zero(den)) { flint_printf("FAIL: return value does not match denominator\n"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-sqr.c000066400000000000000000000056071414523752600177760ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("sqr...."); fflush(stdout); /* 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"); 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"); abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-sqr_KS.c000066400000000000000000000054021414523752600203640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("sqr_KS...."); fflush(stdout); 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"); 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"); abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-sqr_interpolate.c000066400000000000000000000062731414523752600224040ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "fmpz.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("sqr_interpolate...."); fflush(stdout); /* 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"); 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"); abort(); } } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-sub.c000066400000000000000000000105731414523752600177600ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("sub...."); fflush(stdout); /* 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"); 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"); 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"); abort(); } nmod_poly_mat_clear(A); nmod_poly_mat_clear(B); nmod_poly_mat_clear(C); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-trace.c000066400000000000000000000044511414523752600202630ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("trace...."); fflush(stdout); /* 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-window_init_clear.c000066400000000000000000000033161414523752600226640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("window_init/clear...."); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/test/t-zero.c000066400000000000000000000031761414523752600201470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "nmod_mat.h" #include "nmod_poly.h" #include "nmod_poly_mat.h" int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("zero/is_zero...."); fflush(stdout); 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"); 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"); abort(); } } nmod_poly_mat_clear(A); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_poly_mat/trace.c000066400000000000000000000014511414523752600170400ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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)); } } flint2-2.8.4/nmod_poly_mat/window_clear.c000066400000000000000000000010231414523752600204120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_poly_mat.h" void nmod_poly_mat_window_clear(nmod_poly_mat_t window) { if (window->r != 0) flint_free(window->rows); } flint2-2.8.4/nmod_poly_mat/window_init.c000066400000000000000000000017431414523752600203000ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/nmod_poly_mat/zero.c000066400000000000000000000012271414523752600167220ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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)); } flint2-2.8.4/nmod_poly_matxx.h000066400000000000000000000354201414523752600163320ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef NMOD_POLY_MATXX_H #define NMOD_POLY_MATXX_H #include "nmod_poly_mat.h" #include "nmod_matxx.h" #include "nmod_polyxx.h" #include "permxx.h" #include "flintxx/matrix.h" #include "flintxx/stdmath.h" // NOTE: it is *not* valid to use empty nmod_poly_matxx matrices! // TODO nullspace member namespace flint { FLINT_DEFINE_UNOP(sqr_interpolate) FLINT_DEFINE_BINOP(mul_interpolate) namespace detail { template struct nmod_poly_matxx_traits : matrices::generic_traits { }; } // detail template class nmod_poly_matxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; typedef detail::nmod_poly_matxx_traits traits_t; FLINTXX_DEFINE_BASICS(nmod_poly_matxx_expression) FLINTXX_DEFINE_CTORS(nmod_poly_matxx_expression) FLINTXX_DEFINE_C_REF(nmod_poly_matxx_expression, nmod_poly_mat_struct, _mat) // These only make sense with immediates nmodxx_ctx_srcref _ctx() const { return nmodxx_ctx_srcref::make(nmod_poly_mat_entry(_mat(), 0, 0)->mod); } // These work on any expression without evaluation nmodxx_ctx_srcref estimate_ctx() const { return tools::find_nmodxx_ctx(*this); } mp_limb_t modulus() const {return estimate_ctx().n();} template static evaluated_t create_temporary_rowscols( const Expr& e, slong rows, slong cols) { return evaluated_t(rows, cols, tools::find_nmodxx_ctx(e).n()); } FLINTXX_DEFINE_MATRIX_METHODS(traits_t) FLINTXX_DEFINE_FORWARD_STATIC(from_ground) static nmod_poly_matxx_expression randtest(slong rows, slong cols, mp_limb_t M, frandxx& state, slong len) { nmod_poly_matxx_expression res(rows, cols, M); res.set_randtest(state, len); return res; } static nmod_poly_matxx_expression randtest_sparse(slong rows, slong cols, mp_limb_t M, frandxx& state, slong len, float density) { nmod_poly_matxx_expression res(rows, cols, M); res.set_randtest_sparse(state, len, density); return res; } static nmod_poly_matxx_expression zero(slong rows, slong cols, mp_limb_t n) {return nmod_poly_matxx_expression(rows, cols, n);} static nmod_poly_matxx_expression one(slong rows, slong cols, mp_limb_t n) { nmod_poly_matxx_expression res(rows, cols, n); res.set_one(); return res; } // these only make sense with targets void set_randtest(frandxx& state, slong len) {nmod_poly_mat_randtest(_mat(), state._data(), len);} void set_randtest_sparse(frandxx& state, slong len, float density) {nmod_poly_mat_randtest_sparse(_mat(), state._data(), len, density);} void set_zero() {nmod_poly_mat_zero(_mat());} void set_one() {nmod_poly_mat_one(_mat());} // these cause evaluation bool is_zero() const {return nmod_poly_mat_is_zero(this->evaluate()._mat());} bool is_one() const {return nmod_poly_mat_is_one(this->evaluate()._mat());} bool is_square() const {return nmod_poly_mat_is_square(this->evaluate()._mat());} bool is_empty() const {return nmod_poly_mat_is_empty(this->evaluate()._mat());} slong max_length() const {return nmod_poly_mat_max_length(this->evaluate()._mat());} slong rank() const {return nmod_poly_mat_rank(this->evaluate()._mat());} slong find_pivot_any(slong start, slong end, slong c) const { return nmod_poly_mat_find_pivot_any( this->evaluate()._mat(), start, end, c); } slong find_pivot_partial(slong start, slong end, slong c) const { return nmod_poly_mat_find_pivot_partial( this->evaluate()._mat(), start, end, c); } // lazy members FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(nmod_polyxx, det) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(nmod_polyxx, det_fflu) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(nmod_polyxx, det_interpolate) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(nmod_polyxx, trace) FLINTXX_DEFINE_MEMBER_UNOP(sqr) FLINTXX_DEFINE_MEMBER_UNOP(sqr_classical) FLINTXX_DEFINE_MEMBER_UNOP(sqr_interpolate) FLINTXX_DEFINE_MEMBER_UNOP(sqr_KS) FLINTXX_DEFINE_MEMBER_UNOP(transpose) //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(???, nullspace) // TODO FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval) FLINTXX_DEFINE_MEMBER_BINOP(solve) FLINTXX_DEFINE_MEMBER_BINOP(solve_fflu) FLINTXX_DEFINE_MEMBER_BINOP(mul_classical) FLINTXX_DEFINE_MEMBER_BINOP(mul_interpolate) FLINTXX_DEFINE_MEMBER_BINOP(mul_KS) FLINTXX_DEFINE_MEMBER_BINOP(pow) //FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(???, rref) // TODO FLINTXX_DEFINE_MEMBER_FFLU }; namespace detail { struct nmod_poly_mat_data; } // detail typedef nmod_poly_matxx_expression< operations::immediate, detail::nmod_poly_mat_data> nmod_poly_matxx; typedef nmod_poly_matxx_expression > nmod_poly_matxx_ref; typedef nmod_poly_matxx_expression > nmod_poly_matxx_srcref; template<> struct matrix_traits { template static slong rows(const M& m) { return nmod_poly_mat_nrows(m._mat()); } template static slong cols(const M& m) { return nmod_poly_mat_ncols(m._mat()); } template static nmod_polyxx_srcref at(const M& m, slong i, slong j) { return nmod_polyxx_srcref::make(nmod_poly_mat_entry(m._mat(), i, j)); } template static nmod_polyxx_ref at(M& m, slong i, slong j) { return nmod_polyxx_ref::make(nmod_poly_mat_entry(m._mat(), i, j)); } }; namespace traits { template<> struct has_nmodxx_ctx : mp::true_ { }; template<> struct has_nmodxx_ctx : mp::true_ { }; template<> struct has_nmodxx_ctx : mp::true_ { }; } // traits namespace detail { template<> struct nmod_poly_matxx_traits : matrices::generic_traits_srcref { }; template<> struct nmod_poly_matxx_traits : matrices::generic_traits_ref { }; template<> struct nmod_poly_matxx_traits : matrices::generic_traits_nonref { }; struct nmod_poly_mat_data { typedef nmod_poly_mat_t& data_ref_t; typedef const nmod_poly_mat_t& data_srcref_t; nmod_poly_mat_t inner; nmod_poly_mat_data(slong m, slong n, mp_limb_t modulus) { nmod_poly_mat_init(inner, m, n, modulus); } nmod_poly_mat_data(const nmod_poly_mat_data& o) { nmod_poly_mat_init_set(inner, o.inner); } nmod_poly_mat_data(nmod_poly_matxx_srcref o) { nmod_poly_mat_init_set(inner, o._data().inner); } ~nmod_poly_mat_data() {nmod_poly_mat_clear(inner);} template static nmod_poly_mat_data _from_ground(const Nmod_mat& m) { nmod_poly_mat_data res(m.rows(), m.cols(), m.modulus()); for(slong i = 0;i < m.rows();++i) for(slong j = 0;j < m.cols();++j) nmod_poly_set_coeff_ui(nmod_poly_mat_entry(res.inner, i, j), 0, nmod_mat_entry(m._mat(), i, j)); return res; } template static nmod_poly_mat_data from_ground(const Nmod_mat& m, typename mp::enable_if >::type* = 0) { return _from_ground(m.evaluate()); } }; } // detail // temporary instantiation stuff FLINTXX_DEFINE_TEMPORARY_RULES(nmod_poly_matxx) #define NMOD_POLY_MATXX_COND_S FLINTXX_COND_S(nmod_poly_matxx) #define NMOD_POLY_MATXX_COND_T FLINTXX_COND_T(nmod_poly_matxx) namespace rules { FLINT_DEFINE_DOIT_COND2(assignment, NMOD_POLY_MATXX_COND_T, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_set(to._mat(), from._mat())) FLINTXX_DEFINE_SWAP(nmod_poly_matxx, nmod_poly_mat_swap(e1._mat(), e2._mat())) FLINTXX_DEFINE_EQUALS(nmod_poly_matxx, nmod_poly_mat_equal(e1._mat(), e2._mat())) FLINT_DEFINE_PRINT_PRETTY_COND_2(NMOD_POLY_MATXX_COND_S, const char*, (nmod_poly_mat_print(from._mat(), extra), 1)) FLINT_DEFINE_THREEARY_EXPR_COND3(mat_at_op, nmod_polyxx, NMOD_POLY_MATXX_COND_S, traits::fits_into_slong, traits::fits_into_slong, nmod_poly_set(to._poly(), nmod_poly_mat_entry(e1._mat(), e2, e3))) FLINT_DEFINE_BINARY_EXPR_COND2(times, nmod_poly_matxx, NMOD_POLY_MATXX_COND_S, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_mul(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, nmod_poly_matxx, NMOD_POLY_MATXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_mat_scalar_mul_nmod_poly(to._mat(), e1._mat(), e2._poly())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, nmod_poly_matxx, NMOD_POLY_MATXX_COND_S, NMODXX_COND_S, nmod_poly_mat_scalar_mul_nmod(to._mat(), e1._mat(), e2._limb())) FLINT_DEFINE_BINARY_EXPR_COND2(plus, nmod_poly_matxx, NMOD_POLY_MATXX_COND_S, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_add(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, nmod_poly_matxx, NMOD_POLY_MATXX_COND_S, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_sub(to._mat(), e1._mat(), e2._mat())) FLINT_DEFINE_UNARY_EXPR_COND(negate, nmod_poly_matxx, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_neg(to._mat(), from._mat())) namespace rdetail { inline void nmod_poly_mat_transpose(nmod_poly_mat_t to, const nmod_poly_mat_t from) { if(from == to) // guaranteed to be square { for(slong i = 0;i < nmod_poly_mat_nrows(to) - 1;++i) for(slong j = i + 1;j < nmod_poly_mat_ncols(to);++j) nmod_poly_swap(nmod_poly_mat_entry(to, i, j), nmod_poly_mat_entry(to, j, i)); } else { for(slong i = 0;i < nmod_poly_mat_nrows(to);++i) for(slong j = 0;j < nmod_poly_mat_ncols(to);++j) nmod_poly_set(nmod_poly_mat_entry(to, i, j), nmod_poly_mat_entry(from, j, i)); } } } // TODO update this when nmod_poly_mat has transpose FLINT_DEFINE_UNARY_EXPR_COND(transpose_op, nmod_poly_matxx, NMOD_POLY_MATXX_COND_S, rdetail::nmod_poly_mat_transpose(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(trace_op, nmod_polyxx, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_trace(to._poly(), from._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, nmod_matxx, NMOD_POLY_MATXX_COND_S, NMODXX_COND_S, nmod_poly_mat_evaluate_nmod(to._mat(), e1._mat(), e2._limb())) #define NMOD_POLY_MATXX_DEFINE_MUL(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, nmod_poly_matxx, \ NMOD_POLY_MATXX_COND_S, NMOD_POLY_MATXX_COND_S, \ nmod_poly_mat_##name(to._mat(), e1._mat(), e2._mat())) NMOD_POLY_MATXX_DEFINE_MUL(mul_classical) NMOD_POLY_MATXX_DEFINE_MUL(mul_KS) NMOD_POLY_MATXX_DEFINE_MUL(mul_interpolate) FLINT_DEFINE_UNARY_EXPR_COND(sqr_op, nmod_poly_matxx, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_sqr(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_KS_op, nmod_poly_matxx, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_sqr_KS(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_classical_op, nmod_poly_matxx, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_sqr_classical(to._mat(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(sqr_interpolate_op, nmod_poly_matxx, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_sqr_interpolate(to._mat(), from._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, nmod_poly_matxx, NMOD_POLY_MATXX_COND_S, traits::is_unsigned_integer, nmod_poly_mat_pow(to._mat(), e1._mat(), e2)) FLINT_DEFINE_UNARY_EXPR_COND(det_op, nmod_polyxx, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_det(to._poly(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(det_fflu_op, nmod_polyxx, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_det_fflu(to._poly(), from._mat())) FLINT_DEFINE_UNARY_EXPR_COND(det_interpolate_op, nmod_polyxx, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_det_interpolate(to._poly(), from._mat())) namespace rdetail { typedef make_ltuple::type >::type nmod_poly_mat_inv_rt; } // rdetail FLINT_DEFINE_UNARY_EXPR_COND(inv_op, rdetail::nmod_poly_mat_inv_rt, NMOD_POLY_MATXX_COND_S, to.template get<0>() = nmod_poly_mat_inv(to.template get<1>()._mat(), to.template get<2>()._poly(), from._mat())) namespace rdetail { typedef make_ltuple::type >::type nmod_poly_mat_nullspace_rt; } // rdetail FLINT_DEFINE_UNARY_EXPR_COND(nullspace_op, rdetail::nmod_poly_mat_nullspace_rt, NMOD_POLY_MATXX_COND_S, to.template get<0>() = nmod_poly_mat_nullspace( to.template get<1>()._mat(), from._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(solve_op, rdetail::nmod_poly_mat_inv_rt, NMOD_POLY_MATXX_COND_S, NMOD_POLY_MATXX_COND_S, to.template get<0>() = nmod_poly_mat_solve(to.template get<1>()._mat(), to.template get<2>()._poly(), e1._mat(), e2._mat())) FLINT_DEFINE_BINARY_EXPR_COND2(solve_fflu_op, rdetail::nmod_poly_mat_inv_rt, NMOD_POLY_MATXX_COND_S, NMOD_POLY_MATXX_COND_S, to.template get<0>() = nmod_poly_mat_solve_fflu( to.template get<1>()._mat(), to.template get<2>()._poly(), e1._mat(), e2._mat())) namespace rdetail { typedef make_ltuple::type>::type nmod_poly_matxx_fflu_rt; } // rdetail FLINT_DEFINE_THREEARY_EXPR_COND3(fflu_op, rdetail::nmod_poly_matxx_fflu_rt, NMOD_POLY_MATXX_COND_S, traits::is_maybe_perm, tools::is_bool, to.template get<0>() = nmod_poly_mat_fflu(to.template get<1>()._mat(), to.template get<2>()._poly(), maybe_perm_data(e2), e1._mat(), e3)) FLINT_DEFINE_UNARY_EXPR_COND(rref_op, rdetail::nmod_poly_matxx_fflu_rt, NMOD_POLY_MATXX_COND_S, to.template get<0>() = nmod_poly_mat_rref(to.template get<1>()._mat(), to.template get<2>()._poly(), from._mat())) FLINT_DEFINE_THREEARY_EXPR_COND3(solve_fflu_precomp_op, nmod_poly_matxx, traits::is_permxx, NMOD_POLY_MATXX_COND_S, NMOD_POLY_MATXX_COND_S, nmod_poly_mat_solve_fflu_precomp(to._mat(), e1._data(), e2._mat(), e3._mat())) } // rules } // flint #endif flint2-2.8.4/nmod_polyxx.h000066400000000000000000001112541414523752600154710ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef NMOD_POLYXX_H #define NMOD_POLYXX_H #include #include #include "nmod_poly.h" #include "fmpzxx.h" #include "nmod_vecxx.h" #include "fmpz_polyxx.h" #include "fmpq_polyxx.h" #include "flintxx/expression.h" #include "flintxx/ltuple.h" #include "flintxx/flint_classes.h" #include "flintxx/flint_exception.h" #include "flintxx/frandxx.h" #include "flintxx/stdmath.h" #include "flintxx/traits.h" // TODO exhibit this as a specialisation of a generic poly // TODO input // TODO automatic mulmod, powmod etc? // TODO use underscore function versions? // TODO nmod_series class? // TODO subproduct trees? namespace flint { FLINT_DEFINE_BINOP(div_newton) FLINT_DEFINE_BINOP(divrem_newton) FLINT_DEFINE_BINOP(evaluate_fast) FLINT_DEFINE_BINOP(evaluate_iter) FLINT_DEFINE_BINOP(exp_series_basecase) FLINT_DEFINE_BINOP(gcd_euclidean) FLINT_DEFINE_BINOP(gcd_hgcd) FLINT_DEFINE_BINOP(inv_series_basecase) FLINT_DEFINE_BINOP(nmod_polyxx_get_coeff) FLINT_DEFINE_BINOP(deflate) FLINT_DEFINE_BINOP(inflate) FLINT_DEFINE_BINOP(resultant_euclidean) FLINT_DEFINE_BINOP(taylor_shift_convolution) FLINT_DEFINE_BINOP(xgcd_euclidean) FLINT_DEFINE_BINOP(xgcd_hgcd) FLINT_DEFINE_THREEARY(compose_mod) FLINT_DEFINE_THREEARY(compose_mod_brent_kung) FLINT_DEFINE_THREEARY(compose_mod_horner) FLINT_DEFINE_THREEARY(div_newton_n_preinv) FLINT_DEFINE_THREEARY(divrem_newton_n_preinv) FLINT_DEFINE_THREEARY(exp_series_monomial) FLINT_DEFINE_THREEARY(log_series_monomial) FLINT_DEFINE_THREEARY(mulmod) FLINT_DEFINE_THREEARY(powmod_binexp) FLINT_DEFINE_BINOP(nmod_polyxx_interpolate) FLINT_DEFINE_BINOP(nmod_polyxx_interpolate_barycentric) FLINT_DEFINE_BINOP(nmod_polyxx_interpolate_fast) FLINT_DEFINE_BINOP(nmod_polyxx_interpolate_newton) FLINT_DEFINE_UNOP(nmod_polyxx_product_roots) FLINT_DEFINE_FOURARY(compose_mod_brent_kung_preinv) FLINT_DEFINE_FOURARY(mulmod_preinv) FLINT_DEFINE_FOURARY(powmod_binexp_preinv) template class nmod_polyxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; FLINTXX_DEFINE_BASICS(nmod_polyxx_expression) FLINTXX_DEFINE_CTORS(nmod_polyxx_expression) FLINTXX_DEFINE_C_REF(nmod_polyxx_expression, nmod_poly_struct, _poly) // static functions for nmod_polyxx template static FLINT_BINOP_ENABLE_RETTYPE(nmod_polyxx_interpolate, Nmod_vec1, Nmod_vec2) interpolate(const Nmod_vec1& xs, const Nmod_vec2& ys) { return nmod_polyxx_interpolate(xs, ys); } template static FLINT_BINOP_ENABLE_RETTYPE(nmod_polyxx_interpolate_fast, Nmod_vec1, Nmod_vec2) interpolate_fast(const Nmod_vec1& xs, const Nmod_vec2& ys) { return nmod_polyxx_interpolate_fast(xs, ys); } template static FLINT_BINOP_ENABLE_RETTYPE(nmod_polyxx_interpolate_newton, Nmod_vec1, Nmod_vec2) interpolate_newton(const Nmod_vec1& xs, const Nmod_vec2& ys) { return nmod_polyxx_interpolate_newton(xs, ys); } template static FLINT_BINOP_ENABLE_RETTYPE(nmod_polyxx_interpolate_barycentric, Nmod_vec1, Nmod_vec2) interpolate_barycentric(const Nmod_vec1& xs, const Nmod_vec2& ys) { return nmod_polyxx_interpolate_barycentric(xs, ys); } template static FLINT_UNOP_ENABLE_RETTYPE(nmod_polyxx_product_roots, Nmod_vec) product_roots(const Nmod_vec& xs) { return nmod_polyxx_product_roots(xs); } // XXX this is difficult to make lazy template static typename mp::enable_if, nmod_polyxx_expression>::type bit_unpack(const Fmpz& a, flint_bitcnt_t bits, nmodxx_ctx_srcref modulus) { nmod_polyxx_expression res(modulus); nmod_poly_bit_unpack(res._poly(), a.evaluate()._fmpz(), bits); return res; } FLINTXX_DEFINE_FORWARD_STATIC(from_ground) FLINTXX_DEFINE_FORWARD_STATIC(reduce) static nmod_polyxx_expression zero(mp_limb_t n) {return nmod_polyxx_expression(n);} static nmod_polyxx_expression one(mp_limb_t n) { nmod_polyxx_expression res(n); res.set_one(); return res; } static nmod_polyxx_expression randtest(mp_limb_t n, frandxx& state, slong len) { nmod_polyxx_expression res(n); res.set_randtest(state, len); return res; } static nmod_polyxx_expression randtest_irreducible(mp_limb_t n, frandxx& state, slong len) { nmod_polyxx_expression res(n); res.set_randtest_irreducible(state, len); return res; } // these only make sense with immediates void realloc(slong alloc) {nmod_poly_realloc(_poly(), alloc);} void fit_length(slong len) {nmod_poly_fit_length(_poly(), len);} void _normalise() {_nmod_poly_normalise(_poly());} nmodxx_ctx_srcref _ctx() const {return nmodxx_ctx_srcref::make(_poly()->mod);} void set_zero() {nmod_poly_zero(_poly());} void set_one() {nmod_poly_one(_poly());} // These only make sense with target immediates void set_coeff(slong n, ulong c) {nmod_poly_set_coeff_ui(_poly(), n, c);} template typename mp::enable_if >::type set_coeff(slong j, const Nmod& c) { // TODO this does not need reduction nmod_poly_set_coeff_ui(_poly(), j, c.template to()); } void truncate(slong n) {nmod_poly_truncate(_poly(), n);} void set_randtest(frandxx& state, slong len) {nmod_poly_randtest(_poly(), state._data(), len);} void set_randtest_irreducible(frandxx& state, slong len) {nmod_poly_randtest_irreducible(_poly(), state._data(), len);} template slong remove(const Poly& p) { return nmod_poly_remove(_poly(), p.evaluate()._poly()); } // These work on any expression without evaluation nmodxx_ctx_srcref estimate_ctx() const; mp_limb_t modulus() const {return estimate_ctx().n();} evaluated_t create_temporary() const { return evaluated_t(estimate_ctx()); } // These cause evaluation slong length() const {return nmod_poly_length(this->evaluate()._poly());} slong degree() const {return nmod_poly_degree(this->evaluate()._poly());} bool is_one() const {return nmod_poly_is_one(this->evaluate()._poly());} bool is_zero() const {return nmod_poly_is_zero(this->evaluate()._poly());} bool is_squarefree() const {return nmod_poly_is_squarefree(this->evaluate()._poly());} bool is_irreducible() const {return nmod_poly_is_irreducible(this->evaluate()._poly());} slong max_bits() const {return nmod_poly_max_bits(this->evaluate()._poly());} ulong deflation() const {return nmod_poly_deflation(this->evaluate()._poly());} // Lazy members FLINTXX_DEFINE_MEMBER_BINOP_(get_coeff, nmod_polyxx_get_coeff) FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval) FLINTXX_DEFINE_MEMBER_BINOP(inflate) FLINTXX_DEFINE_MEMBER_BINOP(deflate) FLINTXX_DEFINE_MEMBER_BINOP(compose_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(compose_horner) FLINTXX_DEFINE_MEMBER_BINOP(div_basecase) FLINTXX_DEFINE_MEMBER_BINOP(div_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(div_newton) FLINTXX_DEFINE_MEMBER_BINOP(divrem) FLINTXX_DEFINE_MEMBER_BINOP(divrem_basecase) FLINTXX_DEFINE_MEMBER_BINOP(divrem_divconquer) FLINTXX_DEFINE_MEMBER_BINOP(divrem_newton) FLINTXX_DEFINE_MEMBER_BINOP(div_root) FLINTXX_DEFINE_MEMBER_BINOP(evaluate_fast) FLINTXX_DEFINE_MEMBER_BINOP(evaluate_iter) FLINTXX_DEFINE_MEMBER_BINOP(gcd) FLINTXX_DEFINE_MEMBER_BINOP(gcd_euclidean) FLINTXX_DEFINE_MEMBER_BINOP(gcd_hgcd) FLINTXX_DEFINE_MEMBER_BINOP(inv_series) FLINTXX_DEFINE_MEMBER_BINOP(inv_series_basecase) FLINTXX_DEFINE_MEMBER_BINOP(inv_series_newton) FLINTXX_DEFINE_MEMBER_BINOP(invsqrt_series) FLINTXX_DEFINE_MEMBER_BINOP(mul_classical) FLINTXX_DEFINE_MEMBER_BINOP(mul_KS) FLINTXX_DEFINE_MEMBER_BINOP(shift_left) FLINTXX_DEFINE_MEMBER_BINOP(shift_right) FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_BINOP(pow_binexp) FLINTXX_DEFINE_MEMBER_BINOP(rem_basecase) FLINTXX_DEFINE_MEMBER_BINOP(resultant) FLINTXX_DEFINE_MEMBER_BINOP(resultant_euclidean) FLINTXX_DEFINE_MEMBER_BINOP(reverse) FLINTXX_DEFINE_MEMBER_BINOP(revert_series) FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange) FLINTXX_DEFINE_MEMBER_BINOP(revert_series_lagrange_fast) FLINTXX_DEFINE_MEMBER_BINOP(revert_series_newton) FLINTXX_DEFINE_MEMBER_BINOP(sqrt_series) FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift) FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift_convolution) FLINTXX_DEFINE_MEMBER_BINOP(taylor_shift_horner) FLINTXX_DEFINE_MEMBER_BINOP(xgcd) FLINTXX_DEFINE_MEMBER_BINOP(xgcd_euclidean) FLINTXX_DEFINE_MEMBER_BINOP(xgcd_hgcd) FLINTXX_DEFINE_MEMBER_BINOP(log_series) FLINTXX_DEFINE_MEMBER_BINOP(exp_series) FLINTXX_DEFINE_MEMBER_BINOP(exp_series_basecase) FLINTXX_DEFINE_MEMBER_BINOP(atan_series) FLINTXX_DEFINE_MEMBER_BINOP(atanh_series) FLINTXX_DEFINE_MEMBER_BINOP(asin_series) FLINTXX_DEFINE_MEMBER_BINOP(asinh_series) FLINTXX_DEFINE_MEMBER_BINOP(sin_series) FLINTXX_DEFINE_MEMBER_BINOP(cos_series) FLINTXX_DEFINE_MEMBER_BINOP(tan_series) FLINTXX_DEFINE_MEMBER_BINOP(sinh_series) FLINTXX_DEFINE_MEMBER_BINOP(cosh_series) FLINTXX_DEFINE_MEMBER_BINOP(tanh_series) FLINTXX_DEFINE_MEMBER_BINOP(bit_pack) FLINTXX_DEFINE_MEMBER_UNOP(derivative) FLINTXX_DEFINE_MEMBER_UNOP(integral) FLINTXX_DEFINE_MEMBER_UNOP(make_monic) FLINTXX_DEFINE_MEMBER_UNOP(sqrt) FLINTXX_DEFINE_MEMBER_3OP(compose_mod) FLINTXX_DEFINE_MEMBER_3OP(compose_mod_horner) FLINTXX_DEFINE_MEMBER_3OP(compose_mod_brent_kung) FLINTXX_DEFINE_MEMBER_3OP(compose_series) FLINTXX_DEFINE_MEMBER_3OP(compose_series_brent_kung) FLINTXX_DEFINE_MEMBER_3OP(compose_series_divconquer) FLINTXX_DEFINE_MEMBER_3OP(compose_series_horner) FLINTXX_DEFINE_MEMBER_3OP(div_newton_n_preinv) FLINTXX_DEFINE_MEMBER_3OP(divrem_newton_n_preinv) FLINTXX_DEFINE_MEMBER_3OP(div_series) FLINTXX_DEFINE_MEMBER_3OP(mulhigh) FLINTXX_DEFINE_MEMBER_3OP(mulhigh_classical) FLINTXX_DEFINE_MEMBER_3OP(mullow) FLINTXX_DEFINE_MEMBER_3OP(mullow_classical) FLINTXX_DEFINE_MEMBER_3OP(mullow_KS) FLINTXX_DEFINE_MEMBER_3OP(mulmod) FLINTXX_DEFINE_MEMBER_3OP(powmod_binexp) FLINTXX_DEFINE_MEMBER_3OP(pow_trunc) FLINTXX_DEFINE_MEMBER_3OP(pow_trunc_binexp) FLINTXX_DEFINE_MEMBER_4OP(compose_mod_brent_kung_preinv) FLINTXX_DEFINE_MEMBER_4OP(mulmod_preinv) FLINTXX_DEFINE_MEMBER_4OP(powmod_binexp_preinv) }; namespace detail { struct nmod_poly_data; } typedef nmod_polyxx_expression nmod_polyxx; typedef nmod_polyxx_expression > nmod_polyxx_ref; typedef nmod_polyxx_expression > nmod_polyxx_srcref; namespace detail { struct nmod_poly_data { nmod_poly_t inner; typedef nmod_poly_t& data_ref_t; typedef const nmod_poly_t& data_srcref_t; nmod_poly_data(mp_limb_t n) {nmod_poly_init(inner, n);} nmod_poly_data(nmodxx_ctx_srcref c) { nmod_poly_init_preinv(inner, c.n(), c._nmod().ninv); } nmod_poly_data(mp_limb_t n, slong alloc) {nmod_poly_init2(inner, n, alloc);} nmod_poly_data(nmodxx_ctx_srcref c, slong alloc) { nmod_poly_init2_preinv(inner, c.n(), c._nmod().ninv, alloc); } ~nmod_poly_data() {nmod_poly_clear(inner);} nmod_poly_data(const nmod_poly_data& o) { nmod_poly_init2_preinv(inner, o.inner->mod.n, o.inner->mod.ninv, o.inner->length); nmod_poly_set(inner, o.inner); } nmod_poly_data(nmod_polyxx_srcref r) { nmod_poly_init2_preinv(inner, r.modulus(), r._poly()->mod.ninv, r.length()); nmod_poly_set(inner, r._poly()); } nmod_poly_data(const char* str) { mp_limb_t n;slong length; execution_check(flint_sscanf(str, "%wd %wu", &length, &n) == 2 && (nmod_poly_init2(inner, n, length), nmod_poly_set_str(inner, str)), "construct from string", "nmod_polyxx"); } template static nmod_poly_data from_ground(const Nmod& x, typename mp::enable_if >::type* = 0) { nmod_poly_data res(x.estimate_ctx()); nmod_poly_set_coeff_ui(res.inner, 0, x.template to()); return res; } static nmod_poly_data from_ground(mp_limb_t x, nmodxx_ctx_srcref c) { nmod_poly_data res(c); nmod_poly_set_coeff_ui(res.inner, 0, x); return res; } // TODO maybe make these lazy template static nmod_poly_data reduce(const Fmpz_poly& p, nmodxx_ctx_srcref c, typename mp::enable_if >::type* = 0) { nmod_poly_data res(c); fmpz_poly_get_nmod_poly(res.inner, p.evaluate()._poly()); return res; } template static nmod_poly_data reduce(const Fmpz_poly& p, mp_limb_t m, typename mp::enable_if >::type* = 0) { nmod_poly_data res(m); fmpz_poly_get_nmod_poly(res.inner, p.evaluate()._poly()); return res; } template static nmod_poly_data reduce_(const Fmpq_poly& p, nmodxx_ctx_srcref c, typename mp::enable_if >::type* = 0) { nmod_poly_data res(c, p.length()); for(slong i = 0;i < p.length();++i) nmod_poly_set_coeff_ui(res. inner, i, nmodxx::red(p.get_coeff(i), c).template to()); return res; } template static nmod_poly_data reduce(const Fmpq_poly& p, nmodxx_ctx_srcref c, typename mp::enable_if >::type* = 0) { return reduce_(p.evaluate(), c); } template static nmod_poly_data reduce(const Fmpq_poly& p, mp_limb_t m, typename mp::enable_if >::type* = 0) { return reduce_(p.evaluate(), nmodxx_ctx(m)); } }; } // detail namespace traits { template<> struct has_nmodxx_ctx : mp::true_ { }; template<> struct has_nmodxx_ctx : mp::true_ { }; template<> struct has_nmodxx_ctx : mp::true_ { }; template struct is_nmod_polyxx : mp::or_< traits::is_T_expr, flint_classes::is_source > { }; } // traits template inline nmodxx_ctx_srcref nmod_polyxx_expression::estimate_ctx() const { return tools::find_nmodxx_ctx(*this); } namespace rules { #define NMOD_POLYXX_COND_S FLINTXX_COND_S(nmod_polyxx) #define NMOD_POLYXX_COND_T FLINTXX_COND_T(nmod_polyxx) NMODXX_DEFINE_INSTANTIATE_TEMPORARIES(nmod_polyxx) FLINT_DEFINE_DOIT_COND2(assignment, NMOD_POLYXX_COND_T, NMOD_POLYXX_COND_S, nmod_poly_set(to._poly(), from._poly())) FLINTXX_DEFINE_ASSIGN_STR(nmod_polyxx, execution_check( nmod_poly_set_str(to._poly(), from), "assign string", "nmod_polyxx")) FLINT_DEFINE_PRINT_COND(NMOD_POLYXX_COND_S, nmod_poly_fprint(to, from._poly())) FLINT_DEFINE_READ_COND(NMOD_POLYXX_COND_T, nmod_poly_fread(from, to._poly())) FLINTXX_DEFINE_EQUALS(nmod_polyxx, nmod_poly_equal(e1._poly(), e2._poly())) FLINTXX_DEFINE_TO_STR(nmod_polyxx, nmod_poly_get_str(from._poly())) FLINTXX_DEFINE_SWAP(nmod_polyxx, nmod_poly_swap(e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_get_coeff_op, nmodxx, NMOD_POLYXX_COND_S, traits::fits_into_slong, to.set_nored(nmod_poly_get_coeff_ui(e1._poly(), e2))) FLINT_DEFINE_BINARY_EXPR_COND2(plus, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_add(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_sub(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_UNARY_EXPR_COND(negate, nmod_polyxx, NMOD_POLYXX_COND_S, nmod_poly_neg(to._poly(), from._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(reverse_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::fits_into_slong, nmod_poly_reverse(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::fits_into_slong, nmod_poly_shift_left(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::fits_into_slong, nmod_poly_shift_right(to._poly(), e1._poly(), e2)) FLINT_DEFINE_CBINARY_EXPR_COND2(times, nmod_polyxx, NMOD_POLYXX_COND_S, NMODXX_COND_S, nmod_poly_scalar_mul_nmod(to._poly(), e1._poly(), e2._limb())) FLINT_DEFINE_UNARY_EXPR_COND(make_monic_op, nmod_polyxx, NMOD_POLYXX_COND_S, nmod_poly_make_monic(to._poly(), from._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(bit_pack_op, fmpzxx, NMOD_POLYXX_COND_S, traits::fits_into_flint_bitcnt_t, nmod_poly_bit_pack(to._fmpz(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(times, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_mul(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(mul_classical_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_mul_classical(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(mul_KS_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_mul_KS(to._poly(), e1._poly(), e2._poly(), 0 /* TODO */)) #define NMOD_POLYXX_DEFINE_MULFUNC(name) \ FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, nmod_polyxx, \ NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, traits::fits_into_slong, \ nmod_poly_##name(to._poly(), e1._poly(), e2._poly(), e3)) NMOD_POLYXX_DEFINE_MULFUNC(mullow_classical) NMOD_POLYXX_DEFINE_MULFUNC(mullow) NMOD_POLYXX_DEFINE_MULFUNC(mulhigh_classical) NMOD_POLYXX_DEFINE_MULFUNC(mulhigh) FLINT_DEFINE_THREEARY_EXPR_COND3(mullow_KS_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, traits::fits_into_slong, nmod_poly_mullow_KS(to._poly(), e1._poly(), e2._poly(), 0 /* TODO */, e3)) FLINT_DEFINE_THREEARY_EXPR_COND3(mulmod_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_mulmod(to._poly(), e1._poly(), e2._poly(), e3._poly())) FLINT_DEFINE_FOURARY_EXPR_COND4(mulmod_preinv_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_mulmod_preinv(to._poly(), e1._poly(), e2._poly(), e3._poly(), e4._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(pow_binexp_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::is_unsigned_integer, nmod_poly_pow_binexp(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::is_unsigned_integer, nmod_poly_pow(to._poly(), e1._poly(), e2)) FLINT_DEFINE_THREEARY_EXPR_COND3(powmod_binexp_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::is_unsigned_integer, NMOD_POLYXX_COND_S, nmod_poly_powmod_ui_binexp(to._poly(), e1._poly(), e2, e3._poly())) FLINT_DEFINE_FOURARY_EXPR_COND4(powmod_binexp_preinv_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::is_unsigned_integer, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_powmod_ui_binexp_preinv(to._poly(), e1._poly(), e2, e3._poly(), e4._poly())) FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong, nmod_poly_pow_trunc(to._poly(), e1._poly(), e2, e3)) FLINT_DEFINE_THREEARY_EXPR_COND3(pow_trunc_binexp_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong, nmod_poly_pow_trunc_binexp(to._poly(), e1._poly(), e2, e3)) FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, nmod_polyxx, NMOD_POLYXX_COND_S, nmod_poly_derivative(to._poly(), from._poly())) FLINT_DEFINE_UNARY_EXPR_COND(integral_op, nmod_polyxx, NMOD_POLYXX_COND_S, nmod_poly_integral(to._poly(), from._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, nmodxx, NMOD_POLYXX_COND_S, NMODXX_COND_S, to.set_nored(nmod_poly_evaluate_nmod(e1._poly(), e2._limb()))) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, nmod_vecxx, NMOD_POLYXX_COND_S, NMOD_VECXX_COND_S, nmod_poly_evaluate_nmod_vec(to._array(), e1._poly(), e2._array(), to.size())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_fast_op, nmod_vecxx, NMOD_POLYXX_COND_S, NMOD_VECXX_COND_S, nmod_poly_evaluate_nmod_vec_fast(to._array(), e1._poly(), e2._array(), to.size())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_iter_op, nmod_vecxx, NMOD_POLYXX_COND_S, NMOD_VECXX_COND_S, nmod_poly_evaluate_nmod_vec_iter(to._array(), e1._poly(), e2._array(), to.size())) namespace rdetail { typedef make_ltuple::type>::type nmod_polyxx_pair; } // rdetail #define NMOD_POLYXX_DEFINE_DIVREM(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, rdetail::nmod_polyxx_pair, \ NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, \ nmod_poly_##name(to.template get<0>()._poly(), to.template get<1>()._poly(), \ e1._poly(), e2._poly())) NMOD_POLYXX_DEFINE_DIVREM(divrem_basecase) NMOD_POLYXX_DEFINE_DIVREM(divrem_divconquer) NMOD_POLYXX_DEFINE_DIVREM(divrem_newton) NMOD_POLYXX_DEFINE_DIVREM(divrem) FLINT_DEFINE_BINARY_EXPR_COND2(div_basecase_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_div_basecase(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(div_divconquer_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_div_divconquer(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(div_newton_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_div_newton(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_div_divconquer(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_THREEARY_EXPR_COND3(div_newton_n_preinv_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_div_newton_n_preinv(to._poly(), e1._poly(), e2._poly(), e3._poly())) FLINT_DEFINE_THREEARY_EXPR_COND3(divrem_newton_n_preinv_op, rdetail::nmod_polyxx_pair, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_divrem_newton_n_preinv(to.template get<0>()._poly(), to.template get<1>()._poly(), e1._poly(), e2._poly(), e3._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(rem_basecase_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_rem_basecase(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(modulo, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_rem(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_newton_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::fits_into_slong, nmod_poly_inv_series_newton(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::fits_into_slong, nmod_poly_inv_series(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_basecase_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::fits_into_slong, nmod_poly_inv_series_basecase(to._poly(), e1._poly(), e2)) #define NMOD_POLYXX_DEFINE_SERIES(name) \ FLINT_DEFINE_THREEARY_EXPR_COND3(name##_op, nmod_polyxx, \ NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, traits::fits_into_slong, \ nmod_poly_##name(to._poly(), e1._poly(), e2._poly(), e3)) NMOD_POLYXX_DEFINE_SERIES(div_series) FLINT_DEFINE_BINARY_EXPR_COND2(compose_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_compose(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(compose_divconquer_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_compose_divconquer(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(compose_horner_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_compose_horner(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(div_root_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMODXX_COND_S, nmod_poly_div_root(to._poly(), e1._poly(), e2._limb())) FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_interpolate_op, nmod_polyxx, NMOD_VECXX_COND_S, NMOD_VECXX_COND_S, nmod_poly_interpolate_nmod_vec(to._poly(), e1._data().array, e2._data().array, e2.size())) FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_interpolate_fast_op, nmod_polyxx, NMOD_VECXX_COND_S, NMOD_VECXX_COND_S, nmod_poly_interpolate_nmod_vec_fast(to._poly(), e1._data().array, e2._data().array, e2.size())) FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_interpolate_newton_op, nmod_polyxx, NMOD_VECXX_COND_S, NMOD_VECXX_COND_S, nmod_poly_interpolate_nmod_vec_newton(to._poly(), e1._data().array, e2._data().array, e2.size())) FLINT_DEFINE_BINARY_EXPR_COND2(nmod_polyxx_interpolate_barycentric_op, nmod_polyxx, NMOD_VECXX_COND_S, NMOD_VECXX_COND_S, nmod_poly_interpolate_nmod_vec_barycentric(to._poly(), e1._data().array, e2._data().array, e2.size())) FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_horner_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMODXX_COND_S, nmod_poly_taylor_shift_horner(to._poly(), e1._poly(), e2._limb())) FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_convolution_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMODXX_COND_S, nmod_poly_taylor_shift_convolution(to._poly(), e1._poly(), e2._limb())) FLINT_DEFINE_BINARY_EXPR_COND2(taylor_shift_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMODXX_COND_S, nmod_poly_taylor_shift(to._poly(), e1._poly(), e2._limb())) FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_compose_mod(to._poly(), e1._poly(), e2._poly(), e3._poly())) FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_horner_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_compose_mod_horner( to._poly(), e1._poly(), e2._poly(), e3._poly())) FLINT_DEFINE_THREEARY_EXPR_COND3(compose_mod_brent_kung_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_compose_mod_brent_kung( to._poly(), e1._poly(), e2._poly(), e3._poly())) FLINT_DEFINE_FOURARY_EXPR_COND4(compose_mod_brent_kung_preinv_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_compose_mod_brent_kung_preinv( to._poly(), e1._poly(), e2._poly(), e3._poly(), e4._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(gcd_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_gcd(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(gcd_hgcd_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_gcd_hgcd(to._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(gcd_euclidean_op, nmod_polyxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_gcd_euclidean(to._poly(), e1._poly(), e2._poly())) namespace rdetail { typedef make_ltuple::type>::type nmod_polyxx_triple; } // rdetail FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_op, rdetail::nmod_polyxx_triple, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_xgcd(to.template get<0>()._poly(), to.template get<1>()._poly(), to.template get<2>()._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_hgcd_op, rdetail::nmod_polyxx_triple, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_xgcd_hgcd(to.template get<0>()._poly(), to.template get<1>()._poly(), to.template get<2>()._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(xgcd_euclidean_op, rdetail::nmod_polyxx_triple, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, nmod_poly_xgcd_euclidean(to.template get<0>()._poly(), to.template get<1>()._poly(), to.template get<2>()._poly(), e1._poly(), e2._poly())) FLINT_DEFINE_BINARY_EXPR_COND2(resultant_op, nmodxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, to.set_nored(nmod_poly_resultant(e1._poly(), e2._poly()))) FLINT_DEFINE_BINARY_EXPR_COND2(resultant_euclidean_op, nmodxx, NMOD_POLYXX_COND_S, NMOD_POLYXX_COND_S, to.set_nored(nmod_poly_resultant_euclidean(e1._poly(), e2._poly()))) NMOD_POLYXX_DEFINE_SERIES(compose_series) NMOD_POLYXX_DEFINE_SERIES(compose_series_horner) NMOD_POLYXX_DEFINE_SERIES(compose_series_brent_kung) NMOD_POLYXX_DEFINE_SERIES(compose_series_divconquer) #define NMOD_POLYXX_DEFINE_SERIESUN(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_op, nmod_polyxx, \ NMOD_POLYXX_COND_S, traits::fits_into_slong, \ nmod_poly_##name(to._poly(), e1._poly(), e2)) NMOD_POLYXX_DEFINE_SERIESUN(revert_series) NMOD_POLYXX_DEFINE_SERIESUN(revert_series_newton) NMOD_POLYXX_DEFINE_SERIESUN(revert_series_lagrange_fast) NMOD_POLYXX_DEFINE_SERIESUN(revert_series_lagrange) #define NMOD_POLYXX_DEFINE_SERIES_F(name) \ FLINT_DEFINE_BINARY_EXPR_COND2(name##_series_op, nmod_polyxx, \ NMOD_POLYXX_COND_S, traits::fits_into_slong, \ nmod_poly_##name##_series(to._poly(), e1._poly(), e2)) NMOD_POLYXX_DEFINE_SERIES_F(sqrt) NMOD_POLYXX_DEFINE_SERIES_F(invsqrt) NMOD_POLYXX_DEFINE_SERIES_F(log) NMOD_POLYXX_DEFINE_SERIES_F(exp) NMOD_POLYXX_DEFINE_SERIES_F(atan) NMOD_POLYXX_DEFINE_SERIES_F(atanh) NMOD_POLYXX_DEFINE_SERIES_F(asin) NMOD_POLYXX_DEFINE_SERIES_F(asinh) NMOD_POLYXX_DEFINE_SERIES_F(sin) NMOD_POLYXX_DEFINE_SERIES_F(cos) NMOD_POLYXX_DEFINE_SERIES_F(tan) NMOD_POLYXX_DEFINE_SERIES_F(sinh) NMOD_POLYXX_DEFINE_SERIES_F(cosh) NMOD_POLYXX_DEFINE_SERIES_F(tanh) FLINT_DEFINE_BINARY_EXPR_COND2(exp_series_basecase_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::fits_into_slong, nmod_poly_exp_series_basecase(to._poly(), e1._poly(), e2)) FLINT_DEFINE_THREEARY_EXPR_COND3(log_series_monomial_op, nmod_polyxx, NMODXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong, nmod_poly_log_series_monomial_ui(to._poly(), e1._limb(), e2, e3)) FLINT_DEFINE_THREEARY_EXPR_COND3(exp_series_monomial_op, nmod_polyxx, NMODXX_COND_S, traits::is_unsigned_integer, traits::fits_into_slong, nmod_poly_exp_series_monomial_ui(to._poly(), e1._limb(), e2, e3)) FLINT_DEFINE_UNARY_EXPR_COND(sqrt_op, nmod_polyxx, NMOD_POLYXX_COND_S, execution_check(nmod_poly_sqrt(to._poly(), from._poly()), "sqrt", "nmod_polyxx")) FLINT_DEFINE_UNARY_EXPR_COND(nmod_polyxx_product_roots_op, nmod_polyxx, NMOD_VECXX_COND_S, nmod_poly_product_roots_nmod_vec(to._poly(), from._data().array, from.size())) FLINT_DEFINE_BINARY_EXPR_COND2(deflate_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::is_unsigned_integer, nmod_poly_deflate(to._poly(), e1._poly(), e2)) FLINT_DEFINE_BINARY_EXPR_COND2(inflate_op, nmod_polyxx, NMOD_POLYXX_COND_S, traits::is_unsigned_integer, nmod_poly_inflate(to._poly(), e1._poly(), e2)) } // rules ////////////////////////////////////////////////////////////////////////////// // FACTORISATION ////////////////////////////////////////////////////////////////////////////// class nmod_poly_factorxx { private: nmod_poly_factor_t inner; public: nmod_poly_factorxx() {nmod_poly_factor_init(inner);} ~nmod_poly_factorxx() {nmod_poly_factor_clear(inner);} nmod_poly_factorxx(const nmod_poly_factorxx& o) { nmod_poly_factor_init(inner); nmod_poly_factor_set(inner, o.inner); } bool operator==(const nmod_poly_factorxx& o) { if(o.size() != size()) return false; for(slong i = 0;i < size();++i) if(p(i) != o.p(i) || exp(i) != o.exp(i)) return false; return true; } nmod_poly_factorxx& operator=(const nmod_poly_factorxx& o) { nmod_poly_factor_set(inner, o.inner); return *this; } slong size() const {return inner->num;} slong exp(slong i) const {return inner->exp[i];} slong& exp(slong i) {return inner->exp[i];} nmod_polyxx_srcref p(slong i) const {return nmod_polyxx_srcref::make(inner->p + i);} nmod_polyxx_ref p(slong i) {return nmod_polyxx_ref::make(inner->p + i);} nmod_poly_factor_t& _data() {return inner;} const nmod_poly_factor_t& _data() const {return inner;} void realloc(slong a) {nmod_poly_factor_realloc(inner, a);} void fit_length(slong a) {nmod_poly_factor_fit_length(inner, a);} void print() const {nmod_poly_factor_print(inner);} template void insert(const Nmod_poly& p, slong e, typename mp::enable_if >::type* = 0) {nmod_poly_factor_insert(_data(), p.evaluate()._poly(), e);} void concat(const nmod_poly_factorxx& o) {nmod_poly_factor_concat(_data(), o._data());} void pow(slong exp) {nmod_poly_factor_pow(_data(), exp);} #define NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(name) \ template \ void set_##name(const Nmod_poly& p, \ typename mp::enable_if >::type* = 0) \ {nmod_poly_##name(_data(), p.evaluate()._poly());} NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor) NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_squarefree) NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_cantor_zassenhaus) NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_berlekamp) NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_kaltofen_shoup) NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_with_cantor_zassenhaus) NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_with_berlekamp) NMOD_POLY_FACTORXX_DEFINE_SET_FACTOR(factor_with_kaltofen_shoup) template bool set_factor_equal_deg_probab(frandxx& state, const Nmod_poly& p, slong d, typename mp::enable_if >::type* = 0) { return nmod_poly_factor_equal_deg_prob(_data(), state._data(), p.evaluate()._poly(), d); } template void set_factor_equal_deg(const Nmod_poly& p, slong d, typename mp::enable_if >::type* = 0) { nmod_poly_factor_equal_deg(_data(), p.evaluate()._poly(), d); } template void set_factor_distinct_deg(const Nmod_poly& p, std::vector& degs, typename mp::enable_if >::type* = 0) { slong* dgs = °s.front(); nmod_poly_factor_distinct_deg(_data(), p.evaluate()._poly(), &dgs); } }; #define NMOD_POLY_FACTORXX_DEFINE_FACTOR(name) \ template \ nmod_poly_factorxx name(const Nmod_poly& p, \ typename mp::enable_if >::type* = 0) \ { \ nmod_poly_factorxx res; \ res.set_##name(p); \ return res; \ } NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor) NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_squarefree) NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_cantor_zassenhaus) NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_berlekamp) NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_kaltofen_shoup) NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_with_cantor_zassenhaus) NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_with_berlekamp) NMOD_POLY_FACTORXX_DEFINE_FACTOR(factor_with_kaltofen_shoup) // TODO do we want global versions of factor_distinct_deg etc? inline void print(const nmod_poly_factorxx& f) { f.print(); } // CRT stuff // Here for circular dependency reasons namespace rules { FLINT_DEFINE_FOURARY_EXPR_COND4(CRT_op, fmpz_polyxx, FMPZ_POLYXX_COND_T, FMPZXX_COND_S, NMOD_POLYXX_COND_S, tools::is_bool, fmpz_poly_CRT_ui(to._poly(), e1._poly(), e2._fmpz(), e3._poly(), e4)) } // rules } // flint #endif flint2-2.8.4/nmod_vec.h000066400000000000000000000314351414523752600147050ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define NMOD_VEC_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "longlong.h" #include "ulong_extras.h" #include "flint.h" #ifdef __cplusplus extern "C" { #endif typedef struct { mp_limb_t n; mp_limb_t ninv; flint_bitcnt_t norm; } nmod_t; #define NMOD_VEC_NORM(vec, i) \ do { \ while ((i) && vec[(i) - 1] == UWORD(0)) \ (i)--; \ } while (0) #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_ADDMUL(r, a, b, mod) \ do { \ mp_limb_t a_hi, a_lo; \ umul_ppmm(a_hi, a_lo, a, b); \ add_ssaaaa(a_hi, a_lo, a_hi, a_lo, (mp_limb_t) 0, r); \ NMOD_RED2(r, a_hi, a_lo, mod); \ } while (0) NMOD_VEC_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_VEC_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_VEC_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_VEC_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_VEC_INLINE mp_limb_t nmod_neg(mp_limb_t a, nmod_t mod) { if (a) return mod.n - a; else return 0; } NMOD_VEC_INLINE mp_limb_t nmod_mul(mp_limb_t a, mp_limb_t b, nmod_t mod) { mp_limb_t res, hi, lo; umul_ppmm(hi, lo, a, b); NMOD_RED2(res, hi, lo, mod); return res; } NMOD_VEC_INLINE mp_limb_t nmod_addmul(mp_limb_t a, mp_limb_t b, mp_limb_t c, nmod_t mod) { NMOD_ADDMUL(a, b, c, mod); return a; } NMOD_VEC_INLINE mp_limb_t nmod_inv(mp_limb_t a, nmod_t mod) { return n_invmod(a, mod.n); } NMOD_VEC_INLINE mp_limb_t nmod_div(mp_limb_t a, mp_limb_t b, nmod_t mod) { b = n_invmod(b, mod.n); return n_mulmod2_preinv(a, b, mod.n, mod.ninv); } NMOD_VEC_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); } /* This function is in fmpz.h FMPZ_INLINE mp_limb_t nmod_pow_fmpz(mp_limb_t a, const fmpz_t exp, nmod_t mod) */ NMOD_VEC_INLINE void nmod_init(nmod_t * mod, mp_limb_t n) { mod->n = n; mod->ninv = n_preinvert_limb(n); count_leading_zeros(mod->norm, n); } 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); } FLINT_DLL 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_DLL 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; } FLINT_DLL void _nmod_vec_reduce(mp_ptr res, mp_srcptr vec, slong len, nmod_t mod); FLINT_DLL void _nmod_vec_add(mp_ptr res, mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod); FLINT_DLL void _nmod_vec_sub(mp_ptr res, mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod); FLINT_DLL void _nmod_vec_neg(mp_ptr res, mp_srcptr vec, slong len, nmod_t mod); FLINT_DLL void _nmod_vec_scalar_mul_nmod(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod); FLINT_DLL void _nmod_vec_scalar_mul_nmod_shoup(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod); FLINT_DLL void _nmod_vec_scalar_addmul_nmod(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod); FLINT_DLL 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); FLINT_DLL mp_limb_t _nmod_vec_dot(mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod, int nlimbs); FLINT_DLL mp_limb_t _nmod_vec_dot_rev(mp_srcptr vec1, mp_srcptr vec2, slong len, nmod_t mod, int nlimbs); FLINT_DLL mp_limb_t _nmod_vec_dot_ptr(mp_srcptr vec1, const mp_ptr * vec2, slong offset, slong len, nmod_t mod, int nlimbs); /* 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]; FLINT_DLL void nmod_discrete_log_pohlig_hellman_init( nmod_discrete_log_pohlig_hellman_t L); FLINT_DLL void nmod_discrete_log_pohlig_hellman_clear( nmod_discrete_log_pohlig_hellman_t L); FLINT_DLL double nmod_discrete_log_pohlig_hellman_precompute_prime( nmod_discrete_log_pohlig_hellman_t L, mp_limb_t p); FLINT_DLL ulong nmod_discrete_log_pohlig_hellman_run( const nmod_discrete_log_pohlig_hellman_t L, mp_limb_t y); NMOD_VEC_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 flint2-2.8.4/nmod_vec/000077500000000000000000000000001414523752600145265ustar00rootroot00000000000000flint2-2.8.4/nmod_vec/add.c000066400000000000000000000014731414523752600154270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.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); } } flint2-2.8.4/nmod_vec/discrete_log_pohlig_hellman.c000066400000000000000000000220061414523752600223770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" #include "nmod_vec.h" #include "fmpz.h" #include 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; } flint2-2.8.4/nmod_vec/dot.c000066400000000000000000000012671414523752600154660ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.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; } flint2-2.8.4/nmod_vec/dot_bound_limbs.c000066400000000000000000000015051414523752600200360ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" 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); } flint2-2.8.4/nmod_vec/dot_ptr.c000066400000000000000000000013621414523752600163470ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" 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; } flint2-2.8.4/nmod_vec/dot_rev.c000066400000000000000000000021351414523752600163350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" 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; } flint2-2.8.4/nmod_vec/inlines.c000066400000000000000000000010601414523752600163300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define NMOD_VEC_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "nmod_vec.h" flint2-2.8.4/nmod_vec/max_bits.c000066400000000000000000000014231414523752600165000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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); } flint2-2.8.4/nmod_vec/neg.c000066400000000000000000000012021414523752600154360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.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); } flint2-2.8.4/nmod_vec/profile/000077500000000000000000000000001414523752600161665ustar00rootroot00000000000000flint2-2.8.4/nmod_vec/profile/p-add_sub_neg.c000066400000000000000000000045411414523752600210250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "flint.h" #include "ulong_extras.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, r = 0; 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; FLINT_TEST_INIT(state); n = n_randbits(state, bits); if (n == UWORD(0)) n++; nmod_init(&mod, n); mp_ptr vec1 = _nmod_vec_init(1000); mp_ptr vec2 = _nmod_vec_init(1000); mp_ptr 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; } flint2-2.8.4/nmod_vec/profile/p-reduce.c000066400000000000000000000027651414523752600200500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "flint.h" #include "ulong_extras.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; } flint2-2.8.4/nmod_vec/profile/p-scalar_mul.c000066400000000000000000000035031414523752600207120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "flint.h" #include "ulong_extras.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 min1, min2, max; info_t info; flint_bitcnt_t i; for (i = 2; i <= FLINT_BITS; i++) { info.bits = i; 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 128 %.1lf c/l, length 65536 %.1lf c/l\n", i, (min1/(double)FLINT_CLOCK_SCALE_FACTOR)/(1024*30), (min2/(double)FLINT_CLOCK_SCALE_FACTOR)/(65536*30) ); } return 0; } flint2-2.8.4/nmod_vec/randtest.c000066400000000000000000000017461414523752600165260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #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; } } } flint2-2.8.4/nmod_vec/reduce.c000066400000000000000000000012041414523752600161360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.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); } flint2-2.8.4/nmod_vec/scalar_addmul_nmod.c000066400000000000000000000016711414523752600205070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" void _nmod_vec_scalar_addmul_nmod(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { if (mod.norm >= FLINT_BITS/2) /* addmul will fit in a limb */ { mpn_addmul_1(res, vec, len, c); _nmod_vec_reduce(res, res, len, mod); } else /* products may take two limbs */ { slong i; for (i = 0; i < len; i++) NMOD_ADDMUL(res[i], vec[i], c, mod); /* hi already reduced mod n */ } } flint2-2.8.4/nmod_vec/scalar_mul_nmod.c000066400000000000000000000023001414523752600200240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" void _nmod_vec_scalar_mul_nmod(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { if (len < 1) return; if (len > 10 && mod.n < UWORD_HALF) { _nmod_vec_scalar_mul_nmod_shoup(res, vec, len, c, mod); return; } if (mod.norm >= FLINT_BITS / 2) /* products will fit in a limb */ { mpn_mul_1(res, vec, len, c); _nmod_vec_reduce(res, res, len, mod); } else /* products may take two limbs */ { slong i; for (i = 0; i < len; i++) { mp_limb_t hi, lo; umul_ppmm(hi, lo, vec[i], c); NMOD_RED2(res[i], hi, lo, mod); /* hi already reduced mod n */ } } } flint2-2.8.4/nmod_vec/scalar_mul_nmod_shoup.c000066400000000000000000000014741414523752600212550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" #include "nmod_vec.h" 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); } flint2-2.8.4/nmod_vec/sub.c000066400000000000000000000015021414523752600154610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.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); } } flint2-2.8.4/nmod_vec/test/000077500000000000000000000000001414523752600155055ustar00rootroot00000000000000flint2-2.8.4/nmod_vec/test/t-add_sub_neg.c000066400000000000000000000047321414523752600203520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add/sub/neg...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); flint_printf("len = %wd, n = %wd\n", len, n); abort(); } _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) { flint_printf("FAIL:\n"); flint_printf("len = %wd, n = %wd\n", len, n); abort(); } _nmod_vec_clear(vec); _nmod_vec_clear(vec2); _nmod_vec_clear(vec3); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_vec/test/t-discrete_log_pohlig_hellman.c000066400000000000000000000034631414523752600236250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "nmod_vec.h" int main(void) { slong i, j, k; FLINT_TEST_INIT(state); flint_printf("discrete_log_ph...."); fflush(stdout); flint_randinit(state); 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)) { printf("FAIL\n"); flint_printf("modulo %wu log base %wu of %wu" " should be %wu\n", p, alpha, y, x); flint_abort(); } } } nmod_discrete_log_pohlig_hellman_clear(L); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_vec/test/t-dot.c000066400000000000000000000035251414523752600167050ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("dot...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("m = %wu\n", m); flint_printf("len = %wd\n", len); flint_printf("limbs1 = %d\n", limbs1); abort(); } mpz_clear(s); mpz_clear(t); _nmod_vec_clear(x); _nmod_vec_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_vec/test/t-dot_bound_limbs.c000066400000000000000000000030631414523752600212570ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("dot_bound_limbs...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("m = %wu\n", m); flint_printf("len = %wd\n", len); flint_printf("limbs1 = %d\n", limbs1); flint_printf("limbs2 = %d\n", limbs2); gmp_printf("bound: %Zd\n", t); abort(); } mpz_clear(t); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_vec/test/t-dot_ptr.c000066400000000000000000000035101414523752600175640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("dot_ptr...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("m = %wu\n", m); flint_printf("len = %wd\n", len); flint_printf("limbs1 = %d\n", limbs1); abort(); } _nmod_vec_clear(x); _nmod_vec_clear(y); flint_free(z); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_vec/test/t-nmod.c000066400000000000000000000121401414523752600170450ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("nmod...."); fflush(stdout); /* 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) { flint_printf("FAIL (add):\n"); flint_printf("m = %wu\n", m); abort(); } 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) { flint_printf("FAIL (sub):\n"); flint_printf("m = %wu\n", m); abort(); } 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) { flint_printf("FAIL (mul):\n"); flint_printf("m = %wu\n", m); abort(); } 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) { flint_printf("FAIL (div):\n"); flint_printf("m = %wu\n", m); abort(); } 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) { flint_printf("FAIL (div):\n"); flint_printf("m = %wu\n", m); abort(); } 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) { flint_printf("FAIL (pow):\n"); flint_printf("m = %wu\n", m); abort(); } mpz_clear(y); mpz_clear(z); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_vec/test/t-nmod_pow_fmpz.c000066400000000000000000000042431414523752600207730ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("nmod_pow_fmpz...."); fflush(stdout); /* 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) { printf("FAIL\n"); flint_printf("check nmod_pow_fmpz matches nmod_pow_ui\ni = %wd\n", i); flint_abort(); } 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)) { printf("FAIL\n"); flint_printf("check b^e1*b^e2 = b^(e1+e2)\ni = %wd\n", i); flint_abort(); } fmpz_clear(exp3); fmpz_clear(exp2); fmpz_clear(exp1); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_vec/test/t-reduce.c000066400000000000000000000030161414523752600173610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("reduce...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("len = %wd, n = %wd\n", len, n); abort(); } _nmod_vec_clear(vec); _nmod_vec_clear(vec2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_vec/test/t-scalar_addmul_nmod.c000066400000000000000000000033461414523752600217300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_addmul_nmod...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); flint_printf("len = %wd, n = %wd\n", len, n); abort(); } _nmod_vec_clear(vec); _nmod_vec_clear(vec2); _nmod_vec_clear(vec3); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_vec/test/t-scalar_mul_nmod.c000066400000000000000000000036301414523752600212530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_nmod...."); fflush(stdout); { 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) { flint_printf("FAIL:\n"); flint_printf("len = %wd, n = %wd\n", len, n); abort(); } _nmod_vec_clear(vec); _nmod_vec_clear(vec2); _nmod_vec_clear(vec3); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_vec/test/t-scalar_mul_nmod_shoup.c000066400000000000000000000035601414523752600224730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "nmod_vec.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("scalar_mul_nmod_shoup...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); flint_printf("len = %wd, n = %wd\n", len, n); abort(); } _nmod_vec_clear(vec); _nmod_vec_clear(vec2); _nmod_vec_clear(vec3); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/nmod_vecxx.h000066400000000000000000000266621414523752600152730ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ // TODO reference types // TODO addmul // TODO document nmod_vecxx #ifndef NMOD_VECXX_H #define NMOD_VECXX_H #include #include "nmod_vec.h" // TODO reduce dependencies? #include "fmpzxx.h" #include "fmpqxx.h" #include "flintxx/expression.h" #include "flintxx/evaluation_tools.h" #include "flintxx/flint_classes.h" #include "flintxx/stdmath.h" #include "flintxx/vector.h" namespace flint { ////////////////////////////////////////////////////////////////////////////// // NMOD CLASS AND RULES ////////////////////////////////////////////////////////////////////////////// class nmodxx_ctx { private: nmod_t nmod; public: const nmod_t& _nmod() const {return nmod;} explicit nmodxx_ctx(mp_limb_t n) {nmod_init(&nmod, n);} // no destruction necessary bool operator==(const nmodxx_ctx& o) const {return nmod.n == o.nmod.n;} mp_limb_t n() const {return nmod.n;} }; class nmodxx_ctx_srcref { private: const nmod_t& nmod; nmodxx_ctx_srcref(const nmod_t& nm) : nmod(nm) {} public: const nmod_t& _nmod() const {return nmod;} nmodxx_ctx_srcref(const nmodxx_ctx& c) : nmod(c._nmod()) {} static nmodxx_ctx_srcref make(const nmod_t& nm) {return nmodxx_ctx_srcref(nm);} bool operator==(const nmodxx_ctx_srcref& o) const {return nmod.n == o.nmod.n;} mp_limb_t n() const {return nmod.n;} }; namespace detail { struct nmodxx_fake_c_type { }; } // detail template class nmodxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; FLINTXX_DEFINE_BASICS(nmodxx_expression) FLINTXX_DEFINE_CTORS(nmodxx_expression) FLINTXX_DEFINE_C_REF(nmodxx_expression, detail::nmodxx_fake_c_type, _limb) // static functions for nmodxx static nmodxx_expression make_nored(mp_limb_t n, nmodxx_ctx_srcref c) { return nmodxx_expression(Data::make_nored(n, c)); } static nmodxx_expression red(mp_limb_t n, nmodxx_ctx_srcref c) { nmodxx_expression res = make_nored(n, c); res.reduce(); return res; } template static typename mp::enable_if< traits::is_fmpzxx, nmodxx_expression>::type red( const Fmpz& n, nmodxx_ctx_srcref c) { return make_nored((n % c.n()).template to(), c); } template static typename mp::enable_if< traits::is_fmpqxx, nmodxx_expression>::type red( const Fmpq& n, nmodxx_ctx_srcref c) { return make_nored((n % fmpzxx(c.n())).template to(), c); } // TODO more // only makes sense on immediates nmodxx_ctx_srcref _ctx() const {return this->_data().ctx;} const nmod_t& _nmod() const {return this->_data().ctx._nmod();} void reduce() {NMOD_RED(_limb(), _limb(), _nmod());} void set_nored(mp_limb_t n) {this->_data().inner = n;} nmodxx_ctx_srcref estimate_ctx() const; evaluated_t create_temporary() const { return evaluated_t(estimate_ctx()); } FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_UNOP(inv) }; namespace detail { struct nmodxx_data; } // detail typedef nmodxx_expression nmodxx; typedef nmodxx_expression > nmodxx_ref; typedef nmodxx_expression > nmodxx_srcref; namespace flint_classes { template struct ref_data { typedef void IS_REF_OR_CREF; typedef Nmod wrapped_t; typedef mp_limb_t& data_ref_t; typedef const mp_limb_t& data_srcref_t; mp_limb_t& inner; nmodxx_ctx_srcref ctx; ref_data(Nmod& o) : inner(o._data().inner), ctx(o._data().ctx) {} static ref_data make(mp_limb_t& f, nmodxx_ctx_srcref ctx) { return ref_data(f, ctx); } private: ref_data(mp_limb_t& fp, nmodxx_ctx_srcref c) : inner(fp), ctx(c) {} }; template struct srcref_data { typedef void IS_REF_OR_CREF; typedef Nmod wrapped_t; typedef const mp_limb_t& data_ref_t; typedef const mp_limb_t& data_srcref_t; const mp_limb_t& inner; nmodxx_ctx_srcref ctx; srcref_data(const Nmod& o) : inner(o._data().inner), ctx(o._data().ctx) {} srcref_data(Ref o) : inner(o._data().inner) {} static srcref_data make(const mp_limb_t& f, nmodxx_ctx_srcref ctx) { return srcref_data(f, ctx); } private: srcref_data(const mp_limb_t& fp, nmodxx_ctx_srcref c) : inner(fp), ctx(c) {} }; } // flint_classes namespace detail { struct nmodxx_data { nmodxx_ctx_srcref ctx; mp_limb_t inner; typedef mp_limb_t& data_ref_t; typedef const mp_limb_t& data_srcref_t; nmodxx_data(nmodxx_ctx_srcref c) : ctx(c), inner(0) {} private: nmodxx_data(mp_limb_t n, nmodxx_ctx_srcref c) : ctx(c), inner(n) {} public: static nmodxx_data make_nored(mp_limb_t n, nmodxx_ctx_srcref c) { return nmodxx_data(n, c); } nmodxx_data(const nmodxx_srcref& r) : ctx(r.estimate_ctx()), inner(r._limb()) {} }; } // detail // Temporary merging isn't really any use here. On the other hand, it does // not seem to hurt. Let's leave this for now. -- Tom Bachmann (15/10/2013) #if 0 namespace traits { template<> struct use_temporary_merging : mp::false_ { }; } // traits #endif namespace traits { template struct has_nmodxx_ctx : mp::false_ { }; template<> struct has_nmodxx_ctx : mp::true_ { }; template<> struct has_nmodxx_ctx : mp::true_ { }; template<> struct has_nmodxx_ctx : mp::true_ { }; } // traits namespace detail { struct has_nmodxx_ctx_predicate { template struct type : traits::has_nmodxx_ctx { }; }; // XXX this is needed for vectors ... template struct get_nmodxx_ctx { static nmodxx_ctx_srcref get(const T& t) {return t._ctx();} }; template nmodxx_ctx_srcref get_nmodxx_ctx_func(const T& t) { return get_nmodxx_ctx::get(t); } } // detail namespace tools { template nmodxx_ctx_srcref find_nmodxx_ctx(const Expr& e) { return detail::get_nmodxx_ctx_func( tools::find_subexpr(e)); } } // tools template inline nmodxx_ctx_srcref nmodxx_expression::estimate_ctx() const { return tools::find_nmodxx_ctx(*this); } namespace traits { template struct is_nmodxx : mp::or_< traits::is_T_expr, flint_classes::is_source > { }; } // traits namespace rules { #define NMODXX_COND_S FLINTXX_COND_S(nmodxx) #define NMODXX_COND_T FLINTXX_COND_T(nmodxx) #define NMODXX_DEFINE_INSTANTIATE_TEMPORARIES(Classname) \ template \ struct use_default_temporary_instantiation : mp::false_ { }; \ template \ struct instantiate_temporaries \ { \ static Classname get(const Expr& e) \ { \ return Classname(tools::find_nmodxx_ctx(e)); \ } \ }; // This is in order to make temporary allocation work even if there is no // immediate subexpression - c/f test_temporaries NMODXX_DEFINE_INSTANTIATE_TEMPORARIES(nmodxx) FLINTXX_DEFINE_EQUALS(nmodxx, e1._limb() == e2._limb()) FLINT_DEFINE_GET_COND(conversion, mp_limb_t, NMODXX_COND_S, from._limb()) template struct to_string >::type> { static std::string get(const Nmod& i, int base /* ignored */) { std::ostringstream oss; oss << i._limb() << " mod " << i._nmod().n; return oss.str(); } }; FLINT_DEFINE_DOIT_COND2(assignment, NMODXX_COND_T, NMODXX_COND_S, to._limb() = from._limb()) FLINT_DEFINE_CBINARY_EXPR_COND2(plus, nmodxx, NMODXX_COND_S, NMODXX_COND_S, to.set_nored(nmod_add(e1._limb(), e2._limb(), to._nmod()))) FLINT_DEFINE_CBINARY_EXPR_COND2(times, nmodxx, NMODXX_COND_S, NMODXX_COND_S, to.set_nored(nmod_mul(e1._limb(), e2._limb(), to._nmod()))) FLINT_DEFINE_BINARY_EXPR_COND2(minus, nmodxx, NMODXX_COND_S, NMODXX_COND_S, to.set_nored(nmod_sub(e1._limb(), e2._limb(), to._nmod()))) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, nmodxx, NMODXX_COND_S, NMODXX_COND_S, to.set_nored(nmod_div(e1._limb(), e2._limb(), to._nmod()))) FLINT_DEFINE_UNARY_EXPR_COND(negate, nmodxx, NMODXX_COND_S, to.set_nored(nmod_neg(from._limb(), to._nmod()))) FLINT_DEFINE_UNARY_EXPR_COND(inv_op, nmodxx, NMODXX_COND_S, to.set_nored(nmod_inv(from._limb(), to._nmod()))) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, nmodxx, NMODXX_COND_S, traits::is_unsigned_integer, to.set_nored(nmod_pow_ui(e1._limb(), e2, to._nmod()))) } ////////////////////////////////////////////////////////////////////////////// // NMOD_VEC CLASS AND RULES ////////////////////////////////////////////////////////////////////////////// namespace detail { struct nmod_vector_data { slong size; mp_limb_t* array; nmodxx_ctx_srcref ctx; nmod_vector_data(slong n, nmodxx_ctx_srcref c) : size(n), array(_nmod_vec_init(n)), ctx(c) {} ~nmod_vector_data() {_nmod_vec_clear(array);} nmod_vector_data(const nmod_vector_data& o) : size(o.size), array(_nmod_vec_init(o.size)), ctx(o.ctx) { _nmod_vec_set(array, o.array, size); } nmodxx_ref at(slong i) {return nmodxx_ref::make(array[i], ctx);} nmodxx_srcref at(slong i) const {return nmodxx_srcref::make(array[i], ctx);} }; struct nmod_vector_traits : wrapped_vector_traits { template static typename Expr::evaluated_t create_temporary(const Expr& e) { return typename Expr::evaluated_t(e.size(), tools::find_nmodxx_ctx(e)); } }; } // detail // TODO would it make more sense to have this have its own class? typedef vector_expression< detail::nmod_vector_traits, operations::immediate, detail::nmod_vector_data> nmod_vecxx; // TODO references namespace traits { template<> struct has_nmodxx_ctx : mp::true_ { }; } // traits namespace detail { template<> struct get_nmodxx_ctx { static nmodxx_ctx_srcref get(const nmod_vecxx& v) { return v._data().ctx; } }; } // detail template<> struct enable_vector_rules : mp::false_ { }; namespace rules { // TODO hack to make code look like references are implemented template struct NMOD_VECXX_COND_S : mp::equal_types { }; #define NMOD_VECXX_COND_T NMOD_VECXX_COND_S // TODO references FLINT_DEFINE_GET(equals, bool, nmod_vecxx, e1.size() == e2.size() && _nmod_vec_equal(e1._data().array, e2._data().array, e1.size())) FLINT_DEFINE_BINARY_EXPR_COND2(plus, nmod_vecxx, NMOD_VECXX_COND_S, NMOD_VECXX_COND_S, _nmod_vec_add(to._data().array, e1._data().array, e2._data().array, to.size(), to._data().ctx._nmod())) // TODO more } // rules } // flint #endif flint2-2.8.4/padic.h000066400000000000000000000244561414523752600142000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef PADIC_H #define PADIC_H #ifdef PADIC_INLINES_C #define PADIC_INLINE FLINT_DLL #else #define PADIC_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_vec.h" #include "ulong_extras.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) typedef struct { fmpz u; slong v; slong N; } padic_struct; typedef padic_struct padic_t[1]; #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; } 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]; /* Context *******************************************************************/ FLINT_DLL void padic_ctx_init(padic_ctx_t ctx, const fmpz_t p, slong min, slong max, enum padic_print_mode mode); FLINT_DLL 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_printf("Exception (_padic_ctx_pow_ui). Power too large.\n"); flint_printf("e = %wu\n", e); flint_printf("l = %wd\n", l); flint_abort(); } 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_printf("Exception (padic_ctx_pow_ui). Power too large.\n"); flint_printf("e = %wu\n", e); flint_printf("l = %wd\n", l); flint_abort(); } fmpz_pow_ui(rop, ctx->p, e); } } /* Memory management *********************************************************/ FLINT_DLL void padic_init(padic_t rop); FLINT_DLL void padic_init2(padic_t rop, slong N); FLINT_DLL 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; } } FLINT_DLL void _padic_reduce(padic_t rop, const padic_ctx_t ctx); FLINT_DLL void padic_reduce(padic_t rop, const padic_ctx_t ctx); /* Randomisation *************************************************************/ FLINT_DLL void padic_randtest(padic_t rop, flint_rand_t state, const padic_ctx_t ctx); FLINT_DLL void padic_randtest_not_zero(padic_t rop, flint_rand_t state, const padic_ctx_t ctx); FLINT_DLL void padic_randtest_int(padic_t rop, flint_rand_t state, const padic_ctx_t ctx); /* Assignments and conversions ***********************************************/ FLINT_DLL void padic_set(padic_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL void padic_set_si(padic_t rop, slong op, const padic_ctx_t ctx); FLINT_DLL void padic_set_ui(padic_t rop, ulong op, const padic_ctx_t ctx); FLINT_DLL void padic_set_fmpz(padic_t rop, const fmpz_t op, const padic_ctx_t ctx); FLINT_DLL void padic_set_fmpq(padic_t rop, const fmpq_t op, const padic_ctx_t ctx); FLINT_DLL void padic_set_mpz(padic_t rop, const mpz_t op, const padic_ctx_t ctx); FLINT_DLL void padic_set_mpq(padic_t rop, const mpq_t op, const padic_ctx_t ctx); FLINT_DLL void padic_get_fmpz(fmpz_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL void padic_get_fmpq(fmpq_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL void padic_get_mpz(mpz_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL 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) { slong t; fmpz_swap(padic_unit(op1), padic_unit(op2)); t = padic_val(op1); padic_val(op1) = padic_val(op2); padic_val(op2) = t; t = padic_prec(op1); padic_prec(op1) = padic_prec(op2); padic_prec(op2) = t; } 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 *****************************************************/ FLINT_DLL slong * _padic_lifts_exps(slong *n, slong N); FLINT_DLL void _padic_lifts_pows(fmpz *pow, const slong *a, slong n, const fmpz_t p); FLINT_DLL void padic_add(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx); FLINT_DLL void padic_sub(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx); FLINT_DLL void padic_neg(padic_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL void padic_mul(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx); FLINT_DLL void padic_shift(padic_t rop, const padic_t op, slong v, const padic_ctx_t ctx); FLINT_DLL void padic_div(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx); FLINT_DLL void _padic_inv_precompute(padic_inv_t S, const fmpz_t p, slong N); FLINT_DLL void _padic_inv_clear(padic_inv_t S); FLINT_DLL void _padic_inv_precomp(fmpz_t rop, const fmpz_t op, const padic_inv_t S); FLINT_DLL void _padic_inv(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N); FLINT_DLL void padic_inv(padic_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL int padic_sqrt(padic_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL void padic_pow_si(padic_t rop, const padic_t op, slong e, const padic_ctx_t ctx); /* Exponential ***************************************************************/ FLINT_DLL slong _padic_exp_bound(slong v, slong N, const fmpz_t p); FLINT_DLL void _padic_exp(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N); FLINT_DLL void _padic_exp_rectangular(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N); FLINT_DLL void _padic_exp_balanced(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N); FLINT_DLL int padic_exp(padic_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL int padic_exp_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL int padic_exp_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx); /* Logarithm *****************************************************************/ FLINT_DLL slong _padic_log_bound(slong v, slong N, const fmpz_t p); FLINT_DLL void _padic_log(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N); FLINT_DLL void _padic_log_rectangular(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N); FLINT_DLL void _padic_log_satoh(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N); FLINT_DLL void _padic_log_balanced(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N); FLINT_DLL int padic_log(padic_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL int padic_log_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL int padic_log_satoh(padic_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL int padic_log_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx); /* Special functions *********************************************************/ FLINT_DLL void _padic_teichmuller(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N); FLINT_DLL void padic_teichmuller(padic_t rop, const padic_t op, const padic_ctx_t ctx); FLINT_DLL ulong padic_val_fac_ui_2(ulong N); FLINT_DLL ulong padic_val_fac_ui(ulong N, const fmpz_t p); FLINT_DLL void padic_val_fac(fmpz_t rop, const fmpz_t op, const fmpz_t p); /* Input and output **********************************************************/ FLINT_DLL char * _padic_get_str(char * str, const padic_t op, const fmpz_t p, enum padic_print_mode mode); FLINT_DLL char * padic_get_str(char * str, const padic_t op, const padic_ctx_t ctx); FLINT_DLL int _padic_fprint(FILE * file, const fmpz_t u, slong v, const padic_ctx_t ctx); FLINT_DLL int padic_fprint(FILE * file, const padic_t op, const padic_ctx_t ctx); PADIC_INLINE int _padic_print(const fmpz_t u, slong v, const padic_ctx_t ctx) { return _padic_fprint(stdout, u, v, ctx); } PADIC_INLINE int padic_print(const padic_t op, const padic_ctx_t ctx) { return padic_fprint(stdout, op, ctx); } PADIC_INLINE void padic_debug(const padic_t op) { flint_printf("("); fmpz_print(padic_unit(op)); flint_printf(" %wd %wd)", padic_val(op), padic_prec(op)); } #ifdef __cplusplus } #endif #endif flint2-2.8.4/padic/000077500000000000000000000000001414523752600140145ustar00rootroot00000000000000flint2-2.8.4/padic/add.c000066400000000000000000000054201414523752600147110ustar00rootroot00000000000000/* 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 2.1 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); } } } flint2-2.8.4/padic/clear.c000066400000000000000000000007401414523752600152470ustar00rootroot00000000000000/* 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 2.1 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)); } flint2-2.8.4/padic/ctx_clear.c000066400000000000000000000010601414523752600161210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/padic/ctx_init.c000066400000000000000000000022651414523752600160060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (padic_ctx_init). Require 0 <= min <= max."); flint_abort(); } 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; } flint2-2.8.4/padic/div.c000066400000000000000000000020701414523752600147410ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (padic_div). op2 is zero.\n"); flint_abort(); } 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); } } flint2-2.8.4/padic/exp.c000066400000000000000000000034211414523752600147540ustar00rootroot00000000000000/* 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 2.1 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; } } flint2-2.8.4/padic/exp_balanced.c000066400000000000000000000122131414523752600165640ustar00rootroot00000000000000/* 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 2.1 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; } } flint2-2.8.4/padic/exp_rectangular.c000066400000000000000000000103101414523752600173360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/padic/fprint.c000066400000000000000000000066651414523752600154770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "padic.h" 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_printf("Exception (_padic_fprint). Unknown print mode.\n"); flint_abort(); } 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); } flint2-2.8.4/padic/get_fmpq.c000066400000000000000000000023551414523752600157670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/padic/get_fmpz.c000066400000000000000000000017361414523752600160020ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (padic_get_fmpz). Negative valuation.\n"); flint_abort(); } 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); } } flint2-2.8.4/padic/get_mpq.c000066400000000000000000000011201414523752600156060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/padic/get_mpz.c000066400000000000000000000011201414523752600156170ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/padic/get_str.c000066400000000000000000000120011414523752600156210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "padic.h" #include "long_extras.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_printf("Exception (padic_get_str). Memory allocation failed.\n"); flint_abort(); } } 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_printf("Exception (padic_get_str). Memory allocation failed.\n"); flint_abort(); } } 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); } flint2-2.8.4/padic/init.c000066400000000000000000000012371414523752600151260ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/padic/inlines.c000066400000000000000000000012011414523752600156130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define PADIC_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "fmpz_poly.h" #include "padic.h" flint2-2.8.4/padic/inv.c000066400000000000000000000044511414523752600147600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (padic_inv). Zero is not invertible.\n"); flint_abort(); } /* 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); } } flint2-2.8.4/padic/lifts.c000066400000000000000000000026721414523752600153100ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/padic/log.c000066400000000000000000000073471414523752600147540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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) << (FLINT_BITS - 2))) { flint_printf("Exception (_padic_log_bound). N = %wd is too large.\n", N); flint_abort(); } 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; } } flint2-2.8.4/padic/log_balanced.c000066400000000000000000000104161414523752600165540ustar00rootroot00000000000000/* 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 2.1 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; } } flint2-2.8.4/padic/log_rectangular.c000066400000000000000000000112051414523752600173270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "padic.h" #include "ulong_extras.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; } } flint2-2.8.4/padic/log_satoh.c000066400000000000000000000045461414523752600161500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } } flint2-2.8.4/padic/mul.c000066400000000000000000000015261414523752600147610ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/padic/neg.c000066400000000000000000000016111414523752600147300ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/padic/pow_si.c000066400000000000000000000024031414523752600154570ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/padic/profile/000077500000000000000000000000001414523752600154545ustar00rootroot00000000000000flint2-2.8.4/padic/profile/p-exp_balanced_2.c000066400000000000000000000047431414523752600207130ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t d, z; 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"); } flint2-2.8.4/padic/profile/p-exp_balanced_p.c000066400000000000000000000047361414523752600210130ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t d, z; 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"); } flint2-2.8.4/padic/profile/p-exp_rectangular.c000066400000000000000000000047651414523752600212540ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t d, z; 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"); } flint2-2.8.4/padic/profile/p-inv.c000066400000000000000000000045761414523752600166650ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); slong n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t a, z; 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"); } flint2-2.8.4/padic/profile/p-log_balanced.c000066400000000000000000000056671414523752600204650ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t e, z; 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"); 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"); } flint2-2.8.4/padic/profile/p-log_rectangular.c000066400000000000000000000057221414523752600212330ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t e, z; 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"); 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"); } flint2-2.8.4/padic/profile/p-mul.c000066400000000000000000000051001414523752600166460ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t a, b, z; 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"); } flint2-2.8.4/padic/profile/p-sqrt.c000066400000000000000000000050551414523752600170530ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t a, b, z; 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"); } flint2-2.8.4/padic/profile/p-teichmuller.c000066400000000000000000000043121414523752600203720ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); long n = N[l], r; clock_t c0, c1; long double cputime; fmpz_t p; padic_ctx_t ctx; padic_t c, z; 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"); } flint2-2.8.4/padic/randtest.c000066400000000000000000000037211414523752600160070ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/padic/reduce.c000066400000000000000000000017631414523752600154360ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/padic/set.c000066400000000000000000000011271414523752600147540ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/padic/set_fmpq.c000066400000000000000000000022071414523752600157770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/padic/set_fmpz.c000066400000000000000000000012431414523752600160070ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/padic/set_mpq.c000066400000000000000000000011201414523752600156220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/padic/set_mpz.c000066400000000000000000000011261414523752600156410ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/padic/set_si.c000066400000000000000000000010731414523752600154470ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/padic/set_ui.c000066400000000000000000000020541414523752600154510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/padic/shift.c000066400000000000000000000013601414523752600152750ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/padic/sqrt.c000066400000000000000000000130151414523752600151510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } flint2-2.8.4/padic/sub.c000066400000000000000000000054521414523752600147570ustar00rootroot00000000000000/* 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 2.1 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); } } } flint2-2.8.4/padic/teichmuller.c000066400000000000000000000050011414523752600164710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (padic_teichmuller). op is not a p-adic integer.\n"); flint_abort(); } 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; } } flint2-2.8.4/padic/test/000077500000000000000000000000001414523752600147735ustar00rootroot00000000000000flint2-2.8.4/padic/test/t-add.c000066400000000000000000000172071414523752600161370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-div.c000066400000000000000000000122021414523752600161570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div... "); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-exp.c000066400000000000000000000157071414523752600162060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("exp... "); fflush(stdout); /** 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); 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"); 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); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-exp_balanced.c000066400000000000000000000160521414523752600200110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("exp_balanced... "); fflush(stdout); /** 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); 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"); 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); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-exp_rectangular.c000066400000000000000000000161131414523752600205650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("exp_rectangular... "); fflush(stdout); /** 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); 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"); 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); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-get_set_fmpz.c000066400000000000000000000034071414523752600200720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get_set_fmpz... "); fflush(stdout); /* 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"); abort(); } padic_clear(a); padic_clear(b); fmpz_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-get_set_mpq.c000066400000000000000000000033711414523752600177130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get_set_mpq... "); fflush(stdout); /* 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); abort(); } padic_clear(a); padic_clear(b); mpq_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-get_set_mpz.c000066400000000000000000000034511414523752600177230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get_set_mpz... "); fflush(stdout); /* 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); abort(); } padic_clear(a); padic_clear(b); mpz_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-get_str.c000066400000000000000000000033601414523752600170510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("get_str... "); fflush(stdout); 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"); abort(); } flint_free(s); flint_free(t); padic_clear(x); fmpq_clear(y); padic_ctx_clear(ctx); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-inv.c000066400000000000000000000131511414523752600161750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("inv... "); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } } padic_clear(a); padic_clear(b); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-log.c000066400000000000000000000231121414523752600161600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "padic.h" /* 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) { slong N; N = n_randint(state, PADIC_TEST_PREC_MAX) + 1; return N; } int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("log... "); fflush(stdout); /** 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"); 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"); 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); 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"); 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); 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); abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-log_balanced.c000066400000000000000000000233721414523752600200010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "padic.h" /* 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) { slong N; N = n_randint(state, PADIC_TEST_PREC_MAX) + 1; return N; } int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("log_balanced... "); fflush(stdout); /** 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"); 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"); 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); 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"); 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); 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); abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-log_rectangular.c000066400000000000000000000233461414523752600205600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "padic.h" /* 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) { slong N; N = n_randint(state, PADIC_TEST_PREC_MAX) + 1; return N; } int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("log_rectangular... "); fflush(stdout); /** 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"); 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"); 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); 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"); 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); 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); abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-log_satoh.c000066400000000000000000000231261414523752600173630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "padic.h" /* 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) { slong N; N = n_randint(state, PADIC_TEST_PREC_MAX) + 1; return N; } int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("log_satoh... "); fflush(stdout); /** 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"); 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"); 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); 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"); 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); 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); abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-mul.c000066400000000000000000000204171414523752600162010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-neg.c000066400000000000000000000070741414523752600161610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg... "); fflush(stdout); /* 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"); 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"); 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"); abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-pow_si.c000066400000000000000000000152461414523752600167100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "padic.h" #include "long_extras.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow_si... "); fflush(stdout); /* 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); 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); 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); 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); abort(); } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); padic_clear(t); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-randtest.c000066400000000000000000000056761414523752600172420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("randtest... "); fflush(stdout); /* 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); 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); abort(); } padic_clear(a); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-shift.c000066400000000000000000000071401414523752600165170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("shift... "); fflush(stdout); /* 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"); 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"); abort(); } } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-sqrt.c000066400000000000000000000313531414523752600163760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "padic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrt... "); fflush(stdout); /* 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"); 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); 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); 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); 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); 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"); 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); 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); 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); 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); abort(); } } padic_clear(a); padic_clear(b); padic_clear(c); padic_clear(d); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-sub.c000066400000000000000000000173141414523752600161770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); 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"); abort(); } padic_clear(a); padic_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-teichmuller.c000066400000000000000000000056231414523752600177230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("teichmuller... "); fflush(stdout); /* 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"); 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, FLINT_BITS - 2), 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"); abort(); } padic_clear(a); padic_clear(b); padic_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic/test/t-val_fac.c000066400000000000000000000107471414523752600170040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "ulong_extras.h" #include "padic.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("padic_val_fac... "); fflush(stdout); /* 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"); 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"); 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"); 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"); abort(); } fmpz_clear(a); fmpz_clear(p); fmpz_clear(t); fmpz_clear(z); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/padic/val_fac.c000066400000000000000000000024441414523752600155570ustar00rootroot00000000000000/* 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 2.1 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_printf("Exception (padic_val_fac). op is negative.\n"); flint_abort(); } 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); } flint2-2.8.4/padic_mat.h000066400000000000000000000204551414523752600150340ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define PADIC_MAT_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpz_mat.h" #include "fmpq_mat.h" #include "padic.h" #ifdef __cplusplus extern "C" { #endif typedef struct { fmpz_mat_struct mat; slong val; slong N; } padic_mat_struct; typedef padic_mat_struct padic_mat_t[1]; /* 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 ********************************************************/ FLINT_DLL void padic_mat_init(padic_mat_t A, slong r, slong c); FLINT_DLL void padic_mat_init2(padic_mat_t A, slong r, slong c, slong prec); FLINT_DLL void padic_mat_clear(padic_mat_t A); FLINT_DLL void _padic_mat_canonicalise(padic_mat_t A, const padic_ctx_t ctx); FLINT_DLL void _padic_mat_reduce(padic_mat_t A, const padic_ctx_t ctx); FLINT_DLL 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 fmpz_mat_is_empty(padic_mat(A)); } PADIC_MAT_INLINE int padic_mat_is_square(const padic_mat_t A) { return fmpz_mat_is_square(padic_mat(A)); } PADIC_MAT_INLINE 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; } } PADIC_MAT_INLINE 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; } } /* Basic assignment **********************************************************/ FLINT_DLL void padic_mat_set(padic_mat_t B, const padic_mat_t A, const padic_ctx_t ctx); FLINT_DLL 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++) fmpz_swap(padic_mat_entry(mat2, i, j), padic_mat_entry(mat1, i, j)); } FLINT_DLL void padic_mat_zero(padic_mat_t A); FLINT_DLL void padic_mat_one(padic_mat_t A); /* Conversions ***************************************************************/ FLINT_DLL void padic_mat_set_fmpq_mat(padic_mat_t B, const fmpq_mat_t A, const padic_ctx_t ctx); FLINT_DLL void padic_mat_get_fmpq_mat(fmpq_mat_t B, const padic_mat_t A, const padic_ctx_t ctx); /* Entries *******************************************************************/ FLINT_DLL void padic_mat_get_entry_padic(padic_t rop, const padic_mat_t op, slong i, slong j, const padic_ctx_t ctx); FLINT_DLL void padic_mat_set_entry_padic(padic_mat_t rop, slong i, slong j, const padic_t op, const padic_ctx_t ctx); /* Comparison ****************************************************************/ FLINT_DLL int padic_mat_equal(const padic_mat_t A, const padic_mat_t B); FLINT_DLL int padic_mat_is_zero(const padic_mat_t A); /* Input and output *********************************************************/ FLINT_DLL int padic_mat_fprint(FILE * file, const padic_mat_t A, const padic_ctx_t ctx); FLINT_DLL int padic_mat_fprint_pretty(FILE * file, const padic_mat_t A, const padic_ctx_t ctx); PADIC_MAT_INLINE int padic_mat_print(const padic_mat_t A, const padic_ctx_t ctx) { return padic_mat_fprint(stdout, A, ctx); } PADIC_MAT_INLINE int padic_mat_print_pretty(const padic_mat_t A, const padic_ctx_t ctx) { return padic_mat_fprint_pretty(stdout, A, ctx); } /* Random matrix generation *************************************************/ FLINT_DLL void padic_mat_randtest(padic_mat_t mat, flint_rand_t state, const padic_ctx_t ctx); /* Transpose *****************************************************************/ FLINT_DLL void padic_mat_transpose(padic_mat_t B, const padic_mat_t A); /* Addition and subtraction **************************************************/ FLINT_DLL void _padic_mat_add(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx); FLINT_DLL void padic_mat_add(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx); FLINT_DLL void _padic_mat_sub(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx); FLINT_DLL void padic_mat_sub(padic_mat_t C, const padic_mat_t A, const padic_mat_t B, const padic_ctx_t ctx); FLINT_DLL void _padic_mat_neg(padic_mat_t B, const padic_mat_t A); FLINT_DLL void padic_mat_neg(padic_mat_t B, const padic_mat_t A, const padic_ctx_t ctx); /* Scalar operations *********************************************************/ FLINT_DLL void _padic_mat_scalar_mul_padic(padic_mat_t B, const padic_mat_t A, const padic_t c, const padic_ctx_t ctx); FLINT_DLL void padic_mat_scalar_mul_padic(padic_mat_t B, const padic_mat_t A, const padic_t c, const padic_ctx_t ctx); FLINT_DLL void _padic_mat_scalar_mul_fmpz(padic_mat_t B, const padic_mat_t A, const fmpz_t c, const padic_ctx_t ctx); FLINT_DLL void padic_mat_scalar_mul_fmpz(padic_mat_t B, const padic_mat_t A, const fmpz_t c, const padic_ctx_t ctx); FLINT_DLL 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 ************************************************************/ FLINT_DLL 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 flint2-2.8.4/padic_mat/000077500000000000000000000000001414523752600146555ustar00rootroot00000000000000flint2-2.8.4/padic_mat/add.c000066400000000000000000000053671414523752600155640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_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); } } flint2-2.8.4/padic_mat/canonicalise.c000066400000000000000000000047741414523752600174650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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)); } } flint2-2.8.4/padic_mat/clear.c000066400000000000000000000010131414523752600161020ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/padic_mat/equal.c000066400000000000000000000011731414523752600161320ustar00rootroot00000000000000/* 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 2.1 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; } } flint2-2.8.4/padic_mat/fprint.c000066400000000000000000000065261414523752600163340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" 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_printf("ERROR (_padic_mat_fprint). Mode PADIC_SERIES not implemented yet.\n"); flint_abort(); } 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_printf("ERROR (_padic_mat_fprint). Unknown print mode.\n"); flint_abort(); } return 1; } flint2-2.8.4/padic_mat/fprint_pretty.c000066400000000000000000000021641414523752600177350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" 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; } flint2-2.8.4/padic_mat/get_entry_padic.c000066400000000000000000000013441414523752600201630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.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); } flint2-2.8.4/padic_mat/get_fmpq_mat.c000066400000000000000000000027501414523752600174700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } } flint2-2.8.4/padic_mat/init.c000066400000000000000000000013231414523752600157630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.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; } flint2-2.8.4/padic_mat/inlines.c000066400000000000000000000010621414523752600164610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define PADIC_MAT_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "padic_mat.h" flint2-2.8.4/padic_mat/is_zero.c000066400000000000000000000011271414523752600164740ustar00rootroot00000000000000/* 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 2.1 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; } } flint2-2.8.4/padic_mat/mul.c000066400000000000000000000016231414523752600156200ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/padic_mat/neg.c000066400000000000000000000013541414523752600155750ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/padic_mat/one.c000066400000000000000000000012101414523752600155740ustar00rootroot00000000000000/* 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 2.1 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; } } flint2-2.8.4/padic_mat/randtest.c000066400000000000000000000025031414523752600166450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/padic_mat/reduce.c000066400000000000000000000024621414523752600162740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/padic_mat/scalar_div_fmpz.c000066400000000000000000000025641414523752600201730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.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_printf("ERROR (padic_mat_scalar_div_fmpz). c is zero.\n"); flint_abort(); } 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); } } flint2-2.8.4/padic_mat/scalar_mul_fmpz.c000066400000000000000000000023631414523752600202030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" 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); } flint2-2.8.4/padic_mat/scalar_mul_padic.c000066400000000000000000000022161414523752600203040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.h" #include "padic_mat.h" 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); } flint2-2.8.4/padic_mat/set.c000066400000000000000000000020131414523752600156100ustar00rootroot00000000000000/* 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 2.1 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); } } } flint2-2.8.4/padic_mat/set_entry_padic.c000066400000000000000000000031441414523752600201770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mat.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); } } flint2-2.8.4/padic_mat/set_fmpq_mat.c000066400000000000000000000050611414523752600175020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/padic_mat/sub.c000066400000000000000000000056101414523752600156140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/padic_mat/swap.c000066400000000000000000000011421414523752600157710ustar00rootroot00000000000000/* 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 2.1 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) { slong t; fmpz_mat_swap(padic_mat(A), padic_mat(B)); t = A->val; A->val = B->val; B->val = t; } flint2-2.8.4/padic_mat/test/000077500000000000000000000000001414523752600156345ustar00rootroot00000000000000flint2-2.8.4/padic_mat/test/t-add.c000066400000000000000000000162571414523752600170040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" #include "padic_mat.h" int main(void) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; FLINT_TEST_INIT(state); flint_printf("add... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } padic_mat_clear(a); padic_mat_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_mat/test/t-get_set_entry_padic.c000066400000000000000000000042311414523752600222540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" #include "padic_mat.h" int main(void) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; FLINT_TEST_INIT(state); flint_printf("get/ set_entry_padic... "); fflush(stdout); 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"); abort(); } padic_mat_clear(a); padic_clear(x); padic_clear(y); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_mat/test/t-get_set_fmpq_mat.c000066400000000000000000000040641414523752600215630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" #include "padic_mat.h" int main(void) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; FLINT_TEST_INIT(state); flint_printf("get/ set_fmpq_mat... "); fflush(stdout); /* 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"); abort(); } padic_mat_clear(a); padic_mat_clear(c); fmpq_mat_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_mat/test/t-mul.c000066400000000000000000000251571414523752600170500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" #include "padic_mat.h" int main(void) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; FLINT_TEST_INIT(state); flint_printf("mul... "); fflush(stdout); /* 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"); 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"); 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"); 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); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_mat/test/t-neg.c000066400000000000000000000061061414523752600170150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" #include "padic_mat.h" int main(void) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; FLINT_TEST_INIT(state); flint_printf("neg... "); fflush(stdout); /* 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"); 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"); abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_mat_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_mat/test/t-scalar_div_fmpz.c000066400000000000000000000041131414523752600214030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" #include "padic_mat.h" int main(void) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; FLINT_TEST_INIT(state); flint_printf("scalar_div_fmpz... "); fflush(stdout); /* 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"); abort(); } padic_mat_clear(a); padic_mat_clear(b); fmpz_clear(x); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_mat/test/t-scalar_mul_fmpz.c000066400000000000000000000041061414523752600214200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" #include "padic_mat.h" int main(void) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpz... "); fflush(stdout); /* 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"); abort(); } padic_mat_clear(a); padic_mat_clear(b); fmpz_clear(x); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_mat/test/t-scalar_mul_padic.c000066400000000000000000000041301414523752600215210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" #include "padic_mat.h" int main(void) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; FLINT_TEST_INIT(state); flint_printf("scalar_mul_padic... "); fflush(stdout); /* 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"); abort(); } padic_mat_clear(a); padic_mat_clear(b); padic_clear(x); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_mat/test/t-sub.c000066400000000000000000000155751414523752600170470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" #include "padic.h" #include "padic_mat.h" int main(void) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; slong m, n; FLINT_TEST_INIT(state); flint_printf("sub... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } padic_mat_clear(a); padic_mat_clear(b); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_mat/transpose.c000066400000000000000000000010731414523752600170400ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/padic_mat/zero.c000066400000000000000000000010111414523752600157710ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/padic_matxx.h000066400000000000000000000254531414523752600154170ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef PADIC_MATXX_H #define PADIC_MATXX_H #include "padic_mat.h" #include "padicxx.h" #include "fmpq_matxx.h" #include "flintxx/matrix.h" // TODO input and output namespace flint { FLINT_DEFINE_THREEARY(padic_matxx_get_entry) namespace detail { template struct padic_mat_traits : matrices::generic_traits { typedef slong prec_ref_t; typedef slong prec_srcref_t; typedef slong val_ref_t; typedef slong val_srcref_t; static slong prec(const Padic& p) {return tools::padic_output_prec(p);} static slong val(const Padic& p) {return padic_mat_val(p.evaluate()._mat());} }; } //detail template class padic_matxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; FLINTXX_DEFINE_BASICS(padic_matxx_expression) FLINTXX_DEFINE_CTORS(padic_matxx_expression) FLINTXX_DEFINE_C_REF(padic_matxx_expression, padic_mat_struct, _mat) public: typedef detail::padic_mat_traits traits_t; PADICXX_DEFINE_STD static padic_matxx_expression zero(padicxx_ctx_srcref ctx, slong rows, slong cols) {return padic_matxx_expression(ctx, rows, cols);} static padic_matxx_expression zero(padicxx_ctx_srcref ctx, slong rows, slong cols, slong N) {return padic_matxx_expression(ctx, rows, cols, N);} static padic_matxx_expression one(padicxx_ctx_srcref ctx, slong rows, slong cols) { padic_matxx_expression res(ctx, rows, cols); res.set_one(); return res; } static padic_matxx_expression one(padicxx_ctx_srcref ctx, slong rows, slong cols, slong N) { padic_matxx_expression res(ctx, rows, cols, N); res.set_one(); return res; } template static padic_matxx_expression from_QQ(const T& q, padicxx_ctx_srcref ctx, typename mp::enable_if >::type* = 0) { padic_matxx_expression res(ctx, q.rows(), q.cols()); res = q; return res; } template static padic_matxx_expression from_QQ(const T& q, padicxx_ctx_srcref ctx, slong N, typename mp::enable_if >::type* = 0) { padic_matxx_expression res(ctx, q.rows(), q.cols(), N); res = q; return res; } template static evaluated_t create_temporary_rowscols( const Expr& e, slong rows, slong cols) { return evaluated_t(tools::find_padicxx_ctx(e), rows, cols, tools::padic_output_prec(e)); } FLINTXX_DEFINE_MATRIX_METHODS(traits_t) // static methods which only make sense with padicxx static padic_matxx_expression randtest(slong rows, slong cols, frandxx& state, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) { padic_matxx_expression res(ctx, rows, cols, prec); padic_mat_randtest(res._mat(), state._data(), ctx._ctx()); return res; } // These only make sense with immediates void reduce() {padic_mat_reduce(_mat(), _ctx());} void set_zero() {padic_mat_zero(_mat());} void set_one() {padic_mat_one(_mat());} void truncate(slong n) {fmpz_poly_truncate(_mat(), n);} void canonicalise() {padic_mat_canonicalise(_mat());} bool is_canonical() const {return padic_mat_is_canonical(_mat());} bool is_reduced() const {return padic_mat_is_reduced(_mat());} template void set_entry(slong i, slong j, const Padic& p, typename mp::enable_if >::type* = 0) { padic_mat_set_entry_padic(_mat(), i, j, p.evaluate()._padic(), _ctx()); } // these cause evaluation bool is_zero() const {return padic_mat_is_zero(this->evaluate()._mat());} bool is_empty() const {return padic_mat_is_empty(this->evaluate()._mat());} bool is_square() const {return padic_mat_is_square(this->evaluate()._mat());} // forwarding of lazy functions FLINTXX_DEFINE_MEMBER_UNOP(transpose) FLINTXX_DEFINE_MEMBER_3OP_(get_entry, padic_matxx_get_entry) }; namespace detail { struct padic_mat_data; } typedef padic_matxx_expression padic_matxx; typedef padic_matxx_expression > padic_matxx_ref; typedef padic_matxx_expression > padic_matxx_srcref; template<> struct matrix_traits { template static slong rows(const M& m) { return padic_mat_nrows(m._mat()); } template static slong cols(const M& m) { return padic_mat_ncols(m._mat()); } template static fmpzxx_srcref at(const M& m, slong i, slong j) { return fmpzxx_srcref::make(padic_mat_entry(m._mat(), i, j)); } template static fmpzxx_ref at(M& m, slong i, slong j) { return fmpzxx_ref::make(padic_mat_entry(m._mat(), i, j)); } }; namespace traits { template<> struct has_padicxx_ctx : mp::true_ { }; template<> struct has_padicxx_ctx : mp::true_ { }; template<> struct has_padicxx_ctx : mp::true_ { }; } // traits namespace detail { struct padic_matxx_srcref_traits_no_std_matrix { typedef slong prec_ref_t; typedef slong prec_srcref_t; typedef slong val_ref_t; typedef slong val_srcref_t; template static slong prec(P p) {return p._data().N;} template static slong val(P p) {return padic_mat_val(p._mat());} }; struct padic_matxx_ref_traits_no_std_matrix : padic_matxx_srcref_traits_no_std_matrix { typedef slong& prec_ref_t; typedef slong& val_ref_t; template static slong& prec(P& p) {return padic_mat_prec(p._mat());} template static slong prec(const P& p) {return padic_mat_prec(p._mat());} template static slong& val(P& p) {return padic_mat_val(p._mat());} template static slong val(const P& p) {return padic_mat_val(p._mat());} }; template<> struct padic_mat_traits : matrices::generic_traits_srcref, padic_matxx_srcref_traits_no_std_matrix { }; template<> struct padic_mat_traits : matrices::generic_traits_ref, padic_matxx_ref_traits_no_std_matrix { }; template<> struct padic_mat_traits : matrices::generic_traits_nonref, padic_matxx_ref_traits_no_std_matrix { }; } // detail PADICXX_DEFINE_REF_STRUCTS(padic_matxx, padic_mat_struct, padic_mat_prec) namespace detail { struct padic_mat_data { typedef padic_mat_t& data_ref_t; typedef const padic_mat_t& data_srcref_t; padicxx_ctx_srcref ctx; padic_mat_t inner; padic_mat_data(padicxx_ctx_srcref c, slong rows, slong cols) : ctx(c) { padic_mat_init(inner, rows, cols); } padic_mat_data(padicxx_ctx_srcref c, slong rows, slong cols, slong N) : ctx(c) { padic_mat_init2(inner, rows, cols, N); } padic_mat_data(const padic_mat_data& o) : ctx(o.ctx) { padic_mat_init2(inner, padic_mat_nrows(o.inner), padic_mat_ncols(o.inner), padic_mat_prec(o.inner)); padic_mat_set(inner, o.inner, ctx._ctx()); } ~padic_mat_data() {padic_mat_clear(inner);} padic_mat_data(padic_matxx_srcref c) : ctx(c.get_ctx()) { padic_mat_init2(inner, c.rows(), c.cols(), c.prec()); padic_mat_set(inner, c._mat(), ctx._ctx()); } }; } // detail // matrix temporary stuff FLINTXX_DEFINE_TEMPORARY_RULES(padic_matxx) #define PADIC_MATXX_COND_S FLINTXX_COND_S(padic_matxx) #define PADIC_MATXX_COND_T FLINTXX_COND_T(padic_matxx) namespace rules { FLINT_DEFINE_DOIT_COND2(assignment, PADIC_MATXX_COND_T, PADIC_MATXX_COND_S, padic_mat_set(to._mat(), from._mat(), to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, PADIC_MATXX_COND_T, FMPQ_MATXX_COND_S, padic_mat_set_fmpq_mat(to._mat(), from._mat(), to._ctx())) FLINTXX_DEFINE_SWAP(padic_matxx, padic_mat_swap(e1._mat(), e2._mat())) FLINTXX_DEFINE_EQUALS(padic_matxx, padic_mat_equal(e1._mat(), e2._mat())) FLINT_DEFINE_PRINT_COND(PADIC_MATXX_COND_S, padic_mat_fprint(to, from._mat(), from._ctx())) FLINT_DEFINE_PRINT_PRETTY_COND(PADIC_MATXX_COND_S, padic_mat_fprint_pretty(to, from._mat(), from._ctx())) template struct conversion >::type> { static fmpq_matxx get(const T& from) { fmpq_matxx to(from.rows(), from.cols()); padic_mat_get_fmpq_mat(to._mat(), from._mat(), from._ctx()); return to; } }; FLINT_DEFINE_THREEARY_EXPR_COND3(padic_matxx_get_entry_op, padicxx, PADIC_MATXX_COND_S, traits::fits_into_slong, traits::fits_into_slong, padic_mat_get_entry_padic(to._padic(), e1._mat(), e2, e3, to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(transpose_op, padic_matxx, PADIC_MATXX_COND_S, padic_mat_transpose(to._mat(), from._mat())) FLINT_DEFINE_CBINARY_EXPR_COND2(plus, padic_matxx, PADIC_MATXX_COND_S, PADIC_MATXX_COND_S, padic_mat_add(to._mat(), e1._mat(), e2._mat(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, padic_matxx, PADIC_MATXX_COND_S, PADIC_MATXX_COND_S, padic_mat_sub(to._mat(), e1._mat(), e2._mat(), to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(negate, padic_matxx, PADIC_MATXX_COND_S, padic_mat_neg(to._mat(), from._mat(), to._ctx())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, padic_matxx, PADIC_MATXX_COND_S, PADICXX_COND_S, padic_mat_scalar_mul_padic(to._mat(), e1._mat(), e2._padic(), to._ctx())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, padic_matxx, PADIC_MATXX_COND_S, FMPZXX_COND_S, padic_mat_scalar_mul_fmpz(to._mat(), e1._mat(), e2._fmpz(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, padic_matxx, PADIC_MATXX_COND_S, FMPZXX_COND_S, padic_mat_scalar_div_fmpz(to._mat(), e1._mat(), e2._fmpz(), to._ctx())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, padic_matxx, PADIC_MATXX_COND_S, PADIC_MATXX_COND_S, padic_mat_mul(to._mat(), e1._mat(), e2._mat(), to._ctx())) } // rules } #endif flint2-2.8.4/padic_poly.h000066400000000000000000000332411414523752600152330ustar00rootroot00000000000000/* 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 2.1 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 FLINT_DLL #else #define PADIC_POLY_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx/* interferes with system includes */ #include #undef ulong #include #define ulong mp_limb_t #include "fmpz.h" #include "fmpq.h" #include "padic.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "fmpq_poly.h" #ifdef __cplusplus extern "C" { #endif /* Type definitions ********************************************************/ typedef struct { fmpz *coeffs; slong alloc; slong length; slong val; slong N; } padic_poly_struct; typedef padic_poly_struct padic_poly_t[1]; /* 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 *******************************************************/ FLINT_DLL void padic_poly_init(padic_poly_t poly); FLINT_DLL void padic_poly_init2(padic_poly_t poly, slong alloc, slong prec); FLINT_DLL void padic_poly_clear(padic_poly_t poly); FLINT_DLL void padic_poly_realloc(padic_poly_t f, slong alloc, const fmpz_t p); FLINT_DLL 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; } FLINT_DLL void _padic_poly_normalise(padic_poly_t f); FLINT_DLL void _padic_poly_canonicalise(fmpz *poly, slong *v, slong len, const fmpz_t p); FLINT_DLL void padic_poly_canonicalise(padic_poly_t poly, const fmpz_t p); FLINT_DLL 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 ***********************************************************/ FLINT_DLL void padic_poly_randtest(padic_poly_t f, flint_rand_t state, slong len, const padic_ctx_t ctx); FLINT_DLL void padic_poly_randtest_not_zero(padic_poly_t f, flint_rand_t state, slong len, const padic_ctx_t ctx); FLINT_DLL 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 ***************************************/ FLINT_DLL void padic_poly_set(padic_poly_t f, const padic_poly_t g, const padic_ctx_t ctx); FLINT_DLL void padic_poly_set_padic(padic_poly_t poly, const padic_t x, const padic_ctx_t ctx); FLINT_DLL void padic_poly_set_si(padic_poly_t poly, slong x, const padic_ctx_t ctx); FLINT_DLL void padic_poly_set_ui(padic_poly_t poly, ulong x, const padic_ctx_t ctx); FLINT_DLL void padic_poly_set_fmpz(padic_poly_t poly, const fmpz_t x, const padic_ctx_t ctx); FLINT_DLL void padic_poly_set_fmpq(padic_poly_t poly, const fmpq_t x, const padic_ctx_t ctx); FLINT_DLL void padic_poly_set_fmpz_poly(padic_poly_t rop, const fmpz_poly_t op, const padic_ctx_t ctx); FLINT_DLL void padic_poly_set_fmpq_poly(padic_poly_t rop, const fmpq_poly_t op, const padic_ctx_t ctx); FLINT_DLL int padic_poly_get_fmpz_poly(fmpz_poly_t rop, const padic_poly_t op, const padic_ctx_t ctx); FLINT_DLL 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); } } FLINT_DLL void padic_poly_swap(padic_poly_t poly1, padic_poly_t poly2); /* Getting and setting coefficients ****************************************/ FLINT_DLL void padic_poly_get_coeff_padic(padic_t c, const padic_poly_t poly, slong n, const padic_ctx_t ctx); FLINT_DLL void padic_poly_set_coeff_padic(padic_poly_t f, slong n, const padic_t c, const padic_ctx_t ctx); /* Comparison **************************************************************/ FLINT_DLL 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 ************************************************/ FLINT_DLL 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); FLINT_DLL void padic_poly_add(padic_poly_t f, const padic_poly_t g, const padic_poly_t h, const padic_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void padic_poly_sub(padic_poly_t f, const padic_poly_t g, const padic_poly_t h, const padic_ctx_t ctx); FLINT_DLL void padic_poly_neg(padic_poly_t f, const padic_poly_t g, const padic_ctx_t ctx); /* Scalar multiplication and division **************************************/ FLINT_DLL 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); FLINT_DLL 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 **********************************************************/ FLINT_DLL 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); FLINT_DLL void padic_poly_mul(padic_poly_t f, const padic_poly_t g, const padic_poly_t h, const padic_ctx_t ctx); /* Powering ****************************************************************/ FLINT_DLL void _padic_poly_pow(fmpz *rop, slong *rval, slong N, const fmpz *op, slong val, slong len, ulong e, const padic_ctx_t ctx); FLINT_DLL void padic_poly_pow(padic_poly_t rop, const padic_poly_t op, ulong e, const padic_ctx_t ctx); /* Series inversion ********************************************************/ FLINT_DLL void padic_poly_inv_series(padic_poly_t Qinv, const padic_poly_t Q, slong n, const padic_ctx_t ctx); /* Derivative **************************************************************/ FLINT_DLL void _padic_poly_derivative(fmpz *rop, slong *rval, slong N, const fmpz *op, slong val, slong len, const padic_ctx_t ctx); FLINT_DLL void padic_poly_derivative(padic_poly_t rop, const padic_poly_t op, const padic_ctx_t ctx); /* Shifting ****************************************************************/ FLINT_DLL void padic_poly_shift_left(padic_poly_t rop, const padic_poly_t op, slong n, const padic_ctx_t ctx); FLINT_DLL void padic_poly_shift_right(padic_poly_t rop, const padic_poly_t op, slong n, const padic_ctx_t ctx); /* Evaluation **************************************************************/ FLINT_DLL 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); FLINT_DLL void padic_poly_evaluate_padic(padic_t y, const padic_poly_t poly, const padic_t x, const padic_ctx_t ctx); /* Composition *************************************************************/ FLINT_DLL 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); FLINT_DLL void padic_poly_compose(padic_poly_t rop, const padic_poly_t op1, const padic_poly_t op2, const padic_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void padic_poly_compose_pow(padic_poly_t rop, const padic_poly_t op, slong k, const padic_ctx_t ctx); /* Input and output ********************************************************/ PADIC_POLY_INLINE 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_DLL int _padic_poly_fprint(FILE *file, const fmpz *poly, slong val, slong len, const padic_ctx_t ctx); FLINT_DLL int padic_poly_fprint(FILE *file, const padic_poly_t poly, const padic_ctx_t ctx); PADIC_POLY_INLINE 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); } PADIC_POLY_INLINE int padic_poly_print(const padic_poly_t poly, const padic_ctx_t ctx) { return padic_poly_fprint(stdout, poly, ctx); } FLINT_DLL int _padic_poly_fprint_pretty(FILE *file, const fmpz *poly, slong val, slong len, const char *var, const padic_ctx_t ctx); FLINT_DLL int padic_poly_fprint_pretty(FILE *file, const padic_poly_t poly, const char *var, const padic_ctx_t ctx); PADIC_POLY_INLINE int _padic_poly_print_pretty(FILE *file, 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); } PADIC_POLY_INLINE 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); } /* Testing *****************************************************************/ FLINT_DLL int _padic_poly_is_canonical(const fmpz *op, slong val, slong len, const padic_ctx_t ctx); FLINT_DLL int padic_poly_is_canonical(const padic_poly_t op, const padic_ctx_t ctx); FLINT_DLL int _padic_poly_is_reduced(const fmpz *op, slong val, slong len, slong N, const padic_ctx_t ctx); FLINT_DLL int padic_poly_is_reduced(const padic_poly_t op, const padic_ctx_t ctx); #ifdef __cplusplus } #endif #endif flint2-2.8.4/padic_poly/000077500000000000000000000000001414523752600150575ustar00rootroot00000000000000flint2-2.8.4/padic_poly/add.c000066400000000000000000000061351414523752600157600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.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); } flint2-2.8.4/padic_poly/canonicalise.c000066400000000000000000000017571414523752600176650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/padic_poly/clear.c000066400000000000000000000013131414523752600163070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/padic_poly/compose.c000066400000000000000000000112141414523752600166670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.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 *vec2; fmpz_t f; fmpz_t pow; int alloc; 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_mod_poly_compose(rop, op1, len1, vec2, len2, pow); *rval= val1; _padic_poly_canonicalise(rop, rval, lenr, ctx->p); _fmpz_vec_clear(vec2, len2); 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; fmpz_t s, t; slong i; vec1 = _fmpz_vec_init(len1); 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_mod_poly_compose(rop, vec1, len1, op2, len2, pow); *rval = val1 + n*val2; _padic_poly_canonicalise(rop, rval, lenr, ctx->p); _fmpz_vec_clear(vec1, len1); 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); } } flint2-2.8.4/padic_poly/compose_pow.c000066400000000000000000000042351414523752600175610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.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); } } flint2-2.8.4/padic_poly/derivative.c000066400000000000000000000026351414523752600173730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.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); } } flint2-2.8.4/padic_poly/equal.c000066400000000000000000000012401414523752600163270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/padic_poly/evaluate_padic.c000066400000000000000000000111511414523752600201700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.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; } } } /* 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(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(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); } } flint2-2.8.4/padic_poly/fit_length.c000066400000000000000000000021071414523752600173460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } } flint2-2.8.4/padic_poly/fprint.c000066400000000000000000000024171414523752600165310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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(FILE *file, const padic_poly_t poly, const padic_ctx_t ctx) { _padic_poly_fprint(file, poly->coeffs, poly->val, poly->length, ctx); return 1; } flint2-2.8.4/padic_poly/fprint_pretty.c000066400000000000000000000102041414523752600201310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "padic_poly.h" 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_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); } flint2-2.8.4/padic_poly/get_coeff_padic.c000066400000000000000000000014421414523752600203050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/padic_poly/get_fmpq_poly.c000066400000000000000000000031371414523752600200740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/padic_poly/get_fmpz_poly.c000066400000000000000000000021341414523752600201010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/padic_poly/init.c000066400000000000000000000016701414523752600161720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.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; } flint2-2.8.4/padic_poly/inlines.c000066400000000000000000000010641414523752600166650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define PADIC_POLY_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "padic_poly.h" flint2-2.8.4/padic_poly/inv_series.c000066400000000000000000000042731414523752600173770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "padic_poly.h" 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_printf("Exception (padic_poly_inv_series): Constant term is zero.\n"); flint_abort(); } if (fmpz_divisible(Q->coeffs + 0, ctx->p)) { flint_printf("Exception (padic_poly_inv_series):\n"); flint_printf("Valuation of constant term is not minimal.\n"); flint_abort(); } 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); _fmpz_mod_poly_inv_series_newton(Qinv->coeffs, Qcopy, n, cinv, pow); } else { fmpz *t = _fmpz_vec_init(n); _fmpz_mod_poly_inv_series_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); } flint2-2.8.4/padic_poly/is_canonical.c000066400000000000000000000015161414523752600176500ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/padic_poly/is_reduced.c000066400000000000000000000023041414523752600173300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/padic_poly/mul.c000066400000000000000000000040221414523752600160160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/padic_poly/neg.c000066400000000000000000000025151414523752600157770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "padic_poly.h" 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_mod_poly_neg(f->coeffs, g->coeffs, len, pow); } else /* Reduction necessary? */ { _fmpz_vec_scalar_mod_fmpz(f->coeffs, g->coeffs, len, pow); _fmpz_mod_poly_neg(f->coeffs, f->coeffs, len, pow); _padic_poly_normalise(f); } if (alloc) fmpz_clear(pow); } } flint2-2.8.4/padic_poly/normalise.c000066400000000000000000000011541414523752600172150ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/padic_poly/pow.c000066400000000000000000000034171414523752600160350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.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_mod_poly_pow(rop, op, len, e, pow); 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); } } flint2-2.8.4/padic_poly/randtest.c000066400000000000000000000050171414523752600170520ustar00rootroot00000000000000/* Copyright (C) 2011, 2012 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.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_printf("Exception (padic_poly_randtest_not_zero). len == 0.\n"); flint_abort(); } 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; } } flint2-2.8.4/padic_poly/realloc.c000066400000000000000000000023551414523752600166510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } flint2-2.8.4/padic_poly/reduce.c000066400000000000000000000020661414523752600164760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } } } } flint2-2.8.4/padic_poly/scalar_mul_padic.c000066400000000000000000000031541414523752600205100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/padic_poly/set.c000066400000000000000000000032271414523752600160220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; */ } } } } flint2-2.8.4/padic_poly/set_coeff_padic.c000066400000000000000000000040301414523752600203150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/padic_poly/set_fmpq.c000066400000000000000000000012511414523752600170400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/padic_poly/set_fmpq_poly.c000066400000000000000000000024161414523752600201070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_vec.h" #include "fmpq_poly.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); } } flint2-2.8.4/padic_poly/set_fmpz.c000066400000000000000000000012511414523752600170510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/padic_poly/set_fmpz_poly.c000066400000000000000000000014371414523752600201220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_poly.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); } flint2-2.8.4/padic_poly/set_padic.c000066400000000000000000000022651414523752600171630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } } flint2-2.8.4/padic_poly/set_si.c000066400000000000000000000012041414523752600165060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/padic_poly/set_ui.c000066400000000000000000000012041414523752600165100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/padic_poly/shift_left.c000066400000000000000000000020611414523752600173510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Exception (padic_poly_shift_left). rop->N < op->N.\n"); flint_abort(); } 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 */ } } flint2-2.8.4/padic_poly/shift_right.c000066400000000000000000000017731414523752600175450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 */ } } flint2-2.8.4/padic_poly/sub.c000066400000000000000000000062441414523752600160220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.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); } flint2-2.8.4/padic_poly/swap.c000066400000000000000000000020161414523752600161740ustar00rootroot00000000000000/* 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 2.1 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) { if (poly1 != poly2) { slong t; fmpz *c; t = poly1->length; poly1->length = poly2->length; poly2->length = t; t = poly1->alloc; poly1->alloc = poly2->alloc; poly2->alloc = t; t = poly1->val; poly1->val = poly2->val; poly2->val = t; t = poly1->N; poly1->N = poly2->N; poly2->N = t; c = poly1->coeffs; poly1->coeffs = poly2->coeffs; poly2->coeffs = c; } } flint2-2.8.4/padic_poly/test/000077500000000000000000000000001414523752600160365ustar00rootroot00000000000000flint2-2.8.4/padic_poly/test/t-add.c000066400000000000000000000117621414523752600172020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "long_extras.h" #include "ulong_extras.h" #include "padic_poly.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add... "); fflush(stdout); /* 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-compose.c000066400000000000000000000100511414523752600201050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "long_extras.h" #include "ulong_extras.h" #include "padic_poly.h" int main(void) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; FLINT_TEST_INIT(state); flint_printf("compose... "); fflush(stdout); /* 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-compose_pow.c000066400000000000000000000073031414523752600210000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "long_extras.h" #include "ulong_extras.h" #include "padic_poly.h" int main(void) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; FLINT_TEST_INIT(state); flint_printf("compose_pow... "); fflush(stdout); /* 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"); 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); abort(); } padic_poly_clear(f); padic_poly_clear(g); padic_poly_clear(h1); padic_poly_clear(h2); padic_ctx_clear(ctx); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-derivative.c000066400000000000000000000071331414523752600206110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "padic_poly.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; FLINT_TEST_INIT(state); flint_printf("derivative... "); fflush(stdout); /* 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-evaluate_padic.c000066400000000000000000000067431414523752600214230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "long_extras.h" #include "ulong_extras.h" #include "padic_poly.h" int main(void) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; FLINT_TEST_INIT(state); flint_printf("evaluate_padic... "); fflush(stdout); /* 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-get_set_fmpq_poly.c000066400000000000000000000037201414523752600221650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "long_extras.h" #include "ulong_extras.h" #include "padic_poly.h" int main(void) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; FLINT_TEST_INIT(state); flint_printf("get/set_fmpq_poly... "); fflush(stdout); /* 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"); abort(); } padic_poly_clear(a); padic_poly_clear(b); fmpq_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-init_realloc_clear.c000066400000000000000000000037401414523752600222610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "long_extras.h" #include "ulong_extras.h" #include "padic_poly.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("init/init2/realloc/clear... "); fflush(stdout); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-inv_series.c000066400000000000000000000106701414523752600206150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "long_extras.h" #include "ulong_extras.h" #include "padic_poly.h" int main(void) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; FLINT_TEST_INIT(state); flint_printf("inv_series... "); fflush(stdout); /* 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"); 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); abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-mul.c000066400000000000000000000160151414523752600172430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "padic_poly.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; FLINT_TEST_INIT(state); flint_printf("mul... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-neg.c000066400000000000000000000057721414523752600172270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "padic_poly.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("neg... "); fflush(stdout); /* 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"); 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"); abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-one.c000066400000000000000000000032371414523752600172310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "padic_poly.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; FLINT_TEST_INIT(state); flint_printf("one...."); fflush(stdout); 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); abort(); } padic_poly_clear(a); padic_ctx_clear(ctx); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-pow.c000066400000000000000000000112241414523752600172500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "padic_poly.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; FLINT_TEST_INIT(state); flint_printf("pow... "); fflush(stdout); /* 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); 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"); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-shift_left_right.c000066400000000000000000000106331414523752600217720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "padic_poly.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; FLINT_TEST_INIT(state); flint_printf("shift_left/right... "); fflush(stdout); /* 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"); 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"); 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"); abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-sub.c000066400000000000000000000110131414523752600172300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" #include "long_extras.h" #include "padic_poly.h" int main(void) { int i, result; fmpz_t p; slong N; padic_ctx_t ctx; FLINT_TEST_INIT(state); flint_printf("sub... "); fflush(stdout); /* 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"); 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"); 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"); abort(); } padic_poly_clear(a); padic_poly_clear(b); padic_poly_clear(c); fmpz_clear(p); padic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-truncate.c000066400000000000000000000066001414523752600202720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "long_extras.h" #include "ulong_extras.h" #include "padic_poly.h" int main(void) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; FLINT_TEST_INIT(state); flint_printf("truncate... "); fflush(stdout); /* 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"); 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"); abort(); } padic_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(c); padic_ctx_clear(ctx); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_poly/test/t-zero.c000066400000000000000000000031541414523752600174250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "fmpz.h" #include "padic_poly.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; padic_ctx_t ctx; fmpz_t p; slong N; FLINT_TEST_INIT(state); flint_printf("zero...."); fflush(stdout); 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"); abort(); } padic_poly_clear(a); padic_ctx_clear(ctx); fmpz_clear(p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/padic_polyxx.h000066400000000000000000000334211414523752600156130ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef PADIC_POLYXX_H #define PADIC_POLYXX_H #include "padic_poly.h" #include "padicxx.h" #include "fmpz_polyxx.h" #include "fmpq_polyxx.h" #include "flintxx/stdmath.h" // TODO input and output namespace flint { FLINT_DEFINE_BINOP(padic_polyxx_get_coeff) FLINT_DEFINE_BINOP(compose_pow) namespace detail { template struct padic_poly_traits { typedef slong prec_ref_t; typedef slong prec_srcref_t; typedef slong val_ref_t; typedef slong val_srcref_t; static slong prec(const Padic& p) {return tools::padic_output_prec(p);} static slong val(const Padic& p) {return padic_poly_val(p.evaluate()._poly());} }; } //detail template class padic_polyxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; FLINTXX_DEFINE_BASICS(padic_polyxx_expression) FLINTXX_DEFINE_CTORS(padic_polyxx_expression) FLINTXX_DEFINE_C_REF(padic_polyxx_expression, padic_poly_struct, _poly) public: typedef detail::padic_poly_traits traits_t; PADICXX_DEFINE_STD static padic_polyxx_expression zero(padicxx_ctx_srcref ctx) {return padic_polyxx_expression(ctx);} static padic_polyxx_expression zero(padicxx_ctx_srcref ctx, slong N) {return padic_polyxx_expression(ctx, N);} static padic_polyxx_expression one(padicxx_ctx_srcref ctx) { padic_polyxx_expression res(ctx); res.set_one(); return res; } static padic_polyxx_expression one(padicxx_ctx_srcref ctx, slong N) { padic_polyxx_expression res(ctx, N); res.set_one(); return res; } template static padic_polyxx_expression from_QQ(const T& q, padicxx_ctx_srcref ctx, typename mp::enable_if, traits::is_fmpzxx, traits::is_integer > >::type* = 0) { padic_polyxx_expression res(ctx); res = q; return res; } template static padic_polyxx_expression from_QQ(const T& q, padicxx_ctx_srcref ctx, slong N, typename mp::enable_if, traits::is_fmpzxx, traits::is_integer > >::type* = 0) { padic_polyxx_expression res(ctx, N); res = q; return res; } template static padic_polyxx_expression from_QQX(const T& q, padicxx_ctx_srcref ctx, typename mp::enable_if, traits::is_fmpz_polyxx > >::type* = 0) { padic_polyxx_expression res(ctx); res = q; return res; } template static padic_polyxx_expression from_QQX(const T& q, padicxx_ctx_srcref ctx, slong N, typename mp::enable_if, traits::is_fmpz_polyxx > >::type* = 0) { padic_polyxx_expression res(ctx, N); res = q; return res; } template static padic_polyxx_expression _from_ground(const T& q) { padic_polyxx_expression res(q.get_ctx(), q.prec()); res = q; return res; } template static padic_polyxx_expression from_ground(const T& q, typename mp::enable_if >::type* = 0) { return _from_ground(q.evaluate()); } // Create a temporary. The context will be estimated, and the precision // will be the maximum of all subexpressions. evaluated_t create_temporary() const { return evaluated_t(estimate_ctx(), prec()); } // static methods which only make sense with padicxx static padic_polyxx_expression randtest(frandxx& state, slong len, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) { padic_polyxx_expression res(ctx, prec); padic_poly_randtest(res._poly(), state._data(), len, ctx._ctx()); return res; } static padic_polyxx_expression randtest_not_zero(frandxx& state, slong len, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) { padic_polyxx_expression res(ctx, prec); padic_poly_randtest_not_zero(res._poly(), state._data(), len, ctx._ctx()); return res; } static padic_polyxx_expression randtest_val(frandxx& state, slong val, slong len, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) { padic_polyxx_expression res(ctx, prec); padic_poly_randtest_val(res._poly(), state._data(), val, len, ctx._ctx()); return res; } // These only make sense with immediates void reduce() {padic_poly_reduce(_poly(), _ctx());} void realloc(slong alloc) {padic_poly_realloc(_poly(), alloc);} void fit_length(slong len) {padic_poly_fit_length(_poly(), len);} void _normalise() {_padic_poly_normalise(_poly());} void _set_length(slong len) {_padic_poly_set_length(_poly(), len);} void set_zero() {padic_poly_zero(_poly());} void set_one() {padic_poly_one(_poly());} void truncate(slong n) {fmpz_poly_truncate(_poly(), n);} void canonicalise() {padic_poly_canonicalise(_poly());} bool is_canonical() const {return padic_poly_is_canonical(_poly());} bool is_reduced() const {return padic_poly_is_reduced(_poly());} template void set_coeff(slong n, const Padic& p, typename mp::enable_if >::type* = 0) {padic_poly_set_coeff_padic(_poly(), n, p._padic(), _ctx());} // these cause evaluation bool is_zero() const {return padic_poly_is_zero(this->evaluate()._poly());} bool is_one() const {return padic_poly_is_one(this->evaluate()._poly());} slong length() const {return padic_poly_length(this->evaluate()._poly());} slong degree() const {return padic_poly_degree(this->evaluate()._poly());} // forwarding of lazy functions FLINTXX_DEFINE_MEMBER_BINOP_(get_coeff, padic_polyxx_get_coeff) FLINTXX_DEFINE_MEMBER_BINOP_(operator(), compeval) FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_BINOP(compose_pow) FLINTXX_DEFINE_MEMBER_BINOP(inv_series) FLINTXX_DEFINE_MEMBER_BINOP(shift_left) FLINTXX_DEFINE_MEMBER_BINOP(shift_right) FLINTXX_DEFINE_MEMBER_UNOP(derivative) }; namespace detail { struct padic_poly_data; } typedef padic_polyxx_expression padic_polyxx; typedef padic_polyxx_expression > padic_polyxx_ref; typedef padic_polyxx_expression > padic_polyxx_srcref; namespace traits { template<> struct has_padicxx_ctx : mp::true_ { }; template<> struct has_padicxx_ctx : mp::true_ { }; template<> struct has_padicxx_ctx : mp::true_ { }; } // traits namespace detail { template<> struct padic_poly_traits { typedef slong prec_ref_t; typedef slong prec_srcref_t; typedef slong val_ref_t; typedef slong val_srcref_t; template static slong prec(P p) {return p._data().N;} template static slong val(P p) {return padic_poly_val(p._poly());} }; template<> struct padic_poly_traits : padic_poly_traits { typedef slong& prec_ref_t; typedef slong& val_ref_t; template static slong& prec(P& p) {return padic_poly_prec(p._poly());} template static slong prec(const P& p) {return padic_poly_prec(p._poly());} template static slong& val(P& p) {return padic_poly_val(p._poly());} template static slong val(const P& p) {return padic_poly_val(p._poly());} }; template<> struct padic_poly_traits : padic_poly_traits { }; } // detail PADICXX_DEFINE_REF_STRUCTS(padic_polyxx, padic_poly_struct, padic_poly_prec) namespace detail { struct padic_poly_data { typedef padic_poly_t& data_ref_t; typedef const padic_poly_t& data_srcref_t; padicxx_ctx_srcref ctx; padic_poly_t inner; padic_poly_data(padicxx_ctx_srcref c) : ctx(c) { padic_poly_init(inner); } padic_poly_data(padicxx_ctx_srcref c, slong N, slong alloc = 0) : ctx(c) { padic_poly_init2(inner, alloc, N); } padic_poly_data(const padic_poly_data& o) : ctx(o.ctx) { padic_poly_init2(inner, padic_poly_length(o.inner), padic_poly_prec(o.inner)); padic_poly_set(inner, o.inner, ctx._ctx()); } ~padic_poly_data() {padic_poly_clear(inner);} padic_poly_data(padic_polyxx_srcref c) : ctx(c.get_ctx()) { padic_poly_init2(inner, c.length(), c.prec()); padic_poly_set(inner, c._poly(), ctx._ctx()); } }; } // detail #define PADIC_POLYXX_COND_S FLINTXX_COND_S(padic_polyxx) #define PADIC_POLYXX_COND_T FLINTXX_COND_T(padic_polyxx) namespace rules { FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, PADIC_POLYXX_COND_S, padic_poly_set(to._poly(), from._poly(), to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, PADICXX_COND_S, padic_poly_set_padic(to._poly(), from._padic(), to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, traits::is_signed_integer, padic_poly_set_si(to._poly(), from, to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, traits::is_unsigned_integer, padic_poly_set_ui(to._poly(), from, to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, FMPZXX_COND_S, padic_poly_set_fmpz(to._poly(), from._fmpz(), to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, FMPQXX_COND_S, padic_poly_set_fmpq(to._poly(), from._fmpq(), to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, FMPZ_POLYXX_COND_S, padic_poly_set_fmpz_poly(to._poly(), from._poly(), to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, PADIC_POLYXX_COND_T, FMPQ_POLYXX_COND_S, padic_poly_set_fmpq_poly(to._poly(), from._poly(), to._ctx())) FLINTXX_DEFINE_SWAP(padic_polyxx, padic_poly_swap(e1._poly(), e2._poly())) FLINTXX_DEFINE_EQUALS(padic_polyxx, padic_poly_equal(e1._poly(), e2._poly())) FLINT_DEFINE_PRINT_COND(PADIC_POLYXX_COND_S, padic_poly_fprint(to, from._poly(), from._ctx())) FLINT_DEFINE_PRINT_PRETTY_COND_2(PADIC_POLYXX_COND_S, const char*, padic_poly_fprint_pretty(to, from._poly(), extra, from._ctx())) FLINTXX_DEFINE_CONVERSION_TMP(fmpz_polyxx, padic_polyxx, execution_check(padic_poly_get_fmpz_poly( to._poly(), from._poly(), from._ctx()), "to", "padic_polyxx")) FLINTXX_DEFINE_CONVERSION_TMP(fmpq_polyxx, padic_polyxx, padic_poly_get_fmpq_poly(to._poly(), from._poly(), from._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(padic_polyxx_get_coeff_op, padicxx, PADIC_POLYXX_COND_S, traits::fits_into_slong, padic_poly_get_coeff_padic(to._padic(), e1._poly(), e2, to._ctx())) FLINT_DEFINE_CBINARY_EXPR_COND2(plus, padic_polyxx, PADIC_POLYXX_COND_S, PADIC_POLYXX_COND_S, padic_poly_add(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, padic_polyxx, PADIC_POLYXX_COND_S, PADIC_POLYXX_COND_S, padic_poly_sub(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(negate, padic_polyxx, PADIC_POLYXX_COND_S, padic_poly_neg(to._poly(), from._poly(), to._ctx())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, padic_polyxx, PADIC_POLYXX_COND_S, PADICXX_COND_S, padic_poly_scalar_mul_padic(to._poly(), e1._poly(), e2._padic(), to._ctx())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, padic_polyxx, PADIC_POLYXX_COND_S, PADIC_POLYXX_COND_S, padic_poly_mul(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, padic_polyxx, PADIC_POLYXX_COND_S, traits::is_unsigned_integer, padic_poly_pow(to._poly(), e1._poly(), e2, to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(inv_series_op, padic_polyxx, PADIC_POLYXX_COND_S, traits::fits_into_slong, padic_poly_inv_series(to._poly(), e1._poly(), e2, to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(derivative_op, padic_polyxx, PADIC_POLYXX_COND_S, padic_poly_derivative(to._poly(), from._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(shift_left_op, padic_polyxx, PADIC_POLYXX_COND_S, traits::fits_into_slong, padic_poly_shift_left(to._poly(), e1._poly(), e2, to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(shift_right_op, padic_polyxx, PADIC_POLYXX_COND_S, traits::fits_into_slong, padic_poly_shift_right(to._poly(), e1._poly(), e2, to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(evaluate_op, padicxx, PADIC_POLYXX_COND_S, PADICXX_COND_S, padic_poly_evaluate_padic(to._padic(), e1._poly(), e2._padic(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(compose_op, padic_polyxx, PADIC_POLYXX_COND_S, PADIC_POLYXX_COND_S, padic_poly_compose(to._poly(), e1._poly(), e2._poly(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(compose_pow_op, padic_polyxx, PADIC_POLYXX_COND_S, traits::fits_into_slong, padic_poly_compose_pow(to._poly(), e1._poly(), e2, to._ctx())) } // rules } // flint #endif flint2-2.8.4/padicxx.h000066400000000000000000000555171414523752600145620ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_PADICXX_H #define CXX_PADICXX_H CXX_PADICXX_H #include // std::max #include #include "padic.h" #include "flintxx/expression.h" #include "flintxx/flint_classes.h" #include "flintxx/flint_exception.h" #include "flintxx/frandxx.h" #include "flintxx/stdmath.h" #include "flintxx/traits.h" #include "flintxx/tuple.h" #include "fmpzxx.h" #include "fmpqxx.h" // TODO check codegen ... // TODO padic_output_prec does not work on non-padic expressions, // is that a problem? namespace flint { // function "declarations" FLINT_DEFINE_UNOP(exp_rectangular) FLINT_DEFINE_UNOP(exp_balanced) FLINT_DEFINE_UNOP(log_rectangular) FLINT_DEFINE_UNOP(log_balanced) FLINT_DEFINE_UNOP(log_satoh) FLINT_DEFINE_UNOP(teichmuller) FLINT_DEFINE_BINOP(padic_val_fac) class padicxx_ctx { private: mutable padic_ctx_t ctx; public: // NB: you must not modify user-visible state of ctx through a constant // instance of padicxx_ctx padic_ctx_t& _ctx() const {return ctx;} // XXX these two are not actually exposed in the C api ... fmpzxx_ref get_p() {return fmpzxx_ref::make(ctx[0].p);} fmpzxx_srcref get_p() const {return fmpzxx_srcref::make(ctx[0].p);} padic_print_mode mode() const {return _ctx()->mode;} padic_print_mode& mode() {return _ctx()->mode;} // TODO more constructors? Should we wrap padic_print_mode? padicxx_ctx(fmpzxx_srcref p, slong min, slong max, padic_print_mode mode) { padic_ctx_init(ctx, p._fmpz(), min, max, mode); } ~padicxx_ctx() {padic_ctx_clear(ctx);} }; class padicxx_ctx_srcref { private: mutable padic_ctx_struct* ctx; padicxx_ctx_srcref(padic_ctx_struct* c) : ctx(c) {} public: // NB: you must not modify user-visible state of ctx through a constant // instance of padicxx_ctx padic_ctx_struct* _ctx() const {return ctx;} // XXX these two are not actually exposed in the C api ... fmpzxx_ref get_p() {return fmpzxx_ref::make(ctx[0].p);} fmpzxx_srcref get_p() const {return fmpzxx_srcref::make(ctx[0].p);} padic_print_mode mode() const {return _ctx()->mode;} padicxx_ctx_srcref(padicxx_ctx& c) : ctx(c._ctx()) {} static padicxx_ctx_srcref make(padic_ctx_struct* c) {return padicxx_ctx_srcref(c);} }; namespace traits { template struct has_padicxx_ctx : mp::false_ { }; template struct is_padic_expr : has_padicxx_ctx::type> { }; } // traits namespace detail { struct has_padicxx_ctx_predicate { template struct type : traits::has_padicxx_ctx { }; }; template struct padicxx_max_prec; template struct padicxx_max_prec >::type> { static slong get(const T& p) {return p.prec();} }; template struct padicxx_max_prec >::type> { static slong get(const T&) {return 0;} }; template struct padicxx_max_prec_h; template struct padicxx_max_prec_h > { static slong get(const tuple& t) { slong p1 = padicxx_max_prec_h::get(t.tail); slong p2 = padicxx_max_prec::type>::get(t.head); return std::max(p1, p2); } }; template<> struct padicxx_max_prec_h { static slong get(empty_tuple) {return 0;} }; template struct padicxx_max_prec, mp::not_ > > >::type> { static slong get(const T& e) {return padicxx_max_prec_h::get(e._data());} }; } // detail namespace tools { template padicxx_ctx_srcref find_padicxx_ctx(const Expr& e) { return tools::find_subexpr(e).get_ctx(); } template slong padic_output_prec(const Expr& e) { return detail::padicxx_max_prec::get(e); } } // tools FLINT_DEFINE_UNOP(padicxx_unit) namespace detail { template struct padic_traits { typedef FLINT_UNOP_BUILD_RETTYPE(padicxx_unit, fmpzxx, Padic) unit_srcref_t; typedef slong prec_ref_t; typedef slong prec_srcref_t; typedef slong val_ref_t; typedef slong val_srcref_t; static slong prec(const Padic& p) {return tools::padic_output_prec(p);} static slong val(const Padic& p) {return padic_val(p.evaluate()._padic());} static unit_srcref_t unit(const Padic& p) {return padicxx_unit(p);} }; } //detail template class padicxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; FLINTXX_DEFINE_BASICS(padicxx_expression) FLINTXX_DEFINE_CTORS(padicxx_expression) FLINTXX_DEFINE_C_REF(padicxx_expression, padic_struct, _padic) public: typedef detail::padic_traits traits_t; // These only make sense with immediates void reduce() {padic_reduce(_padic(), _ctx());} void set_zero() {padic_zero(_padic());} void set_one() {padic_one(_padic());} #define PADICXX_DEFINE_CTX \ padicxx_ctx_srcref get_ctx() const {return this->_data().ctx;} \ padic_ctx_struct* _ctx() const {return get_ctx()._ctx();} PADICXX_DEFINE_CTX static padicxx_expression zero(padicxx_ctx_srcref ctx) {return padicxx_expression(ctx);} static padicxx_expression zero(padicxx_ctx_srcref ctx, slong N) {return padicxx_expression(ctx, N);} static padicxx_expression one(padicxx_ctx_srcref ctx) { padicxx_expression res(ctx); res.set_one(); return res; } static padicxx_expression one(padicxx_ctx_srcref ctx, slong N) { padicxx_expression res(ctx, N); res.set_one(); return res; } template static padicxx_expression from_QQ(const T& q, padicxx_ctx_srcref ctx, typename mp::enable_if, traits::is_fmpzxx, traits::is_integer > >::type* = 0) { padicxx_expression res(ctx); res = q; return res; } template static padicxx_expression from_QQ(const T& q, padicxx_ctx_srcref ctx, slong N, typename mp::enable_if, traits::is_fmpzxx, traits::is_integer > >::type* = 0) { padicxx_expression res(ctx, N); res = q; return res; } // TODO more? // The above method get_ctx() only works on immediates, i.e. instances of // padicxx. This next one here works on any composite expression which // contains at least one instance of padicxx. Returns the context of one of // those immediate subexpressions. #define PADICXX_DEFINE_ESTIMATE_CTX \ padicxx_ctx_srcref estimate_ctx() const \ { \ return tools::find_padicxx_ctx(*this); \ } PADICXX_DEFINE_ESTIMATE_CTX // Create a temporary. The context will be estimated, and the precision // will be the maximum of all subexpressions. evaluated_t create_temporary() const { return evaluated_t(estimate_ctx(), prec()); } // static methods which only make sense with padicxx static padicxx_expression randtest(frandxx& state, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) { padicxx_expression res(ctx, prec); padic_randtest(res._padic(), state._data(), ctx._ctx()); return res; } static padicxx_expression randtest_not_zero(frandxx& state, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) { padicxx_expression res(ctx, prec); padic_randtest_not_zero(res._padic(), state._data(), ctx._ctx()); return res; } static padicxx_expression randtest_int(frandxx& state, padicxx_ctx_srcref ctx, slong prec = PADIC_DEFAULT_PREC) { padicxx_expression res(ctx, prec); padic_randtest_int(res._padic(), state._data(), ctx._ctx()); return res; } #define PADICXX_DEFINE_TON \ typename flint_classes::to_srcref::type \ toN(slong N) const \ { \ return flint_classes::to_srcref::type::make( \ this->_data().inner, get_ctx(), N); \ } PADICXX_DEFINE_TON typename traits_t::unit_srcref_t unit() const {return traits_t::unit(*this);} // Compute the maximal precision of all subexpressions #define PADICXX_DEFINE_PREC \ typename traits_t::prec_ref_t prec() {return traits_t::prec(*this);} \ typename traits_t::prec_srcref_t prec() const \ {return traits_t::prec(*this);} PADICXX_DEFINE_PREC #define PADICXX_DEFINE_VAL \ typename traits_t::val_ref_t val() {return traits_t::val(*this);} \ typename traits_t::val_srcref_t val() const \ {return traits_t::val(*this);} PADICXX_DEFINE_VAL // these cause evaluation bool is_zero() const {return padic_is_zero(this->evaluate()._padic());} bool is_one() const {return padic_is_one(this->evaluate()._padic());} // forwarding of lazy functions FLINTXX_DEFINE_MEMBER_UNOP(exp) FLINTXX_DEFINE_MEMBER_UNOP(exp_balanced) FLINTXX_DEFINE_MEMBER_UNOP(exp_rectangular) FLINTXX_DEFINE_MEMBER_UNOP(inv) FLINTXX_DEFINE_MEMBER_UNOP(log) FLINTXX_DEFINE_MEMBER_UNOP(log_balanced) FLINTXX_DEFINE_MEMBER_UNOP(log_satoh) FLINTXX_DEFINE_MEMBER_UNOP(sqrt) FLINTXX_DEFINE_MEMBER_UNOP(teichmuller) FLINTXX_DEFINE_MEMBER_BINOP(pow) }; #define PADICXX_DEFINE_STD \ PADICXX_DEFINE_CTX \ PADICXX_DEFINE_ESTIMATE_CTX \ PADICXX_DEFINE_TON \ PADICXX_DEFINE_PREC \ PADICXX_DEFINE_VAL namespace detail { struct padic_data; } typedef padicxx_expression padicxx; typedef padicxx_expression > padicxx_ref; typedef padicxx_expression > padicxx_srcref; namespace traits { template<> struct has_padicxx_ctx : mp::true_ { }; template<> struct has_padicxx_ctx : mp::true_ { }; template<> struct has_padicxx_ctx : mp::true_ { }; template struct is_padicxx : flint_classes::is_Base { }; } // traits namespace detail { template<> struct padic_traits { typedef fmpzxx_srcref unit_srcref_t; template static fmpzxx_srcref unit(const Poly& p) {return fmpzxx_srcref::make(padic_unit(p._padic()));} typedef slong prec_ref_t; typedef slong prec_srcref_t; typedef slong val_ref_t; typedef slong val_srcref_t; template static slong prec(P p) {return p._data().N;} template static slong val(P p) {return padic_val(p._padic());} }; template<> struct padic_traits : padic_traits { typedef slong& prec_ref_t; typedef slong& val_ref_t; template static slong& prec(P& p) {return padic_prec(p._padic());} template static slong prec(const P& p) {return padic_prec(p._padic());} template static slong& val(P& p) {return padic_val(p._padic());} template static slong val(const P& p) {return padic_val(p._padic());} }; template<> struct padic_traits : padic_traits { }; template struct faketemplate : mp::enable_if > { }; } // detail // NB: usually, the "padicname" parameter would not be necessary. We would // leave that as a template, identifying the type by structname alone, and // conveniently delay all instantiations. Unfortunately qadic and padic_poly // have the same structname, so we cannot do this. // Instead we pass in the class name explicitly, and delay relevant functions // by hand... #define PADICXX_DEFINE_REF_STRUCTS_(padicname, structname, precname, ctxtype) \ namespace flint_classes { \ template<> \ struct ref_data \ { \ typedef void IS_REF_OR_CREF; \ typedef padicname wrapped_t; \ \ typedef structname* data_ref_t; \ typedef const structname* data_srcref_t; \ \ structname* inner; \ ctxtype ctx; \ \ template \ ref_data(T& o, typename detail::faketemplate::type* = 0) \ : inner(o._data().inner), ctx(o._data().ctx) {} \ \ static ref_data make(structname* f, ctxtype ctx) \ { \ return ref_data(f, ctx); \ } \ \ private: \ ref_data(structname* fp, ctxtype c) : inner(fp), ctx(c) {} \ }; \ \ template \ struct srcref_data \ { \ typedef void IS_REF_OR_CREF; \ typedef padicname wrapped_t; \ \ typedef const structname* data_ref_t; \ typedef const structname* data_srcref_t; \ \ const structname* inner; \ ctxtype ctx; \ slong N; \ \ template \ srcref_data(const T& o, \ typename detail::faketemplate::type* = 0) \ : inner(o._data().inner), ctx(o._data().ctx), N(o.prec()) {} \ template \ srcref_data(T o, typename detail::faketemplate::type* = 0) \ : inner(o._data().inner), ctx(o._data().ctx), N(o.prec()) {} \ \ static srcref_data make(const structname* f, ctxtype ctx) \ { \ return srcref_data(f, ctx); \ } \ static srcref_data make(const structname* f, ctxtype ctx, \ slong N) \ { \ return srcref_data(f, ctx, N); \ } \ \ private: \ srcref_data(const structname* fp, ctxtype c) \ : inner(fp), ctx(c), N(precname(fp)) {} \ srcref_data(const structname* fp, ctxtype c, slong n) \ : inner(fp), ctx(c), N(n) {} \ }; \ } /* flint_classes */ #define PADICXX_DEFINE_REF_STRUCTS(padicname, structname, precname) \ PADICXX_DEFINE_REF_STRUCTS_(padicname, structname, precname, padicxx_ctx_srcref) PADICXX_DEFINE_REF_STRUCTS(padicxx, padic_struct, padic_prec) namespace detail { struct padic_data { typedef padic_t& data_ref_t; typedef const padic_t& data_srcref_t; padicxx_ctx_srcref ctx; padic_t inner; padic_data(padicxx_ctx_srcref c) : ctx(c) { padic_init(inner); } padic_data(padicxx_ctx_srcref c, slong N) : ctx(c) { padic_init2(inner, N); } padic_data(const padic_data& o) : ctx(o.ctx) { padic_init2(inner, padic_prec(o.inner)); padic_set(inner, o.inner, ctx._ctx()); } ~padic_data() {padic_clear(inner);} padic_data(padicxx_srcref c) : ctx(c.get_ctx()) { padic_init2(inner, c.prec()); padic_set(inner, c._padic(), ctx._ctx()); } }; } // detail #define PADICXX_COND_S FLINTXX_COND_S(padicxx) #define PADICXX_COND_T FLINTXX_COND_T(padicxx) namespace rules { FLINT_DEFINE_DOIT_COND2(assignment, PADICXX_COND_T, PADICXX_COND_S, padic_set(to._padic(), from._padic(), to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, PADICXX_COND_T, traits::is_signed_integer, padic_set_si(to._padic(), from, to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, PADICXX_COND_T, traits::is_unsigned_integer, padic_set_ui(to._padic(), from, to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, PADICXX_COND_T, FMPZXX_COND_S, padic_set_fmpz(to._padic(), from._fmpz(), to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, PADICXX_COND_T, FMPQXX_COND_S, padic_set_fmpq(to._padic(), from._fmpq(), to._ctx())) FLINTXX_DEFINE_CONVERSION_TMP(fmpzxx, padicxx, padic_get_fmpz(to._fmpz(), from._padic(), from._ctx())) FLINTXX_DEFINE_CONVERSION_TMP(fmpqxx, padicxx, padic_get_fmpq(to._fmpq(), from._padic(), from._ctx())) FLINTXX_DEFINE_TO_STR(padicxx, padic_get_str(0, from._padic(), from._ctx())) FLINTXX_DEFINE_SWAP(padicxx, padic_swap(e1._padic(), e2._padic())) FLINTXX_DEFINE_EQUALS(padicxx, padic_equal(e1._padic(), e2._padic())) FLINT_DEFINE_UNARY_EXPR_COND(padicxx_unit_op, fmpzxx, PADICXX_COND_S, fmpz_set(to._fmpz(), padic_unit(from._padic()))) FLINT_DEFINE_PRINT_COND(PADICXX_COND_S, padic_fprint(to, from._padic(), from._ctx())) FLINT_DEFINE_CBINARY_EXPR_COND2(plus, padicxx, PADICXX_COND_S, PADICXX_COND_S, padic_add(to._padic(), e1._padic(), e2._padic(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, padicxx, PADICXX_COND_S, PADICXX_COND_S, padic_sub(to._padic(), e1._padic(), e2._padic(), to._ctx())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, padicxx, PADICXX_COND_S, PADICXX_COND_S, padic_mul(to._padic(), e1._padic(), e2._padic(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(divided_by, padicxx, PADICXX_COND_S, PADICXX_COND_S, padic_div(to._padic(), e1._padic(), e2._padic(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(shift, padicxx, PADICXX_COND_S, traits::fits_into_slong, padic_shift(to._padic(), e1._padic(), e2, to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(negate, padicxx, PADICXX_COND_S, padic_neg(to._padic(), from._padic(), to._ctx())) // lazy functions FLINT_DEFINE_UNARY_EXPR_COND(sqrt_op, padicxx, PADICXX_COND_S, execution_check( padic_sqrt(to._padic(), from._padic(), to._ctx()), "sqrt", "padic")) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, padicxx, PADICXX_COND_S, traits::fits_into_slong, padic_pow_si(to._padic(), e1._padic(), e2, to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(exp_op, padicxx, PADICXX_COND_S, execution_check( padic_exp(to._padic(), from._padic(), to._ctx()), "exp", "padic")) FLINT_DEFINE_UNARY_EXPR_COND(exp_balanced_op, padicxx, PADICXX_COND_S, execution_check(padic_exp_balanced( to._padic(), from._padic(), to._ctx()), "exp_balanced", "padic")) FLINT_DEFINE_UNARY_EXPR_COND(exp_rectangular_op, padicxx, PADICXX_COND_S, execution_check(padic_exp_rectangular( to._padic(), from._padic(), to._ctx()), "exp_rectangular", "padic")) FLINT_DEFINE_UNARY_EXPR_COND(log_op, padicxx, PADICXX_COND_S, execution_check( padic_log(to._padic(), from._padic(), to._ctx()), "log", "padic")) FLINT_DEFINE_UNARY_EXPR_COND(log_rectangular_op, padicxx, PADICXX_COND_S, execution_check(padic_log_rectangular( to._padic(), from._padic(), to._ctx()), "log_rectangular", "padic")) FLINT_DEFINE_UNARY_EXPR_COND(log_balanced_op, padicxx, PADICXX_COND_S, execution_check(padic_log_balanced( to._padic(), from._padic(), to._ctx()), "log_balanced", "padic")) FLINT_DEFINE_UNARY_EXPR_COND(log_satoh_op, padicxx, PADICXX_COND_S, execution_check(padic_log_satoh(to._padic(), from._padic(), to._ctx()), "log_satoh", "padic")) FLINT_DEFINE_UNARY_EXPR_COND(inv_op, padicxx, PADICXX_COND_S, padic_inv(to._padic(), from._padic(), to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(teichmuller_op, padicxx, PADICXX_COND_S, padic_teichmuller(to._padic(), from._padic(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(padic_val_fac_op, fmpzxx, FMPZXX_COND_S, FMPZXX_COND_S, ::padic_val_fac(to._fmpz(), e1._fmpz(), e2._fmpz())) } // rules // immediate version of padic_val_fac template inline typename mp::enable_if, traits::is_fmpzxx >, ulong>::type padic_val_fac(T n, const Fmpz& p) { return padic_val_fac_ui(n, p._fmpz()); } } // flint #endif flint2-2.8.4/perm.h000066400000000000000000000071271414523752600140570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef PERM_H #define PERM_H #ifdef PERM_INLINES_C #define PERM_INLINE FLINT_DLL #else #define PERM_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #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_printf("ERROR (_perm_init).\n\n"); flint_abort(); } 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_set_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_printf("ERROR (_perm_inv).\n\n"); flint_abort(); } 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 *************************************************************/ FLINT_DLL int _perm_randtest(slong * vec, slong n, flint_rand_t state); /* Parity ********************************************************************/ FLINT_DLL int _perm_parity(const slong * vec, slong n); /* Input and output **********************************************************/ PERM_INLINE int _long_vec_print(const slong * vec, slong len) { slong i; flint_printf("%wd", len); if (len > 0) { flint_printf(" "); for (i = 0; i < len; i++) flint_printf(" %wd", vec[i]); } return 1; } PERM_INLINE int _perm_print(const slong * vec, slong n) { slong i; flint_printf("%wd", n); if (n > 0) { flint_printf(" "); for (i = 0; i < n; i++) flint_printf(" %wd", vec[i]); } return 1; } #ifdef __cplusplus } #endif #endif flint2-2.8.4/perm/000077500000000000000000000000001414523752600136775ustar00rootroot00000000000000flint2-2.8.4/perm/inlines.c000066400000000000000000000010501414523752600155000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define PERM_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "perm.h" flint2-2.8.4/perm/parity.c000066400000000000000000000020151414523752600153510ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/perm/randtest.c000066400000000000000000000015071414523752600156720ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/perm/test/000077500000000000000000000000001414523752600146565ustar00rootroot00000000000000flint2-2.8.4/perm/test/t-compose.c000066400000000000000000000046041414523752600167340ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "perm.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("compose...."); fflush(stdout); /* 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)) { flint_printf("FAIL:\n"); flint_printf("a: "); _perm_print(a, n); flint_printf("\n\n"); flint_printf("b: "); _perm_print(b, n); flint_printf("\n\n"); flint_printf("binv: "); _perm_print(binv, n); flint_printf("\n\n"); flint_printf("c: "); _perm_print(c, n); flint_printf("\n\n"); abort(); } _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)) { flint_printf("FAIL:\n"); flint_printf("a: "); _perm_print(a, n); flint_printf("\n\n"); flint_printf("b: "); _perm_print(b, n); flint_printf("\n\n"); flint_printf("c: "); _perm_print(c, n); flint_printf("\n\n"); abort(); } _perm_clear(a); _perm_clear(b); _perm_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/perm/test/t-inv.c000066400000000000000000000037211414523752600160620ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "perm.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("inv...."); fflush(stdout); /* 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)) { flint_printf("FAIL:\n"); flint_printf("a: "); _perm_print(a, n); flint_printf("\n\n"); flint_printf("b: "); _perm_print(b, n); flint_printf("\n\n"); flint_printf("c: "); _perm_print(c, n); flint_printf("\n\n"); abort(); } _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)) { flint_printf("FAIL:\n"); flint_printf("a: "); _perm_print(a, n); flint_printf("\n\n"); flint_printf("b: "); _perm_print(b, n); flint_printf("\n\n"); abort(); } _perm_clear(a); _perm_clear(b); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/perm/test/t-parity.c000066400000000000000000000035271414523752600166020ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "perm.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("parity...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); flint_printf("a: "); _perm_print(a, n); flint_printf("\n\n"); flint_printf("b: "); _perm_print(b, n); flint_printf("\n\n"); flint_printf("c: "); _perm_print(c, n); flint_printf("\n\n"); flint_printf("ap = %d\n", ap); flint_printf("bp = %d\n", bp); flint_printf("cp = %d\n", cp); flint_printf("ap2 = %d\n", ap2); flint_printf("bp2 = %d\n", bp2); flint_printf("cp2 = %d\n", cp2); abort(); } _perm_clear(a); _perm_clear(b); _perm_clear(c); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/permxx.h000066400000000000000000000053671414523752600144430ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef PERMXX_H #define PERMXX_H #include "perm.h" #include "flintxx/frandxx.h" #include "flintxx/mp.h" namespace flint { class permxx { private: slong* data; slong sz; public: permxx(slong n) {data = _perm_init(n);sz = n;} ~permxx() {_perm_clear(data);} permxx(const permxx& o) { sz = o.size(); data = _perm_init(sz); _perm_set(data, o._data(), sz); } permxx& operator=(const permxx& o) { sz = o.size(); _perm_set(_data(), o._data(), sz); return *this; } bool operator==(const permxx& o) {return size() == o.size() && _perm_equal(_data(), o._data(), size());} bool operator!=(const permxx& o) {return !(*this == o);} static permxx one(slong n) {return permxx(n);} static permxx randtest(slong n, frandxx& state) {permxx res(n);res.set_randtest(state);return res;} void set_one() {_perm_set_one(_data(), size());} int set_randtest(frandxx& state) {return _perm_randtest(_data(), size(), state._data());} slong* _data() {return data;} const slong* _data() const {return data;} slong size() const {return sz;} slong& operator[](slong idx) {return data[idx];} slong operator[](slong idx) const {return data[idx];} int parity() const {return _perm_parity(_data(), size());} permxx operator*(const permxx& o) const { permxx res(o.size()); _perm_compose(res._data(), _data(), o._data(), size()); return res; } permxx& operator*=(const permxx& o) { _perm_compose(_data(), _data(), o._data(), size()); return *this; } void set_inv(const permxx& o) {_perm_inv(_data(), o._data(), o.size());} permxx inv() const {permxx res(size());res.set_inv(*this);return res;} }; inline permxx compose(const permxx& p1, const permxx& p2) {return p1*p2;} inline int parity(const permxx& p) {return p.parity();} inline permxx inv(const permxx& o) {return o.inv();} inline slong* maybe_perm_data(permxx* p) {return p ? p->_data() : 0;} inline slong* maybe_perm_data(int zero) {return 0;} namespace traits { template struct is_maybe_perm : mp::or_, mp::equal_types > { }; template struct is_permxx : mp::equal_types { }; } // traits inline int print(const permxx& p) { return _perm_print(p._data(), p.size()); } } // flint #endif flint2-2.8.4/printf.c000066400000000000000000000114161414523752600144050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } int flint_vprintf(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 = printf("%s", str2); len -= n; str += n; 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 += printf(WORD_WIDTH_FMT "x", width, wu); else ret += printf(WORD_FMT "x", wu); ret += printf("%s", str2 + 3); } else if (str[2] == 'u') { wu = (ulong) va_arg(ap, ulong); if (have_width) ret += printf(WORD_WIDTH_FMT "u", width, wu); else ret += printf(WORD_FMT "u", wu); ret += printf("%s", str2 + 3); } else if (str[2] == 'd') { w = (slong) va_arg(ap, slong); if (have_width) ret += printf(WORD_WIDTH_FMT "d", width, w); else ret += printf(WORD_FMT "d", w); ret += printf("%s", str2 + 3); } else { w = (slong) va_arg(ap, slong); if (have_width) ret += printf(WORD_WIDTH_FMT "d", width, w); else ret += printf(WORD_FMT "d", w); ret += printf("%s", str2 + 2); } break; case '%': /*Special Case to handle %%*/ ret += printf("%s",str2+1); 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 += printf(str2, w2, d); else if (args == 3) ret += printf(str2, w1, w2, d); else ret += printf(str2, d); } else { w3 = va_arg(ap, void *); if (args == 2) ret += printf(str2, w2, w3); else if (args == 3) ret += printf(str2, w1, w2, w3); else ret += printf(str2, w3); } } else ret += printf("%s", str2); /* zero args */ } len -= n; str += n; } flint_free(str2); return (int) ret; } int flint_printf(const char * str, ...) { va_list ap; int count; va_start(ap, str); count = flint_vprintf(str, ap); va_end(ap); return count; } flint2-2.8.4/profile/000077500000000000000000000000001414523752600143745ustar00rootroot00000000000000flint2-2.8.4/profile/p-invert_limb.c000066400000000000000000000040611414523752600173100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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)); FLINT_TEST_INIT(state); ulong i, ninv, sum = 0; slong j; algo_s * alg = (algo_s *) arg; 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++) { invert_limb(ninv, 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; } flint2-2.8.4/profile/p-udiv_qrnnd.c000066400000000000000000000027761414523752600171620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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)); FLINT_TEST_INIT(state); ulong i; int j; 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; } flint2-2.8.4/profile/p-udiv_qrnnd_preinv.c000066400000000000000000000031051414523752600205300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #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)); FLINT_TEST_INIT(state); ulong i; int j; d = n_randtest_not_zero(state); count_leading_zeros(norm, 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); } invert_limb(dinv, 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; } flint2-2.8.4/profile/timings.txt000066400000000000000000000002741414523752600166120ustar00rootroot00000000000000udiv_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 flint2-2.8.4/profiler.c000066400000000000000000000075441414523752600147340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/profiler.h000066400000000000000000000132731414523752600147350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef FLINT_PROFILER_H #define FLINT_PROFILER_H #include "flint.h" #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #if defined( _MSC_VER ) #include #include "gettimeofday.h" #pragma intrinsic( __rdtsc ) #else #include #endif #if defined (__WIN32) && !defined(__CYGWIN__) #ifdef __cplusplus FLINT_DLL 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 FLINT_DLL int gettimeofday(struct timeval * p, void * tz); #endif #elif !defined(_MSC_VER) #include #endif #undef ulong #define ulong mp_limb_t #ifdef __cplusplus extern "C" { #endif typedef struct { ulong size; ulong peak; ulong hwm; ulong rss; } meminfo_t[1]; FLINT_DLL 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; } /****************************************************************************** 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 extern double clock_last[FLINT_NUM_CLOCKS]; extern double clock_accum[FLINT_NUM_CLOCKS]; static __inline__ double get_cycle_counter() { #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() { 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() { start_clock(0); } static __inline__ void prof_stop() { stop_clock(0); } typedef void (*profile_target_t)(void* arg, ulong count); FLINT_DLL 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_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 flint2-2.8.4/qadic.h000066400000000000000000000313401414523752600141670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef QADIC_H #define QADIC_H #ifdef QADIC_INLINES_C #define QADIC_INLINE FLINT_DLL #else #define QADIC_INLINE static __inline__ #endif #undef ulong #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "fmpz.h" #include "fmpq.h" #include "fmpz_vec.h" #include "ulong_extras.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]; FLINT_DLL 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); FLINT_DLL 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_DLL 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)); } FLINT_DLL 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); } FLINT_DLL void qadic_mul(qadic_t x, const qadic_t y, const qadic_t z, const qadic_ctx_t ctx); FLINT_DLL void _qadic_inv(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N); FLINT_DLL void qadic_inv(qadic_t x, const qadic_t y, const qadic_ctx_t ctx); FLINT_DLL 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); FLINT_DLL void qadic_pow(qadic_t x, const qadic_t y, const fmpz_t e, const qadic_ctx_t ctx); /* Special functions *********************************************************/ FLINT_DLL 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); FLINT_DLL int qadic_exp_rectangular(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int qadic_exp_balanced(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int qadic_exp(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int qadic_log_rectangular(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int qadic_log_balanced(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); FLINT_DLL 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); FLINT_DLL int qadic_log(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); FLINT_DLL void _qadic_frobenius_a(fmpz *rop, slong exp, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N); FLINT_DLL 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); FLINT_DLL void qadic_frobenius(qadic_t rop, const qadic_t op, slong e, const qadic_ctx_t ctx); FLINT_DLL void _qadic_teichmuller(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N); FLINT_DLL void qadic_teichmuller(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); FLINT_DLL void _qadic_trace(fmpz_t rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t pN); FLINT_DLL void qadic_trace(padic_t rop, const qadic_t op, const qadic_ctx_t ctx); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL void qadic_norm(padic_t rop, const qadic_t op, const qadic_ctx_t ctx); FLINT_DLL void qadic_norm_analytic(padic_t rop, const qadic_t op, const qadic_ctx_t ctx); FLINT_DLL void qadic_norm_resultant(padic_t rop, const qadic_t op, const qadic_ctx_t ctx); FLINT_DLL int qadic_sqrt(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx); /* Output ********************************************************************/ FLINT_DLL int qadic_fprint_pretty(FILE *file, const qadic_t op, const qadic_ctx_t ctx); QADIC_INLINE int qadic_print_pretty(const qadic_t op, const qadic_ctx_t ctx) { return qadic_fprint_pretty(stdout, op, ctx); } QADIC_INLINE int qadic_debug(const qadic_t op) { return padic_poly_debug(op); } #ifdef __cplusplus } #endif #endif flint2-2.8.4/qadic/000077500000000000000000000000001414523752600140155ustar00rootroot00000000000000flint2-2.8.4/qadic/CPimport.txt000066400000000000000000032574571414523752600163420ustar00rootroot000000000000002 1 1 1 2 2 1 1 1 2 3 1 1 0 1 2 4 1 1 0 0 1 2 5 1 0 1 0 0 1 2 6 1 1 0 1 1 0 1 2 7 1 1 0 0 0 0 0 1 2 8 1 0 1 1 1 0 0 0 1 2 9 1 0 0 0 1 0 0 0 0 1 2 10 1 1 1 1 0 1 1 0 0 0 1 2 11 1 0 1 0 0 0 0 0 0 0 0 1 2 12 1 1 0 1 0 1 1 1 0 0 0 0 1 2 13 1 1 0 1 1 0 0 0 0 0 0 0 0 1 2 14 1 0 0 1 0 1 0 1 0 0 0 0 0 0 1 2 15 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0 1 2 16 1 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 1 2 17 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 18 1 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 2 19 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 20 1 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 1 2 21 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 22 1 0 0 0 0 1 1 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 2 23 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 24 1 0 0 1 0 1 0 1 0 1 1 0 0 1 1 1 1 0 0 0 0 0 0 0 1 2 25 1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 26 1 1 0 0 1 0 1 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 2 27 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 28 1 0 1 0 0 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 29 1 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 1 2 30 1 1 1 1 0 1 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 2 31 1 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 1 2 32 1 0 0 1 1 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 33 1 0 0 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 34 1 1 1 0 1 1 1 1 1 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 35 1 0 1 0 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 36 1 1 0 0 0 1 1 0 1 0 0 0 0 1 1 0 0 1 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 2 37 1 1 1 1 1 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 2 38 1 1 1 0 0 1 0 0 1 1 1 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 1 2 39 1 0 1 0 0 1 1 1 0 1 1 1 1 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 1 2 40 1 1 0 1 0 1 0 0 1 0 0 0 1 1 0 1 1 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 41 1 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 1 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 2 43 1 0 0 1 1 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 1 2 44 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 45 1 0 0 0 0 0 1 0 0 0 0 1 1 0 1 1 0 1 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 1 2 46 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 47 1 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 1 2 48 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 49 1 1 1 1 1 0 1 0 1 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 1 2 50 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 51 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 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 1 2 52 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 53 1 1 1 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 1 2 54 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 55 1 0 0 0 1 0 0 1 0 1 1 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 1 2 56 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 57 1 1 1 1 1 1 1 0 1 0 1 1 0 1 0 0 1 0 0 1 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 1 2 58 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 0 0 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 2 59 1 1 0 1 1 1 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 1 2 60 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 61 1 1 1 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 1 2 62 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 0 0 0 0 0 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 2 63 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 64 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 0 0 0 0 0 0 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 2 65 1 1 0 0 0 1 0 1 0 1 1 0 1 1 1 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 1 2 66 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 67 1 1 1 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 1 2 68 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 0 0 0 0 0 0 0 0 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 2 69 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 70 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 0 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 2 71 1 1 0 1 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 1 2 72 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 73 1 0 1 1 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 1 2 74 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 0 0 0 0 0 0 0 0 0 0 0 0 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 2 75 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 76 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 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 77 1 0 1 0 1 0 0 0 0 0 0 1 0 0 1 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 1 2 78 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 0 0 0 0 0 0 0 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 2 79 1 0 1 1 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 1 2 80 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 0 0 0 0 0 0 0 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 2 81 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 82 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 83 1 0 1 0 1 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 1 2 84 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 0 0 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 2 85 1 0 1 0 0 0 1 1 0 0 0 0 0 0 1 1 1 0 1 0 1 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 1 2 86 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 87 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 88 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 89 1 0 0 1 0 1 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 1 2 90 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 0 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 2 91 1 1 0 0 1 0 0 0 0 1 1 0 1 1 0 1 1 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 1 2 92 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 95 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 96 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 0 0 0 0 0 0 0 0 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 2 97 1 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 1 2 98 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 100 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 101 1 1 0 0 0 0 1 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 1 2 102 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 0 0 0 0 0 0 0 0 0 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 2 103 1 0 1 1 1 1 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 2 107 1 1 1 1 0 1 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 1 2 108 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 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 109 1 0 1 0 1 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 1 2 110 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 113 1 0 1 1 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 1 2 114 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 0 0 0 0 0 0 0 0 0 0 0 0 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 2 115 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 119 1 1 1 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 0 1 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 1 2 120 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 0 0 0 0 0 0 0 0 0 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 2 121 1 0 1 0 0 0 1 1 0 0 1 1 1 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 1 2 125 1 0 0 1 0 1 1 0 0 1 1 1 1 1 0 1 1 1 0 1 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 1 2 126 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 0 0 0 0 0 0 0 0 0 0 0 0 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 2 127 1 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 1 2 131 1 1 0 0 1 1 1 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 1 2 132 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 133 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 137 1 0 1 1 1 1 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 1 2 139 1 1 1 1 0 1 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 1 2 143 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 149 1 1 0 1 1 1 1 1 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 1 2 150 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 151 1 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 1 2 157 1 0 1 0 0 1 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 1 2 163 1 0 0 1 0 0 1 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 1 2 167 1 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 1 2 169 1 0 0 1 0 1 1 0 1 1 0 0 1 0 1 0 1 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 1 2 173 1 0 1 0 0 1 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 1 2 179 1 1 1 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 1 2 181 1 1 0 0 0 0 1 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 1 2 191 1 1 0 1 1 1 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 1 2 193 1 1 1 0 1 1 1 1 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 1 2 197 1 1 1 1 0 1 1 1 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 1 2 199 1 0 1 1 0 1 1 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 2 211 1 1 0 1 0 1 1 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 1 2 223 1 0 1 0 1 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 1 2 227 1 1 0 1 1 1 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 1 2 229 1 1 1 0 0 1 1 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 1 2 233 1 0 1 1 1 1 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 1 2 239 1 1 1 1 1 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 1 2 241 1 0 0 1 1 1 1 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 1 2 251 1 0 1 0 1 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 1 2 257 1 0 1 1 1 1 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 1 2 263 1 1 1 1 1 1 1 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 1 2 269 1 1 0 0 0 0 1 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 0 0 0 0 0 0 1 2 271 1 1 1 1 1 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 0 0 0 0 0 0 0 1 2 277 1 1 1 0 1 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 281 1 1 0 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 283 1 1 1 0 0 1 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 289 1 1 1 1 0 0 1 1 1 0 1 0 1 1 1 0 1 1 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 0 0 0 0 0 0 0 0 0 0 0 1 2 293 1 1 0 1 1 0 1 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 0 0 0 0 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 2 307 1 0 1 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 311 1 0 0 1 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 313 1 1 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 317 1 0 1 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 331 1 0 1 0 1 1 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 337 1 1 1 0 0 1 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 347 1 0 1 0 1 1 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 349 1 0 1 0 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 353 1 0 0 0 1 0 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 359 1 1 1 0 0 1 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 361 1 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 1 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 367 1 1 0 1 1 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 373 1 0 1 0 0 0 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 379 1 1 0 1 0 1 0 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 383 1 1 0 0 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 389 1 1 1 1 0 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 397 1 1 0 0 0 1 1 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 401 1 1 0 1 1 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 2 409 1 0 0 1 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 3 1 1 1 3 2 2 2 1 3 3 1 2 0 1 3 4 2 0 0 2 1 3 5 1 2 0 0 0 1 3 6 2 2 1 0 2 0 1 3 7 1 0 2 0 0 0 0 1 3 8 2 2 2 0 1 2 0 0 1 3 9 1 1 2 2 0 0 0 0 0 1 3 10 2 1 0 0 2 2 2 0 0 0 1 3 11 1 0 2 0 0 0 0 0 0 0 0 1 3 12 2 0 1 0 1 1 1 0 0 0 0 0 1 3 13 1 2 0 0 0 0 0 0 0 0 0 0 0 1 3 14 2 0 1 2 0 1 2 1 1 2 0 0 0 0 1 3 15 1 1 2 0 0 1 0 0 2 0 0 0 0 0 0 1 3 16 2 1 2 2 2 0 2 2 0 0 0 0 0 0 0 0 1 3 17 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 18 2 0 2 0 2 1 2 0 2 0 1 0 0 0 0 0 0 0 1 3 19 1 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 20 2 1 0 2 2 2 0 0 1 1 1 1 0 2 0 0 0 0 0 0 1 3 21 1 2 0 2 0 1 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 1 3 22 2 2 0 1 0 1 1 1 2 2 1 2 0 0 0 0 0 0 0 0 0 0 1 3 23 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 24 2 2 0 2 2 0 2 0 2 0 0 2 0 0 1 0 0 0 0 0 0 0 0 0 1 3 25 1 2 1 1 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 26 2 1 2 1 0 0 2 2 2 2 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 3 27 1 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 1 3 28 2 0 0 1 2 0 2 0 1 1 1 2 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 29 1 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 1 3 30 2 2 2 1 2 2 1 2 0 2 2 2 0 2 1 0 2 2 2 0 2 0 0 0 0 0 0 0 0 0 1 3 31 1 1 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 1 3 32 2 1 0 1 2 1 2 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 1 3 33 1 0 2 1 2 2 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 34 2 0 0 0 2 0 2 1 0 2 0 1 2 0 2 0 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 35 1 1 2 0 2 0 0 1 1 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 1 3 36 2 1 1 1 0 2 2 0 2 1 2 2 0 2 2 0 1 1 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 37 1 2 2 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 1 3 38 2 2 0 1 2 2 2 0 2 2 1 0 2 2 2 2 1 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 39 1 0 2 0 1 0 1 2 0 1 2 2 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 1 3 40 2 0 1 2 1 1 2 2 1 0 1 2 0 2 0 1 1 2 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 41 1 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 1 3 42 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 0 0 0 0 0 0 0 0 0 0 0 0 1 3 43 1 1 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 1 3 44 2 0 1 1 2 2 1 1 0 0 1 0 1 0 2 2 0 1 1 0 2 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 45 1 0 0 1 1 2 0 1 2 2 0 1 2 0 1 1 2 2 2 1 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 1 3 46 2 0 1 2 2 1 0 1 0 2 1 0 0 1 2 2 0 2 0 1 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 47 1 2 2 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 0 0 0 0 0 0 0 0 0 0 0 1 3 48 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 49 1 1 0 0 1 1 0 1 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 1 3 50 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 51 1 2 2 2 1 0 2 2 2 0 2 0 1 0 0 0 2 1 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 1 3 52 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 53 1 0 2 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 1 3 54 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 55 1 0 0 1 1 2 1 0 1 0 1 2 0 1 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 1 3 56 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 57 1 1 2 2 2 2 1 0 1 1 0 2 1 0 2 2 2 1 0 2 1 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 1 3 59 1 2 2 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 1 3 60 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 61 1 2 2 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 1 3 65 1 1 0 2 2 0 0 2 2 1 1 2 2 0 2 2 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 1 3 66 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 67 1 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 0 0 0 0 0 0 0 0 0 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 3 71 1 2 2 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 1 3 72 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 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 3 73 1 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 1 3 77 1 2 1 1 0 1 2 2 2 0 0 2 2 0 0 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 1 3 79 1 2 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 3 83 1 2 2 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 1 3 85 1 0 1 1 0 1 2 1 1 0 0 0 0 1 2 2 2 2 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 0 0 0 0 0 0 0 0 0 0 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 3 89 1 0 1 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 1 3 91 1 1 2 1 2 1 1 0 1 2 2 0 0 2 2 2 1 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 1 3 97 1 2 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 1 3 101 1 0 2 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 1 3 103 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 1 3 107 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 3 109 1 0 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 1 3 113 1 2 2 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 1 3 121 1 2 1 2 2 1 1 0 2 2 0 1 2 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 1 3 127 1 0 1 1 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 1 3 131 1 0 1 2 1 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 1 3 137 1 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 1 3 139 1 1 2 1 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 1 3 149 1 2 2 1 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 3 151 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 3 157 1 2 1 1 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 1 3 163 1 0 1 2 1 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 1 3 167 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 1 3 169 1 2 0 0 2 1 0 0 0 2 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 1 3 173 1 1 1 2 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 1 3 179 1 2 0 1 2 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 1 3 181 1 1 2 0 2 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 1 3 191 1 0 1 0 1 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 1 3 193 1 2 0 2 1 1 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 1 3 197 1 1 1 2 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 3 199 1 0 0 2 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 1 3 211 1 2 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 3 223 1 2 2 1 1 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 1 3 227 1 1 0 0 1 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 1 3 229 1 0 2 1 2 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 1 3 233 1 2 2 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 3 239 1 1 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 1 3 241 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 1 3 251 1 2 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 3 257 1 0 2 1 0 1 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 1 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 5 1 3 1 5 2 2 4 1 5 3 3 3 0 1 5 4 2 4 4 0 1 5 5 3 4 0 0 0 1 5 6 2 0 1 4 1 0 1 5 7 3 3 0 0 0 0 0 1 5 8 2 4 3 0 1 0 0 0 1 5 9 3 1 0 2 0 0 0 0 0 1 5 10 2 1 4 2 3 3 0 0 0 0 1 5 11 3 3 0 0 0 0 0 0 0 0 0 1 5 12 2 2 3 4 4 0 1 1 0 0 0 0 1 5 13 3 3 4 0 0 0 0 0 0 0 0 0 0 1 5 14 2 1 0 3 2 4 4 0 1 0 0 0 0 0 1 5 15 3 4 3 3 0 2 0 0 0 0 0 0 0 0 0 1 5 16 2 1 4 4 2 4 4 4 1 0 0 0 0 0 0 0 1 5 17 3 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 18 2 0 2 2 0 1 2 0 2 1 1 1 1 0 0 0 0 0 1 5 19 3 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 20 2 1 0 4 0 0 3 0 2 3 4 0 3 0 0 0 0 0 0 0 1 5 21 3 2 2 1 2 2 2 4 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 22 2 3 3 4 0 2 2 0 3 4 0 3 1 0 0 0 0 0 0 0 0 0 1 5 23 3 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 24 2 1 3 3 2 0 4 2 4 0 3 1 2 4 0 4 2 0 0 0 0 0 0 0 1 5 25 3 4 2 4 0 1 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 26 2 3 4 3 1 1 3 3 2 1 4 0 2 2 0 4 0 0 0 0 0 0 0 0 0 0 1 5 27 3 3 0 4 3 2 0 3 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 28 2 4 2 3 0 2 0 2 3 2 4 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 29 3 1 3 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 1 5 30 2 1 1 0 1 4 3 4 2 2 0 2 3 4 4 0 4 4 0 3 0 4 0 0 0 0 0 0 0 0 1 5 31 3 3 0 0 0 0 0 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 5 33 3 0 1 3 3 0 3 2 4 1 3 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 35 3 2 0 2 1 3 2 0 0 4 3 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 5 36 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 0 0 0 0 0 0 0 0 0 0 0 1 5 37 3 3 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 0 0 0 0 1 5 39 3 2 1 0 2 3 0 4 0 0 0 0 0 0 3 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 5 41 3 0 0 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 0 0 0 0 0 0 0 1 5 42 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 0 0 0 0 0 0 0 0 0 0 0 0 1 5 43 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 47 3 0 4 1 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 0 0 0 0 0 0 0 0 0 0 0 0 1 5 49 3 2 2 4 0 1 0 1 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 53 3 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 1 5 55 3 0 4 0 0 2 1 2 2 3 1 3 4 1 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 0 0 0 0 0 0 0 0 0 0 1 5 59 3 1 2 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 1 5 61 3 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 0 0 0 0 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 5 67 3 1 0 3 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 0 0 0 0 0 0 0 0 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 5 71 3 3 3 3 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 0 0 0 0 0 0 0 0 0 0 0 0 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 5 73 3 2 4 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 79 3 2 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 1 5 83 3 1 3 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 1 5 89 3 0 1 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 1 5 97 3 2 4 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 1 5 101 3 4 4 0 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 103 3 1 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 1 5 107 3 1 3 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 109 3 2 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 1 5 113 3 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 121 3 2 2 2 3 1 4 3 2 3 1 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 127 3 1 3 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 131 3 4 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 1 5 137 3 2 2 0 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 139 3 1 2 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 1 5 149 3 4 1 0 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 151 3 0 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 157 3 3 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 163 3 0 1 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 1 5 167 3 3 2 4 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 1 5 173 3 3 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 1 5 179 3 2 4 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 181 3 3 1 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 1 5 191 3 4 3 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 1 5 193 3 4 2 4 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 197 3 4 1 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 199 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 211 3 0 3 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 223 3 4 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 227 3 1 3 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 1 5 229 3 2 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 1 5 233 3 4 2 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 1 5 239 3 1 4 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 5 241 3 0 1 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 1 5 251 3 1 4 3 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 1 7 1 4 1 7 2 3 6 1 7 3 4 0 6 1 7 4 3 4 5 0 1 7 5 4 1 0 0 0 1 7 6 3 6 4 5 1 0 1 7 7 4 6 0 0 0 0 0 1 7 8 3 2 6 4 0 0 0 0 1 7 9 4 6 0 1 6 0 0 0 0 1 7 10 3 3 2 1 4 1 1 0 0 0 1 7 11 4 1 0 0 0 0 0 0 0 0 0 1 7 12 3 0 5 0 4 2 3 5 2 0 0 0 1 7 13 4 0 6 0 0 0 0 0 0 0 0 0 0 1 7 14 3 6 3 0 2 6 0 5 0 0 0 0 0 0 1 7 15 4 2 1 4 6 6 5 0 0 0 0 0 0 0 0 1 7 16 3 4 2 6 1 4 3 5 4 0 0 0 0 0 0 0 1 7 17 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7 18 3 2 6 0 0 3 1 5 6 1 6 2 1 0 0 0 0 0 1 7 19 4 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7 20 3 1 0 3 0 3 1 3 2 5 2 6 1 0 0 0 0 0 0 0 1 7 21 4 4 0 6 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7 22 3 4 5 5 6 4 3 2 5 3 5 6 1 0 0 0 0 0 0 0 0 0 1 7 23 4 4 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7 24 3 3 4 6 2 2 5 4 3 0 1 2 1 5 5 6 0 0 0 0 0 0 0 0 1 7 25 4 2 1 0 5 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7 26 3 5 5 0 2 0 1 4 6 1 6 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7 27 4 0 5 5 4 2 6 4 5 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7 28 3 1 0 5 1 3 6 4 2 2 6 2 6 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7 29 4 6 0 0 0 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 7 30 3 2 5 1 0 3 2 4 2 3 3 2 5 6 3 2 1 0 4 1 4 4 1 0 0 0 0 0 0 0 1 7 31 4 0 5 0 0 0 0 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 7 35 4 4 0 3 1 3 5 5 6 5 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7 36 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 0 0 0 0 0 0 0 0 0 0 0 1 7 37 4 6 0 0 0 0 0 0 0 0 0 0 0 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 7 41 4 1 4 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 1 7 42 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 0 0 0 0 0 0 0 0 0 0 0 0 1 7 43 4 2 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 47 4 3 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 7 49 4 1 2 1 5 4 3 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 53 4 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 59 4 3 6 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 1 7 61 4 5 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 67 4 4 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 71 4 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 73 4 2 6 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 79 4 2 5 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 1 7 83 4 6 6 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 1 7 89 4 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 1 7 97 4 5 6 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 1 7 101 4 4 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 103 4 1 1 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 1 7 107 4 4 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 109 4 1 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 113 4 5 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 127 4 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 131 4 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 137 4 2 3 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 139 4 4 6 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 1 7 149 4 1 6 2 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 151 4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 157 4 0 1 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 163 4 2 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 167 4 1 5 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 1 7 173 4 2 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 1 7 179 4 3 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 181 4 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 191 4 2 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 193 4 4 6 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 1 7 197 4 4 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 199 4 4 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 223 4 4 5 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 1 7 227 4 6 5 3 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 229 4 3 1 4 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 241 4 3 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 7 251 4 3 4 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 1 9 1 11 2 2 7 1 11 3 9 2 0 1 11 4 2 10 8 0 1 11 5 9 0 10 0 0 1 11 6 2 7 6 4 3 0 1 11 7 9 4 0 0 0 0 0 1 11 8 2 7 1 7 7 0 0 0 1 11 9 9 8 9 0 0 0 0 0 0 1 11 10 2 6 6 10 8 7 0 0 0 0 1 11 11 9 10 0 0 0 0 0 0 0 0 0 1 11 12 2 5 6 5 5 2 4 1 1 0 0 0 1 11 13 9 7 0 0 0 0 0 0 0 0 0 0 0 1 11 14 2 10 6 8 4 6 9 2 0 0 0 0 0 0 1 11 15 9 0 0 5 0 7 10 0 0 0 0 0 0 0 0 1 11 16 2 9 10 3 5 3 1 10 1 0 0 0 0 0 0 0 1 11 17 9 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 11 18 2 2 8 9 3 0 1 9 3 8 10 8 3 0 0 0 0 0 1 11 19 9 2 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 11 20 2 5 6 5 5 4 2 7 5 1 9 10 1 0 0 0 0 0 0 0 1 11 21 9 2 10 7 10 1 7 6 9 0 0 0 0 0 0 0 0 0 0 0 0 1 11 22 2 4 3 6 10 10 8 4 10 4 1 10 1 0 0 0 0 0 0 0 0 0 1 11 23 9 1 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 11 24 2 9 6 5 5 1 4 7 2 5 1 9 9 3 0 9 0 0 0 0 0 0 0 0 1 11 25 9 4 10 0 4 9 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 11 27 9 5 8 3 5 7 8 5 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 11 29 9 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 1 11 30 2 3 3 0 8 10 2 1 6 0 6 9 1 10 5 0 7 8 8 2 0 10 0 0 0 0 0 0 0 0 1 11 31 9 6 7 0 0 0 0 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 11 35 9 3 9 8 6 9 3 2 4 4 3 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 11 37 9 4 10 0 0 0 0 0 0 0 0 0 0 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 11 41 9 6 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 1 11 43 9 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 47 9 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 49 9 0 8 5 7 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 53 9 1 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 59 9 3 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 1 11 61 9 7 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 67 9 10 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 0 0 0 0 0 0 0 0 0 0 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 11 71 9 10 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 73 9 7 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 79 9 9 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 83 9 1 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 89 9 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 97 9 3 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 1 11 101 9 5 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 103 9 1 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 107 9 10 6 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 1 11 109 9 4 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 113 9 5 10 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 127 9 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 131 9 8 10 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 1 11 137 9 2 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 139 9 4 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 149 9 6 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 1 11 151 9 10 10 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 1 11 157 9 0 8 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 1 11 163 9 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 167 9 10 4 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 1 11 173 9 8 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 179 9 2 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 181 9 3 9 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 1 11 191 9 0 8 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 1 11 193 9 4 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 197 9 0 10 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 11 211 9 5 4 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 1 11 223 9 3 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 1 13 1 11 1 13 2 2 12 1 13 3 11 2 0 1 13 4 2 12 3 0 1 13 5 11 4 0 0 0 1 13 6 2 11 11 10 0 0 1 13 7 11 3 0 0 0 0 0 1 13 8 2 3 2 12 8 0 0 0 1 13 9 11 12 12 8 12 0 0 0 0 1 13 10 2 1 1 8 5 7 0 0 0 0 1 13 11 11 3 0 0 0 0 0 0 0 0 0 1 13 12 2 4 1 1 3 11 8 5 1 0 0 0 1 13 13 11 12 0 0 0 0 0 0 0 0 0 0 0 1 13 14 2 10 10 7 11 6 0 4 0 0 0 0 0 0 1 13 15 11 8 11 10 11 2 12 2 0 0 0 0 0 0 0 1 13 16 2 6 12 9 12 2 8 12 3 0 0 0 0 0 0 0 1 13 17 11 6 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 13 18 2 9 0 6 5 3 5 9 11 11 4 10 0 0 0 0 0 0 1 13 19 11 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 13 20 2 11 8 4 0 4 7 8 7 0 9 12 1 0 0 0 0 0 0 0 1 13 21 11 7 12 11 0 4 0 2 9 1 0 0 0 0 0 0 0 0 0 0 0 1 13 23 11 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 13 24 2 1 10 0 3 0 9 1 1 0 9 0 5 0 0 4 0 0 0 0 0 0 0 0 1 13 25 11 1 0 5 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 13 27 11 8 7 9 6 7 5 3 5 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 13 29 11 4 11 0 0 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 13 30 2 0 2 4 4 4 5 4 12 4 9 5 4 6 7 11 3 11 10 1 0 0 2 0 0 0 0 0 0 0 1 13 31 11 2 11 0 0 0 0 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 13 37 11 12 0 0 0 0 0 0 0 0 0 0 0 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 13 41 11 5 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 1 13 43 11 8 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 47 11 6 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 49 11 7 3 5 3 4 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 1 13 53 11 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 13 59 11 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 61 11 8 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 67 11 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 71 11 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 73 11 7 8 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 1 13 79 11 9 10 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 1 13 83 11 0 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 89 11 7 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 97 11 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 101 11 5 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 1 13 103 11 3 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 1 13 107 11 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 109 11 3 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 113 11 12 10 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 1 13 127 11 7 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 1 13 131 11 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 137 11 11 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 139 11 10 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 149 11 11 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 151 11 12 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 157 11 6 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 163 11 12 8 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 1 13 173 11 2 6 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 179 11 6 4 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 1 13 191 11 7 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 1 14 1 17 2 3 16 1 17 3 14 1 0 1 17 4 3 10 7 0 1 17 5 14 1 0 0 0 1 17 6 3 3 10 0 2 0 1 17 7 14 12 0 0 0 0 0 1 17 8 3 6 0 12 11 0 0 0 1 17 9 14 8 7 0 0 0 0 0 0 1 17 10 3 12 9 5 6 13 0 0 0 0 1 17 11 14 5 0 0 0 0 0 0 0 0 0 1 17 12 3 9 14 6 13 14 14 4 1 0 0 0 1 17 13 14 15 0 0 0 0 0 0 0 0 0 0 0 1 17 14 3 3 9 13 16 8 1 11 1 0 0 0 0 0 1 17 15 14 14 14 6 16 4 4 0 0 0 0 0 0 0 0 1 17 16 3 1 12 13 12 2 5 13 1 0 0 0 0 0 0 0 1 17 17 14 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 17 18 3 9 13 13 11 9 0 1 7 16 9 0 1 0 0 0 0 0 1 17 19 14 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 17 20 3 5 2 13 1 9 14 3 13 14 16 5 1 0 0 0 0 0 0 0 1 17 21 14 3 6 6 0 16 12 9 10 1 0 0 0 0 0 0 0 0 0 0 0 1 17 23 14 16 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 17 24 3 14 14 6 6 14 7 15 8 2 3 2 2 6 6 3 1 0 0 0 0 0 0 0 1 17 25 14 9 6 13 15 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 17 27 14 4 6 7 6 10 7 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 17 29 14 11 16 0 0 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 17 30 3 14 8 0 6 12 5 12 15 1 8 16 15 14 8 13 13 3 12 0 9 14 0 0 0 0 0 0 0 0 1 17 31 14 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 1 17 37 14 16 0 0 0 0 0 0 0 0 0 0 0 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 17 41 14 1 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 43 14 11 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 47 14 8 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 49 14 13 14 15 1 7 9 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 53 14 2 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 59 14 1 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 61 14 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 67 14 11 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 71 14 15 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 73 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 79 14 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 83 14 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 89 14 3 11 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 1 17 97 14 10 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 101 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 103 14 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 107 14 8 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 113 14 15 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 127 14 9 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 131 14 9 13 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 1 17 157 14 16 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 163 14 3 11 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 1 17 179 14 5 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 191 14 7 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 1 19 1 17 1 19 2 2 18 1 19 3 17 4 0 1 19 4 2 11 2 0 1 19 5 17 5 0 0 0 1 19 6 2 6 17 17 0 0 1 19 7 17 6 0 0 0 0 0 1 19 8 2 3 10 12 1 0 0 0 1 19 9 17 16 14 11 0 0 0 0 0 1 19 10 2 4 3 17 13 18 0 0 0 0 1 19 11 17 8 0 0 0 0 0 0 0 0 0 1 19 12 2 7 16 9 2 18 2 3 0 0 0 0 1 19 13 17 11 0 0 0 0 0 0 0 0 0 0 0 1 19 14 2 7 16 5 1 11 11 11 0 0 0 0 0 0 1 19 15 17 0 14 15 13 11 10 1 0 0 0 0 0 0 0 1 19 16 2 14 6 9 15 0 13 12 0 0 0 0 0 0 0 0 1 19 17 17 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 19 18 2 14 3 7 5 16 0 5 17 7 9 10 0 0 0 0 0 0 1 19 19 17 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 19 20 2 11 6 3 0 6 8 7 4 0 13 16 0 0 0 0 0 0 0 0 1 19 21 17 16 12 7 10 1 12 15 12 1 0 0 0 0 0 0 0 0 0 0 0 1 19 23 17 13 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 19 24 2 8 17 8 5 12 6 0 9 15 15 6 14 0 4 6 0 0 0 0 0 0 0 0 1 19 25 17 12 1 14 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 19 29 17 8 0 0 0 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 19 30 2 14 14 16 6 16 14 14 13 2 9 5 4 13 0 18 0 16 11 10 15 13 1 0 0 0 0 0 0 0 1 19 31 17 5 17 0 0 0 0 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 19 37 17 1 18 0 0 0 0 0 0 0 0 0 0 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 19 41 17 1 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 43 17 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 47 17 6 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 49 17 11 0 15 7 11 10 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 53 17 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 59 17 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 61 17 16 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 67 17 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 71 17 14 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 73 17 2 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 79 17 7 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 83 17 11 14 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 1 19 89 17 4 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 97 17 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 101 17 2 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 103 17 3 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 107 17 8 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 109 17 6 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 113 17 18 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 127 17 7 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 131 17 1 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 137 17 3 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 139 17 11 18 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 1 19 149 17 4 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 151 17 4 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 157 17 14 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 167 17 14 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 181 17 1 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 19 199 17 9 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 1 23 1 18 1 23 2 5 21 1 23 3 18 2 0 1 23 4 5 19 3 0 1 23 5 18 3 0 0 0 1 23 6 5 1 9 9 1 0 1 23 7 18 21 0 0 0 0 0 1 23 8 5 3 5 20 3 0 0 0 1 23 9 18 9 8 3 0 0 0 0 0 1 23 10 5 1 6 15 5 17 0 0 0 0 1 23 11 18 7 22 0 0 0 0 0 0 0 0 1 23 12 5 12 18 12 14 15 21 21 0 0 0 0 1 23 13 18 9 0 0 0 0 0 0 0 0 0 0 0 1 23 14 5 22 1 19 18 1 16 5 1 0 0 0 0 0 1 23 15 18 18 7 9 15 8 2 0 0 0 0 0 0 0 0 1 23 16 5 17 14 1 13 16 19 19 0 0 0 0 0 0 0 0 1 23 17 18 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 23 18 5 19 3 11 0 21 16 3 18 1 2 18 1 0 0 0 0 0 1 23 19 18 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 23 23 18 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 23 25 18 4 13 5 11 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 23 29 18 5 21 0 0 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 23 31 18 13 0 0 0 0 0 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 23 37 18 3 22 0 0 0 0 0 0 0 0 0 0 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 23 41 18 7 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 43 18 6 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 47 18 2 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 53 18 6 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 59 18 1 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 61 18 17 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 67 18 7 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 71 18 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 73 18 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 79 18 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 83 18 17 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 89 18 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 97 18 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 103 18 18 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 107 18 7 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 127 18 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 137 18 10 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 151 18 3 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 163 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 23 179 18 5 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 1 27 1 29 2 2 24 1 29 3 27 2 0 1 29 4 2 15 2 0 1 29 5 27 3 0 0 0 1 29 6 2 13 17 25 1 0 1 29 7 27 2 0 0 0 0 0 1 29 8 2 23 26 24 3 0 0 0 1 29 9 27 22 22 4 0 0 0 0 0 1 29 10 2 22 2 17 8 25 1 0 0 0 1 29 11 27 8 28 0 0 0 0 0 0 0 0 1 29 12 2 1 1 25 16 9 28 19 3 0 0 0 1 29 13 27 7 0 0 0 0 0 0 0 0 0 0 0 1 29 14 2 5 27 18 21 10 14 3 1 0 0 0 0 0 1 29 15 27 26 12 1 8 14 13 0 0 0 0 0 0 0 0 1 29 16 2 10 27 1 23 18 2 27 6 0 0 0 0 0 0 0 1 29 17 27 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 29 18 2 14 19 16 8 10 2 26 6 1 1 24 0 0 0 0 0 0 1 29 19 27 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 29 23 27 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 29 25 27 0 21 9 28 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 29 29 27 28 0 0 0 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 29 31 27 13 0 0 0 0 0 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 29 37 27 21 27 0 0 0 0 0 0 0 0 0 0 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 29 41 27 5 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 43 27 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 47 27 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 53 27 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 59 27 6 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 61 27 23 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 67 27 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 71 27 19 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 73 27 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 79 27 23 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 83 27 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 89 27 28 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 97 27 20 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 103 27 21 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 107 27 14 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 109 27 24 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 131 27 5 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 137 27 24 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 139 27 22 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 151 27 13 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 29 157 27 4 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 1 28 1 31 2 3 29 1 31 3 28 1 0 1 31 4 3 16 3 0 1 31 5 28 7 0 0 0 1 31 6 3 8 16 19 0 0 1 31 7 28 1 0 0 0 0 0 1 31 8 3 24 12 25 0 0 0 0 1 31 9 28 29 20 4 0 0 0 0 0 1 31 10 3 13 13 13 26 30 0 0 0 0 1 31 11 28 20 0 0 0 0 0 0 0 0 0 1 31 12 3 12 25 9 2 28 14 4 0 0 0 0 1 31 13 28 6 0 0 0 0 0 0 0 0 0 0 0 1 31 14 3 6 18 18 1 1 5 10 0 0 0 0 0 0 1 31 15 28 25 23 13 12 29 30 0 0 0 0 0 0 0 0 1 31 16 3 27 19 11 28 26 24 28 0 0 0 0 0 0 0 0 1 31 17 28 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 31 18 3 6 10 25 25 11 12 7 2 24 5 27 1 0 0 0 0 0 1 31 19 28 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 31 23 28 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 31 25 28 15 0 17 18 3 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 31 29 28 11 0 0 0 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 31 31 28 30 0 0 0 0 0 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 31 37 28 5 0 0 0 0 0 0 0 0 0 0 0 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 31 41 28 1 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 43 28 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 47 28 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 53 28 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 31 59 28 26 29 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 61 28 6 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 67 28 13 29 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 71 28 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 73 28 26 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 79 28 15 29 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 83 28 11 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 89 28 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 101 28 30 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 103 28 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 107 28 15 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 109 28 16 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 113 28 25 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 137 28 17 29 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 31 139 28 1 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 1 35 1 37 2 2 33 1 37 3 35 6 0 1 37 4 2 24 6 0 1 37 5 35 10 0 0 0 1 37 6 2 30 4 35 0 0 1 37 7 35 7 0 0 0 0 0 1 37 8 2 1 27 20 7 0 0 0 1 37 9 35 32 20 6 0 0 0 0 0 1 37 10 2 4 11 18 29 8 0 0 0 0 1 37 11 35 2 0 0 0 0 0 0 0 0 0 1 37 12 2 33 18 23 23 10 31 4 0 0 0 0 1 37 13 35 6 0 0 0 0 0 0 0 0 0 0 0 1 37 14 2 9 1 16 32 1 35 35 4 0 0 0 0 0 1 37 15 35 33 34 13 27 28 31 1 0 0 0 0 0 0 0 1 37 17 35 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 37 18 2 20 27 14 32 12 20 22 1 15 19 8 1 0 0 0 0 0 1 37 19 35 23 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 37 23 35 22 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 37 25 35 10 24 33 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 37 29 35 13 36 0 0 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 37 31 35 33 35 0 0 0 0 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 37 37 35 36 0 0 0 0 0 0 0 0 0 0 0 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 37 41 35 22 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 43 35 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 1 37 47 35 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 49 35 25 0 35 23 11 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 53 35 27 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 59 35 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 61 35 29 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 67 35 16 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 71 35 2 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 73 35 7 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 79 35 23 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 83 35 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 97 35 29 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 107 35 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 151 35 17 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 37 157 35 1 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 1 35 1 41 2 6 38 1 41 3 35 1 0 1 41 4 6 23 0 0 1 41 5 35 14 40 0 0 1 41 6 6 6 39 33 4 0 1 41 7 35 6 0 0 0 0 0 1 41 8 6 6 20 32 5 0 0 0 1 41 9 35 5 31 4 0 0 0 0 0 1 41 10 6 30 20 8 31 3 0 0 0 0 1 41 11 35 20 0 0 0 0 0 0 0 0 0 1 41 12 6 27 21 24 34 13 26 0 0 0 0 0 1 41 13 35 13 0 0 0 0 0 0 0 0 0 0 0 1 41 14 6 10 39 11 27 4 15 12 0 0 0 0 0 0 1 41 15 35 21 10 35 2 16 29 0 0 0 0 0 0 0 0 1 41 17 35 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 41 18 6 6 10 29 12 24 38 35 23 20 7 1 0 0 0 0 0 0 1 41 19 35 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 41 23 35 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 41 25 35 38 21 27 40 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 41 29 35 13 0 0 0 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 41 31 35 6 0 0 0 0 0 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 41 37 35 30 0 0 0 0 0 0 0 0 0 0 0 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 41 41 35 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 43 35 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 1 41 47 35 38 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 53 35 21 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 59 35 12 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 61 35 11 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 67 35 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 71 35 2 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 73 35 12 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 79 35 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 83 35 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 89 35 4 37 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 97 35 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 113 35 0 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 149 35 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 151 35 25 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 41 157 35 8 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 1 40 1 43 2 3 42 1 43 3 40 1 0 1 43 4 3 42 5 0 1 43 5 40 8 0 0 0 1 43 6 3 21 28 19 0 0 1 43 7 40 7 42 0 0 0 0 1 43 8 3 24 20 39 1 0 0 0 1 43 9 40 1 39 12 0 0 0 0 0 1 43 10 3 24 27 5 36 26 3 0 0 0 1 43 11 40 7 0 0 0 0 0 0 0 0 0 1 43 12 3 38 23 6 17 16 27 34 0 0 0 0 1 43 13 40 4 0 0 0 0 0 0 0 0 0 0 0 1 43 14 3 19 4 18 37 24 22 38 0 0 0 0 0 0 1 43 15 40 37 15 4 42 22 37 2 0 0 0 0 0 0 0 1 43 17 40 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 43 18 3 18 37 34 16 29 24 7 24 41 28 3 1 0 0 0 0 0 1 43 19 40 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 43 23 40 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 43 25 40 2 25 19 13 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 43 29 40 8 42 0 0 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 43 31 40 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 1 43 37 40 13 42 0 0 0 0 0 0 0 0 0 0 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 43 41 40 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 43 40 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 47 40 29 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 53 40 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 59 40 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 61 40 40 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 67 40 27 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 71 40 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 73 40 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 79 40 14 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 83 40 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 89 40 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 97 40 24 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 107 40 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 109 40 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 131 40 18 37 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 1 42 1 47 2 5 45 1 47 3 42 3 0 1 47 4 5 40 8 0 1 47 5 42 1 0 0 0 1 47 6 5 41 9 35 2 0 1 47 7 42 12 0 0 0 0 0 1 47 8 5 3 19 29 1 0 0 0 1 47 9 42 1 19 1 0 0 0 0 0 1 47 10 5 45 45 18 14 42 1 0 0 0 1 47 11 42 6 0 0 0 0 0 0 0 0 0 1 47 12 5 9 14 46 12 35 40 46 0 0 0 0 1 47 13 42 5 0 0 0 0 0 0 0 0 0 0 0 1 47 14 5 32 9 24 17 30 20 36 0 0 0 0 0 0 1 47 15 42 17 13 42 14 31 43 0 0 0 0 0 0 0 0 1 47 17 42 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 47 18 5 33 45 5 11 22 24 44 26 42 41 6 0 0 0 0 0 0 1 47 19 42 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 47 23 42 14 46 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 47 25 42 27 43 12 46 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 47 29 42 15 0 0 0 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 47 31 42 10 46 0 0 0 0 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 47 37 42 34 45 0 0 0 0 0 0 0 0 0 0 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 47 41 42 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 43 42 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 47 42 46 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 53 42 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 59 42 18 46 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 61 42 37 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 67 42 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 1 47 71 42 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 73 42 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 79 42 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 83 42 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 97 42 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 101 42 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 107 42 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 47 127 42 41 46 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 1 51 1 53 2 2 49 1 53 3 51 3 0 1 53 4 2 38 9 0 1 53 5 51 3 0 0 0 1 53 6 2 45 4 7 1 0 1 53 7 51 9 0 0 0 0 0 1 53 8 2 1 18 29 8 0 0 0 1 53 9 51 5 13 0 0 0 0 0 0 1 53 10 2 29 15 27 1 0 1 0 0 0 1 53 11 51 15 0 0 0 0 0 0 0 0 0 1 53 12 2 41 34 42 10 13 4 34 2 0 0 0 1 53 13 51 28 52 0 0 0 0 0 0 0 0 0 0 1 53 14 2 23 12 37 0 52 23 45 1 0 0 0 0 0 1 53 15 51 4 20 11 15 31 22 0 0 0 0 0 0 0 0 1 53 17 51 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 53 18 2 11 16 8 6 44 39 0 27 51 31 52 0 0 0 0 0 0 1 53 19 51 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 53 23 51 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 53 25 51 11 27 21 12 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 53 29 51 20 0 0 0 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 53 31 51 33 0 0 0 0 0 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 53 37 51 9 0 0 0 0 0 0 0 0 0 0 0 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 53 41 51 50 52 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 43 51 46 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 47 51 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 53 51 52 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 59 51 23 51 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 61 51 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 67 51 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 71 51 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 73 51 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 79 51 26 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 83 51 38 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 97 51 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 101 51 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 107 51 49 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 113 51 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 53 127 51 25 52 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 1 57 1 59 2 2 58 1 59 3 57 5 0 1 59 4 2 40 2 0 1 59 5 57 8 0 0 0 1 59 6 2 0 38 18 2 0 1 59 7 57 10 0 0 0 0 0 1 59 8 2 50 2 32 16 0 0 0 1 59 9 57 47 32 1 0 0 0 0 0 1 59 10 2 15 39 4 25 28 1 0 0 0 1 59 11 57 6 0 0 0 0 0 0 0 0 0 1 59 12 2 1 8 38 21 51 25 39 0 0 0 0 1 59 13 57 3 0 0 0 0 0 0 0 0 0 0 0 1 59 14 2 26 32 25 13 11 51 33 1 0 0 0 0 0 1 59 15 57 58 39 13 23 24 57 0 0 0 0 0 0 0 0 1 59 17 57 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 59 18 2 32 34 47 16 44 7 14 11 27 38 37 1 0 0 0 0 0 1 59 19 57 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 59 23 57 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 59 25 57 6 45 56 33 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 59 29 57 9 58 0 0 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 59 31 57 9 0 0 0 0 0 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 59 37 57 22 0 0 0 0 0 0 0 0 0 0 0 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 59 41 57 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 43 57 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 47 57 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 53 57 14 58 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 59 57 58 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 61 57 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 67 57 49 57 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 71 57 22 58 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 73 57 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 79 57 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 83 57 47 57 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 89 57 15 58 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 59 107 57 34 57 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 1 59 1 61 2 2 60 1 61 3 59 7 0 1 61 4 2 40 3 0 1 61 5 59 12 0 0 0 1 61 6 2 29 3 49 0 0 1 61 7 59 2 0 0 0 0 0 1 61 8 2 56 1 57 0 0 0 0 1 61 9 59 18 50 9 0 0 0 0 0 1 61 10 2 6 16 44 15 28 0 0 0 0 1 61 11 59 18 0 0 0 0 0 0 0 0 0 1 61 12 2 15 1 14 38 8 33 42 2 0 0 0 1 61 13 59 3 0 0 0 0 0 0 0 0 0 0 0 1 61 14 2 48 54 30 8 11 26 48 1 0 0 0 0 0 1 61 15 59 51 23 25 44 35 39 0 0 0 0 0 0 0 0 1 61 17 59 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 61 18 2 52 25 25 42 57 32 4 36 13 36 35 3 0 0 0 0 0 1 61 19 59 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 61 23 59 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 61 25 59 28 25 43 58 37 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 61 29 59 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 1 61 31 59 11 0 0 0 0 0 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 61 37 59 5 0 0 0 0 0 0 0 0 0 0 0 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 61 41 59 35 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 43 59 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 47 59 20 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 53 59 39 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 59 59 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 61 59 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 67 59 44 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 71 59 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 73 59 51 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 89 59 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 101 59 31 58 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 107 59 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 109 59 52 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 61 139 59 55 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 67 1 65 1 67 2 2 63 1 67 3 65 6 0 1 67 4 2 54 8 0 1 67 5 65 2 0 0 0 1 67 6 2 55 49 63 0 0 1 67 7 65 7 0 0 0 0 0 1 67 8 2 64 17 46 3 0 0 0 1 67 9 65 55 49 25 0 0 0 0 0 1 67 10 2 23 7 16 0 21 2 0 0 0 1 67 11 65 9 66 0 0 0 0 0 0 0 0 1 67 12 2 27 21 64 55 4 27 57 3 0 0 0 1 67 13 65 22 0 0 0 0 0 0 0 0 0 0 0 1 67 14 2 37 1 0 56 5 22 17 0 0 0 0 0 0 1 67 15 65 46 21 20 41 52 1 1 0 0 0 0 0 0 0 1 67 17 65 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 67 18 2 13 59 6 51 29 28 55 33 18 52 63 1 0 0 0 0 0 1 67 19 65 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 67 23 65 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 67 25 65 3 11 51 21 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 67 29 65 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 1 67 31 65 24 0 0 0 0 0 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 67 37 65 54 0 0 0 0 0 0 0 0 0 0 0 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 67 41 65 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 67 43 65 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 67 47 65 26 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 67 53 65 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 67 59 65 42 65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 67 61 65 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 67 67 65 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 67 71 65 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 67 73 65 23 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 67 79 65 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 67 89 65 47 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 67 103 65 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 1 64 1 71 2 7 69 1 71 3 64 4 0 1 71 4 7 41 4 0 1 71 5 64 18 0 0 0 1 71 6 7 29 13 10 1 0 1 71 7 64 2 0 0 0 0 0 1 71 8 7 19 22 53 0 0 0 0 1 71 9 64 62 43 4 0 0 0 0 0 1 71 10 7 40 1 26 17 53 0 0 0 0 1 71 11 64 48 0 0 0 0 0 0 0 0 0 1 71 12 7 23 58 21 55 29 28 12 0 0 0 0 1 71 13 64 27 0 0 0 0 0 0 0 0 0 0 0 1 71 15 64 49 67 52 18 32 28 0 0 0 0 0 0 0 0 1 71 17 64 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 71 19 64 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 71 23 64 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 71 25 64 7 30 65 69 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 71 29 64 19 0 0 0 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 71 31 64 21 0 0 0 0 0 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 71 37 64 35 0 0 0 0 0 0 0 0 0 0 0 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 71 41 64 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 43 64 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 47 64 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 53 64 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 71 59 64 50 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 61 64 24 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 67 64 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 1 71 71 64 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 73 64 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 79 64 33 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 83 64 26 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 97 64 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 107 64 48 65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 109 64 6 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 71 131 64 8 67 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 73 1 68 1 73 2 5 70 1 73 3 68 2 0 1 73 4 5 56 16 0 1 73 5 68 9 0 0 0 1 73 6 5 48 23 45 0 0 1 73 7 68 10 0 0 0 0 0 1 73 8 5 18 39 53 3 0 0 0 1 73 9 68 15 72 0 0 0 0 0 0 1 73 10 5 69 32 33 23 15 2 0 0 0 1 73 11 68 5 0 0 0 0 0 0 0 0 0 1 73 12 5 25 29 46 20 26 52 69 1 0 0 0 1 73 13 68 7 0 0 0 0 0 0 0 0 0 0 0 1 73 15 68 62 57 57 33 10 0 0 0 0 0 0 0 0 0 1 73 17 68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 73 19 68 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 73 23 68 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 73 25 68 46 20 21 27 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 73 29 68 3 0 0 0 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 73 31 68 10 0 0 0 0 0 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 73 37 68 11 0 0 0 0 0 0 0 0 0 0 0 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 73 41 68 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 73 43 68 22 71 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 73 47 68 1 71 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 73 53 68 53 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 73 59 68 59 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 73 61 68 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 73 67 68 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 73 71 68 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 73 73 68 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 73 89 68 63 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 73 101 68 40 67 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 73 107 68 64 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 1 76 1 79 2 3 78 1 79 3 76 9 0 1 79 4 3 66 2 0 1 79 5 76 5 0 0 0 1 79 6 3 68 28 19 0 0 1 79 7 76 4 0 0 0 0 0 1 79 8 3 48 59 60 0 0 0 0 1 79 9 76 19 57 0 0 0 0 0 0 1 79 10 3 42 30 1 51 44 4 0 0 0 1 79 11 76 3 0 0 0 0 0 0 0 0 0 1 79 12 3 62 59 40 7 52 45 29 1 0 0 0 1 79 13 76 4 78 0 0 0 0 0 0 0 0 0 0 1 79 17 76 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 79 19 76 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 79 23 76 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 79 25 76 68 67 7 42 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 79 29 76 11 0 0 0 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 79 31 76 52 78 0 0 0 0 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 79 37 76 44 0 0 0 0 0 0 0 0 0 0 0 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 79 41 76 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 43 76 13 78 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 47 76 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 53 76 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 59 76 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 61 76 48 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 67 76 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 71 76 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 73 76 49 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 79 76 78 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 83 76 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 89 76 10 76 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 79 109 76 59 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 1 81 1 83 2 2 82 1 83 3 81 3 0 1 83 4 2 42 4 0 1 83 5 81 9 0 0 0 1 83 6 2 17 32 76 1 0 1 83 7 81 3 0 0 0 0 0 1 83 8 2 42 23 65 1 0 0 0 1 83 9 81 18 24 1 0 0 0 0 0 1 83 10 2 53 0 73 0 7 0 0 0 0 1 83 11 81 17 0 0 0 0 0 0 0 0 0 1 83 12 2 75 55 65 19 31 12 35 0 0 0 0 1 83 13 81 15 0 0 0 0 0 0 0 0 0 0 0 1 83 17 81 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 83 19 81 47 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 83 23 81 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 83 25 81 74 17 3 11 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 83 29 81 9 0 0 0 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 83 31 81 38 0 0 0 0 0 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 83 37 81 32 0 0 0 0 0 0 0 0 0 0 0 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 83 41 81 18 82 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 43 81 44 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 47 81 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 53 81 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 83 59 81 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 61 81 63 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 67 81 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 71 81 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 73 81 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 83 81 82 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 89 81 64 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 97 81 80 82 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 103 81 58 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 83 113 81 21 82 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 1 86 1 89 2 3 82 1 89 3 86 3 0 1 89 4 3 72 4 0 1 89 5 86 1 0 0 0 1 89 6 3 15 80 82 1 0 1 89 7 86 7 0 0 0 0 0 1 89 8 3 79 40 65 0 0 0 0 1 89 9 86 6 12 5 0 0 0 0 0 1 89 10 3 4 52 82 33 16 1 0 0 0 1 89 11 86 26 88 0 0 0 0 0 0 0 0 1 89 12 3 52 70 8 51 44 15 85 2 0 0 0 1 89 13 86 17 0 0 0 0 0 0 0 0 0 0 0 1 89 17 86 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 89 19 86 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 89 23 86 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 89 25 86 18 44 40 84 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 89 29 86 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 1 89 31 86 24 0 0 0 0 0 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 89 37 86 7 88 0 0 0 0 0 0 0 0 0 0 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 89 41 86 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 43 86 71 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 47 86 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 53 86 14 88 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 59 86 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 61 86 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 67 86 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 71 86 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 73 86 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 79 86 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 89 86 88 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 101 86 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 107 86 79 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 109 86 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 89 113 86 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 1 92 1 97 2 5 96 1 97 3 92 9 0 1 97 4 5 80 6 0 1 97 5 92 3 0 0 0 1 97 6 5 88 58 92 0 0 1 97 7 92 5 0 0 0 0 0 1 97 8 5 32 1 65 0 0 0 0 1 97 9 92 7 59 12 0 0 0 0 0 1 97 10 5 20 34 34 66 22 0 0 0 0 1 97 11 92 5 0 0 0 0 0 0 0 0 0 1 97 12 5 94 78 86 0 81 59 30 0 0 0 0 1 97 13 92 3 0 0 0 0 0 0 0 0 0 0 0 1 97 17 92 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 97 19 92 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 97 23 92 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 97 25 92 10 73 85 11 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 97 29 92 22 0 0 0 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 97 31 92 59 0 0 0 0 0 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 97 37 92 28 0 0 0 0 0 0 0 0 0 0 0 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 97 41 92 94 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 43 92 0 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 47 92 66 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 53 92 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 59 92 14 95 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 61 92 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 67 92 7 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 71 92 7 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 73 92 79 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 79 92 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 97 92 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 113 92 93 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 97 127 92 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 101 1 99 1 101 2 2 97 1 101 3 99 3 0 1 101 4 2 78 1 0 1 101 5 99 2 0 0 0 1 101 6 2 67 20 90 2 0 1 101 7 99 6 0 0 0 0 0 1 101 8 2 24 29 76 4 0 0 0 1 101 9 99 47 64 0 0 0 0 0 0 1 101 10 2 52 100 100 49 67 1 0 0 0 1 101 11 99 31 0 0 0 0 0 0 0 0 0 1 101 12 2 21 84 48 78 39 64 79 1 0 0 0 1 101 13 99 7 0 0 0 0 0 0 0 0 0 0 0 1 101 17 99 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 101 19 99 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 101 23 99 38 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 101 25 99 55 72 95 79 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 101 29 99 12 0 0 0 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 101 31 99 63 0 0 0 0 0 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 101 37 99 66 0 0 0 0 0 0 0 0 0 0 0 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 101 41 99 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 101 43 99 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 101 47 99 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 103 1 98 1 103 2 5 102 1 103 3 98 2 0 1 103 4 5 88 2 0 1 103 5 98 11 0 0 0 1 103 6 5 30 9 96 0 0 1 103 7 98 5 0 0 0 0 0 1 103 8 5 49 71 70 1 0 0 0 1 103 9 98 51 97 0 0 0 0 0 0 1 103 10 5 11 94 101 86 101 1 0 0 0 1 103 11 98 5 0 0 0 0 0 0 0 0 0 1 103 12 5 88 29 81 20 94 23 74 1 0 0 0 1 103 13 98 5 0 0 0 0 0 0 0 0 0 0 0 1 103 17 98 8 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 103 19 98 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 103 23 98 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 103 25 98 58 7 39 21 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 103 29 98 101 0 0 0 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 103 31 98 16 0 0 0 0 0 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 103 37 98 9 0 0 0 0 0 0 0 0 0 0 0 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 103 41 98 74 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 103 43 98 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 103 47 98 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 107 1 105 1 107 2 2 103 1 107 3 105 5 0 1 107 4 2 79 13 0 1 107 5 105 8 0 0 0 1 107 6 2 79 22 52 1 0 1 107 7 105 16 0 0 0 0 0 1 107 8 2 95 24 105 2 0 0 0 1 107 9 105 66 3 3 0 0 0 0 0 1 107 10 2 95 83 83 61 94 2 0 0 0 1 107 11 105 8 0 0 0 0 0 0 0 0 0 1 107 12 2 57 42 61 0 6 48 37 0 0 0 0 1 107 13 105 4 0 0 0 0 0 0 0 0 0 0 0 1 107 17 105 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 107 19 105 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 107 23 105 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 107 25 105 15 101 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 107 29 105 45 0 0 0 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 107 31 105 9 0 0 0 0 0 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 107 37 105 10 0 0 0 0 0 0 0 0 0 0 0 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 107 41 105 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 107 43 105 29 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 107 47 105 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 109 1 103 1 109 2 6 108 1 109 3 103 1 0 1 109 4 6 98 11 0 1 109 5 103 4 0 0 0 1 109 6 6 66 102 107 0 0 1 109 7 103 14 0 0 0 0 0 1 109 8 6 86 34 102 1 0 0 0 1 109 9 103 87 93 0 0 0 0 0 0 1 109 10 6 69 75 16 55 71 1 0 0 0 1 109 11 103 11 0 0 0 0 0 0 0 0 0 1 109 12 6 28 103 65 8 37 53 50 1 0 0 0 1 109 13 103 1 0 0 0 0 0 0 0 0 0 0 0 1 109 17 103 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 109 19 103 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 109 23 103 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 109 25 103 9 94 61 83 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 109 29 103 43 0 0 0 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 109 31 103 9 0 0 0 0 0 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 109 37 103 66 0 0 0 0 0 0 0 0 0 0 0 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 109 41 103 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 109 43 103 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 109 47 103 52 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 113 1 110 1 113 2 3 101 1 113 3 110 8 0 1 113 4 3 62 0 0 1 113 5 110 7 0 0 0 1 113 6 3 71 30 59 1 0 1 113 7 110 5 0 0 0 0 0 1 113 8 3 28 38 98 3 0 0 0 1 113 9 110 71 87 0 0 0 0 0 0 1 113 10 3 56 83 45 57 108 0 0 0 0 1 113 11 110 3 0 0 0 0 0 0 0 0 0 1 113 12 3 27 10 56 98 4 62 23 1 0 0 0 1 113 13 110 4 0 0 0 0 0 0 0 0 0 0 0 1 113 17 110 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 113 19 110 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 113 23 110 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 113 25 110 73 76 59 53 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 113 29 110 52 0 0 0 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 113 31 110 11 0 0 0 0 0 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 113 37 110 9 0 0 0 0 0 0 0 0 0 0 0 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 113 41 110 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 113 43 110 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 113 47 110 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 127 1 124 1 127 2 3 126 1 127 3 124 3 0 1 127 4 3 97 2 0 1 127 5 124 7 0 0 0 1 127 6 3 82 115 84 0 0 1 127 7 124 15 0 0 0 0 0 1 127 8 3 8 55 104 3 0 0 0 1 127 9 124 126 119 14 0 0 0 0 0 1 127 10 3 4 60 95 64 107 0 0 0 0 1 127 11 124 11 0 0 0 0 0 0 0 0 0 1 127 12 3 8 99 15 97 33 25 119 0 0 0 0 1 127 13 124 8 0 0 0 0 0 0 0 0 0 0 0 1 127 17 124 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 127 19 124 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 127 23 124 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 127 25 124 82 71 50 33 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 127 29 124 15 0 0 0 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 127 31 124 13 0 0 0 0 0 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 127 37 124 73 0 0 0 0 0 0 0 0 0 0 0 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 127 41 124 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 0 0 0 0 0 0 0 0 0 1 127 43 124 54 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 127 47 124 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 131 1 129 1 131 2 2 127 1 131 3 129 3 0 1 131 4 2 109 9 0 1 131 5 129 19 0 0 0 1 131 6 2 22 4 66 2 0 1 131 7 129 10 0 0 0 0 0 1 131 8 2 104 116 72 3 0 0 0 1 131 9 129 19 6 6 0 0 0 0 0 1 131 10 2 44 126 9 97 124 0 0 0 0 1 131 11 129 6 0 0 0 0 0 0 0 0 0 1 131 12 2 103 28 125 83 40 122 50 0 0 0 0 1 131 13 129 9 0 0 0 0 0 0 0 0 0 0 0 1 131 17 129 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 131 19 129 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 131 23 129 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 131 25 129 109 130 96 129 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 131 29 129 15 0 0 0 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 131 31 129 19 0 0 0 0 0 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 131 37 129 11 0 0 0 0 0 0 0 0 0 0 0 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 131 41 129 90 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 131 43 129 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 131 47 129 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 137 1 134 1 137 2 3 131 1 137 3 134 6 0 1 137 4 3 95 1 0 1 137 5 134 7 0 0 0 1 137 6 3 3 102 116 1 0 1 137 7 134 1 0 0 0 0 0 1 137 8 3 34 21 105 4 0 0 0 1 137 9 134 122 80 1 0 0 0 0 0 1 137 10 3 119 93 67 20 0 2 0 0 0 1 137 11 134 1 0 0 0 0 0 0 0 0 0 1 137 12 3 61 135 36 12 40 40 61 1 0 0 0 1 137 13 134 14 0 0 0 0 0 0 0 0 0 0 0 1 137 17 134 4 136 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 137 19 134 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 137 23 134 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 137 25 134 130 29 88 129 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 137 29 134 57 0 0 0 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 137 31 134 38 0 0 0 0 0 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 137 37 134 21 0 0 0 0 0 0 0 0 0 0 0 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 137 41 134 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 137 43 134 53 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 137 47 134 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 139 1 137 1 139 2 2 138 1 139 3 137 6 0 1 139 4 2 96 7 0 1 139 5 137 10 0 0 0 1 139 6 2 118 10 46 4 0 1 139 7 137 9 0 0 0 0 0 1 139 8 2 21 36 103 4 0 0 0 1 139 9 137 87 70 3 0 0 0 0 0 1 139 10 2 106 66 130 48 110 0 0 0 0 1 139 11 137 7 0 0 0 0 0 0 0 0 0 1 139 12 2 10 8 106 77 41 75 120 0 0 0 0 1 139 13 137 22 0 0 0 0 0 0 0 0 0 0 0 1 139 17 137 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 139 19 137 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 139 23 137 12 138 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 139 25 137 70 100 35 105 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 139 29 137 32 0 0 0 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 139 31 137 9 0 0 0 0 0 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 139 37 137 12 0 0 0 0 0 0 0 0 0 0 0 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 139 41 137 58 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 139 43 137 75 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 139 47 137 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 149 1 147 1 149 2 2 145 1 149 3 147 3 0 1 149 4 2 107 7 0 1 149 5 147 2 0 0 0 1 149 6 2 55 33 105 1 0 1 149 7 147 19 0 0 0 0 0 1 149 8 2 123 25 140 2 0 0 0 1 149 9 147 20 146 0 0 0 0 0 0 1 149 10 2 51 143 148 42 74 0 0 0 0 1 149 11 147 33 0 0 0 0 0 0 0 0 0 1 149 12 2 110 104 9 52 91 121 0 0 0 0 0 1 149 13 147 4 0 0 0 0 0 0 0 0 0 0 0 1 149 17 147 29 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 149 19 147 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 149 23 147 65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 149 25 147 85 5 80 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 149 29 147 10 0 0 0 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 149 31 147 43 0 0 0 0 0 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 149 37 147 13 148 0 0 0 0 0 0 0 0 0 0 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 149 41 147 49 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 149 43 147 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 149 47 147 54 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 151 1 145 1 151 2 6 149 1 151 3 145 1 0 1 151 4 6 89 13 0 1 151 5 145 11 0 0 0 1 151 6 6 15 18 125 0 0 1 151 7 145 9 0 0 0 0 0 1 151 8 6 43 122 140 9 0 0 0 1 151 9 145 96 126 6 0 0 0 0 0 1 151 10 6 142 20 49 104 21 1 0 0 0 1 151 11 145 1 0 0 0 0 0 0 0 0 0 1 151 12 6 147 107 77 6 101 121 109 1 0 0 0 1 151 13 145 12 0 0 0 0 0 0 0 0 0 0 0 1 151 17 145 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 151 19 145 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 151 23 145 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 151 29 145 12 0 0 0 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 151 31 145 20 0 0 0 0 0 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 151 37 145 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 1 151 41 145 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 151 43 145 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 151 47 145 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 157 1 152 1 157 2 5 152 1 157 3 152 1 0 1 157 4 5 136 11 0 1 157 5 152 7 0 0 0 1 157 6 5 144 43 130 3 0 1 157 7 152 14 0 0 0 0 0 1 157 8 5 153 40 97 3 0 0 0 1 157 9 152 52 114 2 0 0 0 0 0 1 157 10 5 93 61 124 22 61 0 0 0 0 1 157 11 152 29 0 0 0 0 0 0 0 0 0 1 157 12 5 57 152 43 137 72 110 77 0 0 0 0 1 157 13 152 9 156 0 0 0 0 0 0 0 0 0 0 1 157 17 152 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 157 19 152 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 157 23 152 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 157 25 152 42 56 112 15 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 157 29 152 33 0 0 0 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 157 31 152 116 0 0 0 0 0 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 157 37 152 25 0 0 0 0 0 0 0 0 0 0 0 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 157 41 152 56 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 157 43 152 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 157 47 152 145 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 163 1 161 1 163 2 2 159 1 163 3 161 7 0 1 163 4 2 91 8 0 1 163 5 161 3 0 0 0 1 163 6 2 156 25 83 0 0 1 163 7 161 9 0 0 0 0 0 1 163 8 2 6 83 132 1 0 0 0 1 163 9 161 127 162 15 0 0 0 0 0 1 163 10 2 0 15 125 120 111 3 0 0 0 1 163 11 161 11 0 0 0 0 0 0 0 0 0 1 163 12 2 69 10 103 38 31 112 39 0 0 0 0 1 163 13 161 24 0 0 0 0 0 0 0 0 0 0 0 1 163 17 161 71 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 163 19 161 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 163 23 161 59 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 163 25 161 95 71 120 45 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 163 29 161 6 0 0 0 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 163 31 161 3 0 0 0 0 0 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 163 37 161 34 0 0 0 0 0 0 0 0 0 0 0 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 163 41 161 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 163 43 161 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 163 47 161 37 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 167 1 162 1 167 2 5 166 1 167 3 162 7 0 1 167 4 5 120 3 0 1 167 5 162 3 0 0 0 1 167 6 5 2 38 75 2 0 1 167 7 162 10 0 0 0 0 0 1 167 8 5 113 56 149 2 0 0 0 1 167 9 162 122 165 0 0 0 0 0 0 1 167 10 5 148 143 109 68 85 0 0 0 0 1 167 11 162 24 0 0 0 0 0 0 0 0 0 1 167 12 5 57 41 140 131 142 10 142 0 0 0 0 1 167 13 162 10 0 0 0 0 0 0 0 0 0 0 0 1 167 17 162 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 167 19 162 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 167 23 162 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 167 29 162 48 0 0 0 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 167 31 162 85 0 0 0 0 0 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 167 37 162 17 0 0 0 0 0 0 0 0 0 0 0 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 167 41 162 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 167 43 162 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 167 47 162 54 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 173 1 171 1 173 2 2 169 1 173 3 171 2 0 1 173 4 2 102 1 0 1 173 5 171 6 0 0 0 1 173 6 2 107 134 27 1 0 1 173 7 171 5 0 0 0 0 0 1 173 8 2 27 158 125 2 0 0 0 1 173 9 171 104 56 0 0 0 0 0 0 1 173 10 2 58 106 48 164 156 1 0 0 0 1 173 11 171 12 0 0 0 0 0 0 0 0 0 1 173 12 2 22 159 0 166 46 64 29 1 0 0 0 1 173 13 171 6 0 0 0 0 0 0 0 0 0 0 0 1 173 17 171 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 173 19 171 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 173 23 171 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 173 29 171 19 0 0 0 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 173 31 171 3 0 0 0 0 0 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 173 37 171 42 0 0 0 0 0 0 0 0 0 0 0 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 173 41 171 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 173 43 171 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 0 0 0 0 0 0 0 0 0 0 0 1 173 47 171 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 179 1 177 1 179 2 2 172 1 179 3 177 4 0 1 179 4 2 109 1 0 1 179 5 177 2 0 0 0 1 179 6 2 109 55 91 7 0 1 179 7 177 6 0 0 0 0 0 1 179 8 2 73 144 163 0 0 0 0 1 179 9 177 64 40 0 0 0 0 0 0 1 179 10 2 87 49 150 71 115 0 0 0 0 1 179 11 177 28 0 0 0 0 0 0 0 0 0 1 179 12 2 1 177 8 76 43 83 103 2 0 0 0 1 179 13 177 18 0 0 0 0 0 0 0 0 0 0 0 1 179 17 177 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 179 19 177 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 179 23 177 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 179 25 177 143 85 31 8 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 179 29 177 35 0 0 0 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 179 31 177 69 0 0 0 0 0 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 179 37 177 12 0 0 0 0 0 0 0 0 0 0 0 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 179 41 177 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 179 43 177 107 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 179 47 177 45 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 181 1 179 1 181 2 2 177 1 181 3 179 6 0 1 181 4 2 105 6 0 1 181 5 179 21 0 0 0 1 181 6 2 169 163 177 0 0 1 181 7 179 4 0 0 0 0 0 1 181 8 2 149 22 108 2 0 0 0 1 181 9 179 168 107 11 0 0 0 0 0 1 181 10 2 88 57 94 104 154 0 0 0 0 1 181 11 179 24 0 0 0 0 0 0 0 0 0 1 181 12 2 10 12 175 122 45 141 171 0 0 0 0 1 181 13 179 8 0 0 0 0 0 0 0 0 0 0 0 1 181 17 179 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 181 19 179 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 181 23 179 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 181 29 179 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 1 181 31 179 6 0 0 0 0 0 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 181 37 179 19 0 0 0 0 0 0 0 0 0 0 0 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 181 41 179 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 181 43 179 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 181 47 179 122 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 191 1 172 1 191 2 19 190 1 191 3 172 4 0 1 191 4 19 100 7 0 1 191 5 172 1 0 0 0 1 191 6 19 10 10 110 1 0 1 191 7 172 14 0 0 0 0 0 1 191 8 19 171 139 164 2 0 0 0 1 191 9 172 124 62 0 0 0 0 0 0 1 191 10 19 156 74 173 47 113 0 0 0 0 1 191 11 172 6 0 0 0 0 0 0 0 0 0 1 191 12 19 151 7 90 49 25 168 79 0 0 0 0 1 191 13 172 12 0 0 0 0 0 0 0 0 0 0 0 1 191 17 172 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 191 19 172 2 190 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 191 23 172 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 191 29 172 50 0 0 0 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 191 31 172 3 0 0 0 0 0 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 191 37 172 20 0 0 0 0 0 0 0 0 0 0 0 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 191 41 172 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 191 43 172 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 191 47 172 96 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 193 1 188 1 193 2 5 192 1 193 3 188 1 0 1 193 4 5 148 6 0 1 193 5 188 7 0 0 0 1 193 6 5 172 8 149 0 0 1 193 7 188 8 0 0 0 0 0 1 193 8 5 154 34 145 10 0 0 0 1 193 9 188 27 168 8 0 0 0 0 0 1 193 10 5 89 0 77 51 20 0 0 0 0 1 193 11 188 1 0 0 0 0 0 0 0 0 0 1 193 12 5 28 46 90 152 135 52 155 0 0 0 0 1 193 13 188 39 0 0 0 0 0 0 0 0 0 0 0 1 193 17 188 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 193 19 188 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 193 23 188 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 193 29 188 8 0 0 0 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 193 31 188 3 0 0 0 0 0 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 193 37 188 9 0 0 0 0 0 0 0 0 0 0 0 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 193 41 188 80 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 193 43 188 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 193 47 188 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 197 1 195 1 197 2 2 192 1 197 3 195 3 0 1 197 4 2 124 16 0 1 197 5 195 4 0 0 0 1 197 6 2 173 79 124 1 0 1 197 7 195 6 0 0 0 0 0 1 197 8 2 29 96 176 0 0 0 0 1 197 9 195 8 127 13 0 0 0 0 0 1 197 10 2 42 73 8 137 121 0 0 0 0 1 197 11 195 14 0 0 0 0 0 0 0 0 0 1 197 12 2 163 90 9 141 130 15 168 0 0 0 0 1 197 13 195 39 0 0 0 0 0 0 0 0 0 0 0 1 197 17 195 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 197 19 195 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 197 23 195 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 197 29 195 52 0 0 0 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 197 31 195 13 0 0 0 0 0 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 197 37 195 25 0 0 0 0 0 0 0 0 0 0 0 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 197 41 195 75 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 197 43 195 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 197 47 195 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 199 1 196 1 199 2 3 193 1 199 3 196 1 0 1 199 4 3 162 7 0 1 199 5 196 3 0 0 0 1 199 6 3 79 58 90 0 0 1 199 7 196 3 0 0 0 0 0 1 199 8 3 159 23 160 1 0 0 0 1 199 9 196 141 177 8 0 0 0 0 0 1 199 10 3 9 54 31 158 171 0 0 0 0 1 199 11 196 1 0 0 0 0 0 0 0 0 0 1 199 12 3 151 57 69 138 197 192 33 0 0 0 0 1 199 13 196 10 0 0 0 0 0 0 0 0 0 0 0 1 199 17 196 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 199 19 196 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 199 23 196 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 199 29 196 37 0 0 0 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 199 31 196 15 0 0 0 0 0 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 199 37 196 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 1 199 41 196 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 199 43 196 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 199 47 196 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 211 1 209 1 211 2 2 207 1 211 3 209 2 0 1 211 4 2 161 8 0 1 211 5 209 13 0 0 0 1 211 6 2 133 194 81 0 0 1 211 7 209 3 0 0 0 0 0 1 211 8 2 29 87 200 2 0 0 0 1 211 9 209 26 139 19 0 0 0 0 0 1 211 10 2 125 87 148 61 30 1 0 0 0 1 211 11 209 7 0 0 0 0 0 0 0 0 0 1 211 12 2 27 84 184 126 145 50 8 0 0 0 0 1 211 13 209 12 0 0 0 0 0 0 0 0 0 0 0 1 211 17 209 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 211 19 209 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 211 23 209 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 211 29 209 33 0 0 0 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 211 31 209 8 0 0 0 0 0 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 211 37 209 69 0 0 0 0 0 0 0 0 0 0 0 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 211 41 209 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 211 43 209 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 211 47 209 54 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 223 1 220 1 223 2 3 221 1 223 3 220 6 0 1 223 4 3 163 6 0 1 223 5 220 1 0 0 0 1 223 6 3 196 24 68 2 0 1 223 7 220 6 0 0 0 0 0 1 223 8 3 138 98 139 2 0 0 0 1 223 9 220 64 164 1 0 0 0 0 0 1 223 10 3 62 99 87 177 118 1 0 0 0 1 223 11 220 8 0 0 0 0 0 0 0 0 0 1 223 12 3 213 151 64 105 11 94 64 1 0 0 0 1 223 13 220 23 0 0 0 0 0 0 0 0 0 0 0 1 223 17 220 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 223 19 220 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 223 23 220 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 223 29 220 47 0 0 0 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 223 31 220 12 0 0 0 0 0 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 223 37 220 22 222 0 0 0 0 0 0 0 0 0 0 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 223 41 220 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 223 43 220 69 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 223 47 220 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 227 1 225 1 227 2 2 220 1 227 3 225 2 0 1 227 4 2 143 1 0 1 227 5 225 5 0 0 0 1 227 6 2 135 24 174 1 0 1 227 7 225 18 0 0 0 0 0 1 227 8 2 106 176 151 2 0 0 0 1 227 9 225 183 24 3 0 0 0 0 0 1 227 10 2 77 93 12 199 22 0 0 0 0 1 227 11 225 2 0 0 0 0 0 0 0 0 0 1 227 12 2 94 142 127 96 160 99 123 0 0 0 0 1 227 13 225 2 0 0 0 0 0 0 0 0 0 0 0 1 227 17 225 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 227 19 225 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 227 23 225 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 227 29 225 22 0 0 0 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 227 31 225 17 0 0 0 0 0 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 227 37 225 10 0 0 0 0 0 0 0 0 0 0 0 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 227 41 225 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 1 227 43 225 49 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 227 47 225 142 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 229 1 223 1 229 2 6 228 1 229 3 223 1 0 1 229 4 6 162 7 0 1 229 5 223 8 0 0 0 1 229 6 6 186 160 24 0 0 1 229 7 223 7 0 0 0 0 0 1 229 8 6 205 62 193 8 0 0 0 1 229 9 223 50 117 15 0 0 0 0 0 1 229 10 6 98 167 158 135 185 1 0 0 0 1 229 11 223 2 0 0 0 0 0 0 0 0 0 1 229 12 6 145 9 172 6 25 140 131 0 0 0 0 1 229 13 223 47 0 0 0 0 0 0 0 0 0 0 0 1 229 17 223 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 229 19 223 15 228 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 229 23 223 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 229 29 223 40 0 0 0 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 229 31 223 48 0 0 0 0 0 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 229 37 223 37 0 0 0 0 0 0 0 0 0 0 0 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 229 41 223 154 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 229 43 223 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 229 47 223 103 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 233 1 230 1 233 2 3 232 1 233 3 230 1 0 1 233 4 3 158 4 0 1 233 5 230 17 0 0 0 1 233 6 3 32 215 122 3 0 1 233 7 230 4 0 0 0 0 0 1 233 8 3 181 135 202 12 0 0 0 1 233 9 230 146 56 7 0 0 0 0 0 1 233 10 3 48 3 102 71 28 3 0 0 0 1 233 11 230 5 0 0 0 0 0 0 0 0 0 1 233 12 3 20 216 19 31 114 21 96 0 0 0 0 1 233 13 230 14 0 0 0 0 0 0 0 0 0 0 0 1 233 17 230 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 233 19 230 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 233 23 230 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 233 29 230 5 232 0 0 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 233 31 230 153 0 0 0 0 0 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 233 37 230 24 0 0 0 0 0 0 0 0 0 0 0 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 233 41 230 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 233 43 230 63 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 233 47 230 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 239 1 232 1 239 2 7 237 1 239 3 232 11 0 1 239 4 7 132 11 0 1 239 5 232 2 0 0 0 1 239 6 7 200 60 237 1 0 1 239 7 232 17 0 0 0 0 0 1 239 8 7 54 202 201 1 0 0 0 1 239 9 232 88 2 3 0 0 0 0 0 1 239 10 7 108 127 226 68 57 0 0 0 0 1 239 11 232 8 0 0 0 0 0 0 0 0 0 1 239 12 7 216 81 101 182 113 14 235 1 0 0 0 1 239 13 232 2 0 0 0 0 0 0 0 0 0 0 0 1 239 17 232 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 239 19 232 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 239 23 232 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 239 29 232 63 0 0 0 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 239 31 232 16 0 0 0 0 0 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 239 37 232 92 0 0 0 0 0 0 0 0 0 0 0 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 239 41 232 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 239 43 232 93 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 239 47 232 74 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 241 1 234 1 241 2 7 238 1 241 3 234 1 0 1 241 4 7 152 14 0 1 241 5 234 7 0 0 0 1 241 6 7 5 6 83 0 0 1 241 7 234 2 0 0 0 0 0 1 241 8 7 153 212 173 1 0 0 0 1 241 9 234 125 236 0 0 0 0 0 0 1 241 10 7 55 208 145 27 29 1 0 0 0 1 241 11 234 3 0 0 0 0 0 0 0 0 0 1 241 12 7 17 197 22 168 109 10 42 0 0 0 0 1 241 13 234 11 0 0 0 0 0 0 0 0 0 0 0 1 241 17 234 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 241 19 234 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 241 23 234 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 241 29 234 17 0 0 0 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 241 31 234 106 0 0 0 0 0 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 241 37 234 9 0 0 0 0 0 0 0 0 0 0 0 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 241 41 234 104 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 241 43 234 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 241 47 234 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 251 1 245 1 251 2 6 242 1 251 3 245 3 0 1 251 4 6 200 3 0 1 251 5 245 3 0 0 0 1 251 6 6 179 151 247 1 0 1 251 7 245 8 0 0 0 0 0 1 251 8 6 173 215 142 7 0 0 0 1 251 9 245 106 187 4 0 0 0 0 0 1 251 10 6 149 34 45 110 138 1 0 0 0 1 251 11 245 26 0 0 0 0 0 0 0 0 0 1 251 12 6 232 201 15 20 20 53 192 1 0 0 0 1 251 13 245 15 0 0 0 0 0 0 0 0 0 0 0 1 251 17 245 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 251 19 245 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 251 23 245 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 251 29 245 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 1 251 31 245 11 0 0 0 0 0 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 251 37 245 79 0 0 0 0 0 0 0 0 0 0 0 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 251 41 245 38 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 251 43 245 92 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 251 47 245 67 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 257 1 254 1 257 2 3 251 1 257 3 254 6 0 1 257 4 3 187 16 0 1 257 5 254 4 0 0 0 1 257 6 3 138 18 62 3 0 1 257 7 254 31 0 0 0 0 0 1 257 8 3 162 140 179 0 0 0 0 1 257 9 254 50 201 1 0 0 0 0 0 1 257 10 3 20 180 225 12 97 0 0 0 0 1 257 11 254 40 0 0 0 0 0 0 0 0 0 1 257 12 3 20 148 249 173 215 225 13 2 0 0 0 1 257 13 254 5 0 0 0 0 0 0 0 0 0 0 0 1 257 17 254 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 257 19 254 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 257 23 254 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 257 29 254 48 0 0 0 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 257 31 254 22 0 0 0 0 0 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 257 37 254 3 0 0 0 0 0 0 0 0 0 0 0 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 257 41 254 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 257 43 254 104 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 257 47 254 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 263 1 258 1 263 2 5 261 1 263 3 258 14 0 1 263 4 5 171 5 0 1 263 5 258 13 0 0 0 1 263 6 5 225 250 222 1 0 1 263 7 258 1 0 0 0 0 0 1 263 8 5 7 170 227 3 0 0 0 1 263 9 258 29 261 6 0 0 0 0 0 1 263 10 5 119 145 198 231 245 0 0 0 0 1 263 11 258 2 0 0 0 0 0 0 0 0 0 1 263 12 5 180 45 47 252 162 174 172 0 0 0 0 1 269 1 267 1 269 2 2 268 1 269 3 267 9 0 1 269 4 2 262 8 0 1 269 5 267 12 0 0 0 1 269 6 2 206 101 120 1 0 1 269 7 267 6 0 0 0 0 0 1 269 8 2 232 131 220 4 0 0 0 1 269 9 267 267 214 2 0 0 0 0 0 1 269 10 2 10 61 186 243 264 2 0 0 0 1 269 11 267 20 0 0 0 0 0 0 0 0 0 1 269 12 2 150 180 132 215 63 165 126 0 0 0 0 1 271 1 265 1 271 2 6 269 1 271 3 265 2 0 1 271 4 6 205 3 0 1 271 5 265 2 0 0 0 1 271 6 6 81 207 207 0 0 1 271 7 265 22 0 0 0 0 0 1 271 8 6 69 114 199 1 0 0 0 1 271 9 265 186 266 10 0 0 0 0 0 1 271 10 6 126 74 256 10 133 1 0 0 0 1 271 11 265 10 0 0 0 0 0 0 0 0 0 1 271 12 6 130 256 237 205 116 210 162 0 0 0 0 1 277 1 272 1 277 2 5 274 1 277 3 272 3 0 1 277 4 5 222 1 0 1 277 5 272 1 0 0 0 1 277 6 5 118 9 33 1 0 1 277 7 272 9 0 0 0 0 0 1 277 8 5 176 159 187 4 0 0 0 1 277 9 272 110 177 4 0 0 0 0 0 1 277 10 5 260 241 237 253 206 0 0 0 0 1 277 11 272 5 0 0 0 0 0 0 0 0 0 1 277 12 5 202 115 180 40 240 218 183 4 0 0 0 1 281 1 278 1 281 2 3 280 1 281 3 278 1 0 1 281 4 3 176 7 0 1 281 5 278 5 0 0 0 1 281 6 3 27 13 151 1 0 1 281 7 278 19 0 0 0 0 0 1 281 8 3 140 279 195 4 0 0 0 1 281 9 278 70 148 6 0 0 0 0 0 1 281 10 3 191 138 13 145 258 2 0 0 0 1 281 11 278 36 0 0 0 0 0 0 0 0 0 1 281 12 3 191 28 58 116 103 68 202 0 0 0 0 1 283 1 280 1 283 2 3 282 1 283 3 280 3 0 1 283 4 3 238 5 0 1 283 5 280 3 0 0 0 1 283 6 3 73 68 199 0 0 1 283 7 280 8 0 0 0 0 0 1 283 8 3 232 32 179 11 0 0 0 1 283 9 280 65 136 0 0 0 0 0 0 1 283 10 3 219 100 68 185 271 3 0 0 0 1 283 11 280 4 0 0 0 0 0 0 0 0 0 1 283 12 3 56 14 49 229 96 8 20 0 0 0 0 1 293 1 291 1 293 2 2 292 1 293 3 291 2 0 1 293 4 2 166 3 0 1 293 5 291 2 0 0 0 1 293 6 2 260 210 128 1 0 1 293 7 291 8 0 0 0 0 0 1 293 8 2 239 195 175 29 0 0 0 1 293 9 291 190 208 0 0 0 0 0 0 1 293 10 2 24 184 46 28 186 0 0 0 0 1 293 11 291 3 0 0 0 0 0 0 0 0 0 1 293 12 2 157 144 167 212 125 210 159 0 0 0 0 1 307 1 302 1 307 2 5 306 1 307 3 302 7 0 1 307 4 5 239 2 0 1 307 5 302 5 0 0 0 1 307 6 5 61 172 213 0 0 1 307 7 302 6 0 0 0 0 0 1 307 8 5 131 232 283 0 0 0 0 1 307 9 302 70 165 1 0 0 0 0 0 1 311 1 294 1 311 2 17 310 1 311 3 294 3 0 1 311 4 17 163 3 0 1 311 5 294 1 0 0 0 1 311 6 17 152 167 27 1 0 1 311 7 294 10 0 0 0 0 0 1 311 8 17 2 118 162 19 0 0 0 1 311 9 294 74 287 1 0 0 0 0 0 1 313 1 303 1 313 2 10 310 1 313 3 303 2 0 1 313 4 10 239 8 0 1 313 5 303 7 0 0 0 1 313 6 10 253 213 196 0 0 1 313 7 303 4 0 0 0 0 0 1 313 8 10 106 99 306 8 0 0 0 1 313 9 303 300 267 8 0 0 0 0 0 1 317 1 315 1 317 2 2 313 1 317 3 315 7 0 1 317 4 2 178 6 0 1 317 5 315 2 0 0 0 1 317 6 2 4 156 195 2 0 1 317 7 315 7 0 0 0 0 0 1 317 8 2 31 85 207 1 0 0 0 1 317 9 315 296 284 0 0 0 0 0 0 1 331 1 328 1 331 2 3 326 1 331 3 328 1 0 1 331 4 3 290 3 0 1 331 5 328 4 0 0 0 1 331 6 3 159 205 283 1 0 1 331 7 328 5 0 0 0 0 0 1 331 8 3 78 308 249 1 0 0 0 1 331 9 328 210 194 0 0 0 0 0 0 1 337 1 327 1 337 2 10 332 1 337 3 327 2 0 1 337 4 10 224 25 0 1 337 5 327 2 0 0 0 1 337 6 10 109 127 216 0 0 1 337 7 327 5 0 0 0 0 0 1 337 8 10 251 246 331 0 0 0 0 1 337 9 327 98 148 12 0 0 0 0 0 1 347 1 345 1 347 2 2 343 1 347 3 345 9 0 1 347 4 2 295 13 0 1 347 5 345 3 0 0 0 1 347 6 2 56 26 343 3 0 1 347 7 345 4 0 0 0 0 0 1 347 8 2 117 213 187 1 0 0 0 1 347 9 345 252 235 2 0 0 0 0 0 1 349 1 347 1 349 2 2 348 1 349 3 347 4 0 1 349 4 2 279 3 0 1 349 5 347 2 0 0 0 1 349 6 2 316 177 135 0 0 1 349 7 347 10 0 0 0 0 0 1 349 8 2 268 328 308 0 0 0 0 1 349 9 347 130 290 36 0 0 0 0 0 1 353 1 350 1 353 2 3 348 1 353 3 350 3 0 1 353 4 3 199 0 0 1 353 5 350 1 0 0 0 1 353 6 3 295 226 215 1 0 1 353 7 350 16 0 0 0 0 0 1 353 8 3 37 26 182 1 0 0 0 1 353 9 350 49 319 2 0 0 0 0 0 1 359 1 352 1 359 2 7 358 1 359 3 352 3 0 1 359 4 7 229 2 0 1 359 5 352 1 0 0 0 1 359 6 7 327 327 309 4 0 1 359 7 352 1 0 0 0 0 0 1 359 8 7 271 143 301 0 0 0 0 1 359 9 352 165 356 0 0 0 0 0 0 1 367 1 361 1 367 2 6 366 1 367 3 361 10 0 1 367 4 6 295 3 0 1 367 5 361 3 0 0 0 1 367 6 6 324 321 222 0 0 1 367 7 361 13 0 0 0 0 0 1 367 8 6 50 282 335 2 0 0 0 1 367 9 361 268 213 15 0 0 0 0 0 1 373 1 371 1 373 2 2 369 1 373 3 371 5 0 1 373 4 2 304 15 0 1 373 5 371 2 0 0 0 1 373 6 2 108 83 126 0 0 1 373 7 371 7 0 0 0 0 0 1 373 8 2 66 219 203 0 0 0 0 1 373 9 371 370 238 14 0 0 0 0 0 1 379 1 377 1 379 2 2 374 1 379 3 377 5 0 1 379 4 2 327 2 0 1 379 5 377 4 0 0 0 1 379 6 2 246 364 374 0 0 1 379 7 377 14 0 0 0 0 0 1 379 8 2 173 194 210 13 0 0 0 1 379 9 377 369 362 11 0 0 0 0 0 1 383 1 378 1 383 2 5 382 1 383 3 378 1 0 1 383 4 5 309 7 0 1 383 5 378 1 0 0 0 1 383 6 5 158 8 69 1 0 1 383 7 378 6 0 0 0 0 0 1 383 8 5 296 332 281 10 0 0 0 1 383 9 378 76 137 2 0 0 0 0 0 1 389 1 387 1 389 2 2 379 1 389 3 387 2 0 1 389 4 2 266 2 0 1 389 5 387 4 0 0 0 1 389 6 2 255 339 218 1 0 1 389 7 387 24 0 0 0 0 0 1 389 8 2 290 19 351 0 0 0 0 1 389 9 387 308 258 2 0 0 0 0 0 1 397 1 392 1 397 2 5 392 1 397 3 392 2 0 1 397 4 5 363 12 0 1 397 5 392 7 0 0 0 1 397 6 5 287 274 382 0 0 1 397 7 392 12 0 0 0 0 0 1 397 8 5 203 255 375 1 0 0 0 1 397 9 392 252 166 6 0 0 0 0 0 1 401 1 398 1 401 2 3 396 1 401 3 398 3 0 1 401 4 3 372 2 0 1 401 5 398 4 0 0 0 1 401 6 3 51 81 115 4 0 1 401 7 398 5 0 0 0 0 0 1 401 8 3 164 113 380 0 0 0 0 1 401 9 398 158 199 1 0 0 0 0 0 1 409 1 388 1 409 2 21 404 1 409 3 388 3 0 1 409 4 21 407 12 0 1 409 5 388 5 0 0 0 1 409 6 21 364 53 372 0 0 1 409 7 388 7 0 0 0 0 0 1 409 8 21 396 69 256 3 0 0 0 1 409 9 388 211 318 8 0 0 0 0 0 1 419 1 417 1 419 2 2 418 1 419 3 417 11 0 1 419 4 2 373 4 0 1 419 5 417 4 0 0 0 1 419 6 2 257 33 411 2 0 1 419 7 417 4 0 0 0 0 0 1 419 8 2 151 388 234 8 0 0 0 1 419 9 417 386 93 0 0 0 0 0 0 1 421 1 419 1 421 2 2 417 1 421 3 419 2 0 1 421 4 2 257 10 0 1 421 5 419 15 0 0 0 1 421 6 2 41 342 111 0 0 1 421 7 419 21 0 0 0 0 0 1 421 8 2 77 32 389 5 0 0 0 1 421 9 419 145 394 18 0 0 0 0 0 1 431 1 424 1 431 2 7 430 1 431 3 424 2 0 1 431 4 7 323 2 0 1 431 5 424 7 0 0 0 1 431 6 7 182 202 161 4 0 1 431 7 424 1 0 0 0 0 0 1 431 8 7 115 286 243 5 0 0 0 1 431 9 424 329 71 2 0 0 0 0 0 1 433 1 428 1 433 2 5 432 1 433 3 428 1 0 1 433 4 5 402 6 0 1 433 5 428 5 0 0 0 1 433 6 5 360 353 244 0 0 1 433 7 428 6 0 0 0 0 0 1 433 8 5 39 32 347 10 0 0 0 1 433 9 428 45 232 27 0 0 0 0 0 1 439 1 424 1 439 2 15 436 1 439 3 424 3 0 1 439 4 15 323 0 0 1 439 5 424 1 0 0 0 1 439 6 15 190 324 1 0 0 1 439 7 424 1 0 0 0 0 0 1 439 8 15 266 296 359 0 0 0 0 1 439 9 424 254 342 16 0 0 0 0 0 1 443 1 441 1 443 2 2 437 1 443 3 441 4 0 1 443 4 2 383 4 0 1 443 5 441 4 0 0 0 1 443 6 2 41 218 298 1 0 1 443 7 441 6 0 0 0 0 0 1 443 8 2 290 217 437 2 0 0 0 1 443 9 441 109 125 3 0 0 0 0 0 1 449 1 446 1 449 2 3 444 1 449 3 446 1 0 1 449 4 3 249 2 0 1 449 5 446 9 0 0 0 1 449 6 3 69 293 437 2 0 1 449 7 446 28 0 0 0 0 0 1 449 8 3 124 348 361 0 0 0 0 1 449 9 446 9 226 6 0 0 0 0 0 1 457 1 444 1 457 2 13 454 1 457 3 444 1 0 1 457 4 13 407 8 0 1 457 5 444 4 0 0 0 1 457 6 13 266 389 205 0 0 1 457 7 444 14 0 0 0 0 0 1 457 8 13 412 296 365 9 0 0 0 1 457 9 444 84 354 9 0 0 0 0 0 1 461 1 459 1 461 2 2 460 1 461 3 459 3 0 1 461 4 2 393 3 0 1 461 5 459 14 0 0 0 1 461 6 2 329 432 439 1 0 1 461 7 459 5 0 0 0 0 0 1 461 8 2 321 449 388 15 0 0 0 1 461 9 459 276 210 5 0 0 0 0 0 1 463 1 460 1 463 2 3 461 1 463 3 460 10 0 1 463 4 3 262 17 0 1 463 5 460 3 0 0 0 1 463 6 3 110 51 462 0 0 1 463 7 460 13 0 0 0 0 0 1 463 8 3 396 414 234 0 0 0 0 1 463 9 460 227 433 3 0 0 0 0 0 1 467 1 465 1 467 2 2 463 1 467 3 465 2 0 1 467 4 2 353 14 0 1 467 5 465 2 0 0 0 1 467 6 2 237 62 123 1 0 1 467 7 465 7 0 0 0 0 0 1 467 8 2 289 413 318 5 0 0 0 1 467 9 465 447 397 0 0 0 0 0 0 1 479 1 466 1 479 2 13 474 1 479 3 466 4 0 1 479 4 13 386 6 0 1 479 5 466 2 0 0 0 1 479 6 13 334 287 243 1 0 1 479 7 466 4 0 0 0 0 0 1 479 8 13 17 440 247 7 0 0 0 1 479 9 466 185 3 2 0 0 0 0 0 1 487 1 484 1 487 2 3 485 1 487 3 484 4 0 1 487 4 3 483 4 0 1 487 5 484 1 0 0 0 1 487 6 3 185 427 450 0 0 1 487 7 484 7 0 0 0 0 0 1 487 8 3 137 249 283 1 0 0 0 1 487 9 484 447 271 10 0 0 0 0 0 1 491 1 489 1 491 2 2 487 1 491 3 489 2 0 1 491 4 2 360 7 0 1 491 5 489 5 0 0 0 1 491 6 2 125 402 369 1 0 1 491 7 489 5 0 0 0 0 0 1 491 8 2 216 372 378 1 0 0 0 1 491 9 489 453 149 0 0 0 0 0 0 1 499 1 492 1 499 2 7 493 1 499 3 492 2 0 1 499 4 7 495 4 0 1 499 5 492 17 0 0 0 1 499 6 7 78 191 407 0 0 1 499 7 492 8 0 0 0 0 0 1 499 8 7 200 309 288 1 0 0 0 1 499 9 492 222 491 5 0 0 0 0 0 1 503 1 498 1 503 2 5 498 1 503 3 498 2 0 1 503 4 5 325 6 0 1 503 5 498 15 0 0 0 1 503 6 5 255 292 380 1 0 1 503 7 498 11 0 0 0 0 0 1 503 8 5 316 203 441 8 0 0 0 1 503 9 498 337 158 3 0 0 0 0 0 1 509 1 507 1 509 2 2 508 1 509 3 507 3 0 1 509 4 2 408 4 0 1 509 5 507 3 0 0 0 1 509 6 2 41 232 350 1 0 1 509 7 507 6 0 0 0 0 0 1 509 8 2 382 473 420 2 0 0 0 1 509 9 507 28 314 0 0 0 0 0 0 1 521 1 518 1 521 2 3 515 1 521 3 518 4 0 1 521 4 3 509 0 0 1 521 5 518 3 0 0 0 1 521 6 3 280 153 315 1 0 1 521 7 518 1 0 0 0 0 0 1 521 8 3 312 407 462 6 0 0 0 1 521 9 518 483 181 5 0 0 0 0 0 1 523 1 521 1 523 2 2 522 1 523 3 521 5 0 1 523 4 2 382 2 0 1 523 5 521 4 0 0 0 1 523 6 2 371 475 475 0 0 1 523 7 521 13 0 0 0 0 0 1 523 8 2 380 184 518 4 0 0 0 1 523 9 521 145 342 19 0 0 0 0 0 1 541 1 539 1 541 2 2 537 1 541 3 539 2 0 1 541 4 2 333 6 0 1 541 5 539 3 0 0 0 1 541 6 2 69 320 239 0 0 1 541 7 539 2 0 0 0 0 0 1 541 8 2 113 108 376 3 0 0 0 1 541 9 539 318 340 16 0 0 0 0 0 1 547 1 545 1 547 2 2 543 1 547 3 545 4 0 1 547 4 2 334 8 0 1 547 5 545 2 0 0 0 1 547 6 2 423 153 334 0 0 1 547 7 545 11 0 0 0 0 0 1 547 8 2 180 20 368 10 0 0 0 1 547 9 545 263 238 11 0 0 0 0 0 1 557 1 555 1 557 2 2 553 1 557 3 555 3 0 1 557 4 2 430 7 0 1 557 5 555 9 0 0 0 1 557 6 2 253 192 202 1 0 1 557 7 555 6 0 0 0 0 0 1 557 8 2 113 384 480 0 0 0 0 1 557 9 555 434 456 1 0 0 0 0 0 1 563 1 561 1 563 2 2 559 1 563 3 561 3 0 1 563 4 2 399 20 0 1 563 5 561 6 0 0 0 1 563 6 2 246 303 122 1 0 1 563 7 561 5 0 0 0 0 0 1 563 8 2 509 176 503 2 0 0 0 1 563 9 561 19 15 3 0 0 0 0 0 1 569 1 566 1 569 2 3 568 1 569 3 566 4 0 1 569 4 3 381 7 0 1 569 5 566 4 0 0 0 1 569 6 3 480 263 50 2 0 1 569 7 566 5 0 0 0 0 0 1 569 8 3 241 173 527 1 0 0 0 1 569 9 566 566 478 1 0 0 0 0 0 1 571 1 568 1 571 2 3 570 1 571 3 568 8 0 1 571 4 3 402 2 0 1 571 5 568 4 0 0 0 1 571 6 3 33 295 221 0 0 1 571 7 568 7 0 0 0 0 0 1 571 8 3 371 119 363 4 0 0 0 1 571 9 568 179 545 34 0 0 0 0 0 1 577 1 572 1 577 2 5 572 1 577 3 572 2 0 1 577 4 5 494 12 0 1 577 5 572 3 0 0 0 1 577 6 5 283 25 450 1 0 1 577 7 572 8 0 0 0 0 0 1 577 8 5 321 545 450 12 0 0 0 1 577 9 572 449 576 17 0 0 0 0 0 1 587 1 585 1 587 2 2 583 1 587 3 585 3 0 1 587 4 2 444 16 0 1 587 5 585 2 0 0 0 1 587 6 2 226 121 204 1 0 1 587 7 585 3 0 0 0 0 0 1 587 8 2 91 44 492 5 0 0 0 1 587 9 585 55 333 0 0 0 0 0 0 1 593 1 590 1 593 2 3 592 1 593 3 590 6 0 1 593 4 3 419 4 0 1 593 5 590 3 0 0 0 1 593 6 3 478 65 345 2 0 1 593 7 590 15 0 0 0 0 0 1 593 8 3 495 291 350 9 0 0 0 1 593 9 590 523 223 8 0 0 0 0 0 1 599 1 592 1 599 2 7 598 1 599 3 592 2 0 1 599 4 7 419 3 0 1 599 5 592 8 0 0 0 1 599 6 7 586 274 515 1 0 1 599 7 592 2 0 0 0 0 0 1 599 8 7 124 37 440 3 0 0 0 1 599 9 592 98 114 3 0 0 0 0 0 1 601 1 594 1 601 2 7 598 1 601 3 594 1 0 1 601 4 7 347 14 0 1 601 5 594 13 0 0 0 1 601 6 7 49 440 128 1 0 1 601 7 594 5 0 0 0 0 0 1 601 8 7 490 241 550 0 0 0 0 1 601 9 594 590 487 7 0 0 0 0 0 1 607 1 604 1 607 2 3 606 1 607 3 604 5 0 1 607 4 3 449 8 0 1 607 5 604 4 0 0 0 1 607 6 3 478 45 10 0 0 1 607 7 604 9 0 0 0 0 0 1 607 8 3 449 35 468 4 0 0 0 1 607 9 604 129 444 1 0 0 0 0 0 1 613 1 611 1 613 2 2 609 1 613 3 611 6 0 1 613 4 2 333 12 0 1 613 5 611 32 0 0 0 1 613 6 2 601 595 609 0 0 1 613 7 611 6 0 0 0 0 0 1 613 8 2 539 57 489 6 0 0 0 1 613 9 611 536 513 8 0 0 0 0 0 1 617 1 614 1 617 2 3 612 1 617 3 614 3 0 1 617 4 3 503 2 0 1 617 5 614 4 0 0 0 1 617 6 3 310 595 318 1 0 1 617 7 614 7 0 0 0 0 0 1 617 8 3 155 501 519 0 0 0 0 1 617 9 614 543 388 15 0 0 0 0 0 1 619 1 617 1 619 2 2 618 1 619 3 617 6 0 1 619 4 2 492 6 0 1 619 5 617 8 0 0 0 1 619 6 2 347 468 238 0 0 1 619 7 617 7 0 0 0 0 0 1 619 8 2 225 383 416 10 0 0 0 1 619 9 617 310 579 0 0 0 0 0 0 1 631 1 628 1 631 2 3 629 1 631 3 628 5 0 1 631 4 3 376 6 0 1 631 5 628 5 0 0 0 1 631 6 3 106 541 516 0 0 1 631 7 628 5 0 0 0 0 0 1 631 8 3 187 516 379 2 0 0 0 1 631 9 628 413 296 3 0 0 0 0 0 1 641 1 638 1 641 2 3 635 1 641 3 638 4 0 1 641 4 3 629 0 0 1 641 5 638 1 0 0 0 1 641 6 3 294 557 105 2 0 1 641 7 638 3 0 0 0 0 0 1 641 8 3 332 392 356 3 0 0 0 1 641 9 638 141 66 0 0 0 0 0 0 1 643 1 632 1 643 2 11 641 1 643 3 632 1 0 1 643 4 11 600 0 0 1 643 5 632 2 0 0 0 1 643 6 11 293 412 345 0 0 1 643 7 632 5 0 0 0 0 0 1 643 8 11 569 573 631 1 0 0 0 1 643 9 632 475 591 3 0 0 0 0 0 1 647 1 642 1 647 2 5 645 1 647 3 642 6 0 1 647 4 5 643 3 0 1 647 5 642 11 0 0 0 1 647 6 5 642 385 308 5 0 1 647 7 642 1 0 0 0 0 0 1 647 8 5 271 259 603 9 0 0 0 1 647 9 642 123 561 13 0 0 0 0 0 1 653 1 651 1 653 2 2 649 1 653 3 651 3 0 1 653 4 2 596 6 0 1 653 5 651 5 0 0 0 1 653 6 2 242 220 45 2 0 1 653 7 651 15 0 0 0 0 0 1 653 8 2 296 18 385 0 0 0 0 1 653 9 651 60 365 0 0 0 0 0 0 1 659 1 657 1 659 2 2 655 1 659 3 657 2 0 1 659 4 2 351 8 0 1 659 5 657 4 0 0 0 1 659 6 2 223 105 371 6 0 1 659 7 657 5 0 0 0 0 0 1 659 8 2 90 246 358 6 0 0 0 1 659 9 657 46 592 2 0 0 0 0 0 1 661 1 659 1 661 2 2 660 1 661 3 659 4 0 1 661 4 2 616 7 0 1 661 5 659 19 0 0 0 1 661 6 2 382 456 551 0 0 1 661 7 659 2 0 0 0 0 0 1 661 8 2 72 285 612 0 0 0 0 1 661 9 659 220 389 18 0 0 0 0 0 1 673 1 668 1 673 2 5 672 1 673 3 668 1 0 1 673 4 5 416 6 0 1 673 5 668 15 0 0 0 1 673 6 5 35 248 524 0 0 1 673 7 668 6 0 0 0 0 0 1 673 8 5 302 587 669 6 0 0 0 1 673 9 668 553 347 11 0 0 0 0 0 1 677 1 675 1 677 2 2 672 1 677 3 675 2 0 1 677 4 2 631 0 0 1 677 5 675 5 0 0 0 1 677 6 2 50 632 446 1 0 1 677 7 675 10 0 0 0 0 0 1 677 8 2 152 619 363 0 0 0 0 1 677 9 675 404 504 0 0 0 0 0 0 1 683 1 678 1 683 2 5 682 1 683 3 678 5 0 1 683 4 5 455 5 0 1 683 5 678 7 0 0 0 1 683 6 5 434 109 644 2 0 1 683 7 678 30 0 0 0 0 0 1 683 8 5 65 184 383 0 0 0 0 1 683 9 678 444 85 0 0 0 0 0 0 1 691 1 688 1 691 2 3 686 1 691 3 688 14 0 1 691 4 3 632 3 0 1 691 5 688 4 0 0 0 1 691 6 3 262 408 579 0 0 1 691 7 688 4 0 0 0 0 0 1 691 8 3 321 425 356 7 0 0 0 1 691 9 688 443 556 5 0 0 0 0 0 1 701 1 699 1 701 2 2 697 1 701 3 699 2 0 1 701 4 2 379 12 0 1 701 5 699 5 0 0 0 1 701 6 2 285 327 571 1 0 1 701 7 699 10 0 0 0 0 0 1 701 8 2 593 206 619 1 0 0 0 1 701 9 699 373 459 1 0 0 0 0 0 1 709 1 707 1 709 2 2 705 1 709 3 707 2 0 1 709 4 2 384 6 0 1 709 5 707 10 0 0 0 1 709 6 2 295 514 669 0 0 1 709 7 707 4 0 0 0 0 0 1 709 8 2 79 233 689 2 0 0 0 1 709 9 707 171 257 3 0 0 0 0 0 1 719 1 708 1 719 2 11 715 1 719 3 708 1 0 1 719 4 11 602 5 0 1 719 5 708 1 0 0 0 1 719 6 11 182 591 533 1 0 1 719 7 708 11 0 0 0 0 0 1 719 8 11 244 362 714 5 0 0 0 1 719 9 708 560 288 3 0 0 0 0 0 1 727 1 722 1 727 2 5 725 1 727 3 722 7 0 1 727 4 5 723 3 0 1 727 5 722 5 0 0 0 1 727 6 5 672 397 86 0 0 1 727 7 722 17 0 0 0 0 0 1 727 8 5 368 671 639 0 0 0 0 1 727 9 722 502 573 6 0 0 0 0 0 1 733 1 727 1 733 2 6 732 1 733 3 727 4 0 1 733 4 6 539 12 0 1 733 5 727 8 0 0 0 1 733 6 6 151 549 174 1 0 1 733 7 727 3 0 0 0 0 0 1 733 8 6 142 610 532 1 0 0 0 1 733 9 727 6 337 2 0 0 0 0 0 1 739 1 736 1 739 2 3 734 1 739 3 736 11 0 1 739 4 3 678 3 0 1 739 5 736 9 0 0 0 1 739 6 3 625 447 422 0 0 1 739 7 736 44 0 0 0 0 0 1 739 8 3 25 169 401 2 0 0 0 1 739 9 736 81 616 1 0 0 0 0 0 1 743 1 738 1 743 2 5 742 1 743 3 738 3 0 1 743 4 5 425 5 0 1 743 5 738 6 0 0 0 1 743 6 5 88 471 236 1 0 1 743 7 738 6 0 0 0 0 0 1 743 8 5 588 279 551 0 0 0 0 1 743 9 738 676 327 3 0 0 0 0 0 1 751 1 748 1 751 2 3 749 1 751 3 748 5 0 1 751 4 3 525 3 0 1 751 5 748 7 0 0 0 1 751 6 3 539 633 298 2 0 1 751 7 748 7 0 0 0 0 0 1 751 8 3 672 243 741 3 0 0 0 1 751 9 748 489 703 10 0 0 0 0 0 1 757 1 755 1 757 2 2 753 1 757 3 755 6 0 1 757 4 2 537 10 0 1 757 5 755 13 0 0 0 1 757 6 2 745 739 753 0 0 1 757 7 755 4 0 0 0 0 0 1 757 8 2 509 110 494 12 0 0 0 1 757 9 755 702 688 8 0 0 0 0 0 1 761 1 755 1 761 2 6 758 1 761 3 755 12 0 1 761 4 6 658 0 0 1 761 5 755 6 0 0 0 1 761 6 6 155 597 634 2 0 1 761 7 755 6 0 0 0 0 0 1 761 8 6 540 144 603 11 0 0 0 1 761 9 755 571 317 4 0 0 0 0 0 1 769 1 758 1 769 2 11 765 1 769 3 758 2 0 1 769 4 11 741 32 0 1 769 5 758 1 0 0 0 1 769 6 11 650 326 43 0 0 1 769 7 758 8 0 0 0 0 0 1 769 8 11 632 574 560 1 0 0 0 1 769 9 758 751 623 0 0 0 0 0 0 1 773 1 771 1 773 2 2 772 1 773 3 771 2 0 1 773 4 2 444 4 0 1 773 5 771 8 0 0 0 1 773 6 2 581 3 91 1 0 1 773 7 771 9 0 0 0 0 0 1 773 8 2 693 94 484 0 0 0 0 1 773 9 771 574 216 4 0 0 0 0 0 1 787 1 785 1 787 2 2 786 1 787 3 785 2 0 1 787 4 2 605 11 0 1 787 5 785 9 0 0 0 1 787 6 2 606 512 98 0 0 1 787 7 785 3 0 0 0 0 0 1 787 8 2 715 26 612 5 0 0 0 1 787 9 785 573 480 5 0 0 0 0 0 1 797 1 795 1 797 2 2 793 1 797 3 795 2 0 1 797 4 2 717 1 0 1 797 5 795 3 0 0 0 1 797 6 2 71 396 657 1 0 1 797 7 795 11 0 0 0 0 0 1 797 8 2 389 747 596 1 0 0 0 1 797 9 795 599 240 2 0 0 0 0 0 1 809 1 806 1 809 2 3 799 1 809 3 806 1 0 1 809 4 3 644 4 0 1 809 5 806 3 0 0 0 1 809 6 3 43 75 562 1 0 1 809 7 806 3 0 0 0 0 0 1 809 8 3 673 745 593 1 0 0 0 1 809 9 806 727 341 1 0 0 0 0 0 1 811 1 808 1 811 2 3 806 1 811 3 808 1 0 1 811 4 3 453 3 0 1 811 5 808 3 0 0 0 1 811 6 3 307 755 780 0 0 1 811 7 808 1 0 0 0 0 0 1 811 8 3 525 806 663 3 0 0 0 1 811 9 808 200 382 10 0 0 0 0 0 1 821 1 819 1 821 2 2 816 1 821 3 819 2 0 1 821 4 2 662 15 0 1 821 5 819 9 0 0 0 1 821 6 2 803 130 160 2 0 1 821 7 819 10 0 0 0 0 0 1 821 8 2 589 556 626 5 0 0 0 1 821 9 819 557 650 1 0 0 0 0 0 1 823 1 820 1 823 2 3 821 1 823 3 820 3 0 1 823 4 3 819 4 0 1 823 5 820 3 0 0 0 1 823 6 3 744 616 822 0 0 1 823 7 820 10 0 0 0 0 0 1 823 8 3 31 437 451 0 0 0 0 1 823 9 820 609 740 6 0 0 0 0 0 1 827 1 825 1 827 2 2 821 1 827 3 825 5 0 1 827 4 2 605 18 0 1 827 5 825 3 0 0 0 1 827 6 2 691 601 685 9 0 1 827 7 825 5 0 0 0 0 0 1 827 8 2 32 79 812 2 0 0 0 1 827 9 825 372 177 0 0 0 0 0 0 1 829 1 827 1 829 2 2 828 1 829 3 827 5 0 1 829 4 2 604 9 0 1 829 5 827 7 0 0 0 1 829 6 2 817 476 341 1 0 1 829 7 827 5 0 0 0 0 0 1 829 8 2 138 241 468 1 0 0 0 1 829 9 827 552 621 3 0 0 0 0 0 1 839 1 828 1 839 2 11 838 1 839 3 828 4 0 1 839 4 11 609 2 0 1 839 5 828 2 0 0 0 1 839 6 11 23 537 370 1 0 1 839 7 828 7 0 0 0 0 0 1 839 8 11 329 779 553 16 0 0 0 1 839 9 828 206 349 0 0 0 0 0 0 1 853 1 851 1 853 2 2 852 1 853 3 851 4 0 1 853 4 2 623 3 0 1 853 5 851 2 0 0 0 1 853 6 2 512 194 276 0 0 1 853 7 851 4 0 0 0 0 0 1 853 8 2 118 846 544 8 0 0 0 1 853 9 851 821 677 11 0 0 0 0 0 1 857 1 854 1 857 2 3 850 1 857 3 854 4 0 1 857 4 3 528 0 0 1 857 5 854 3 0 0 0 1 857 6 3 65 824 32 1 0 1 857 7 854 7 0 0 0 0 0 1 857 8 3 494 552 611 3 0 0 0 1 857 9 854 719 308 0 0 0 0 0 0 1 859 1 857 1 859 2 2 858 1 859 3 857 6 0 1 859 4 2 530 2 0 1 859 5 857 12 0 0 0 1 859 6 2 566 646 419 0 0 1 859 7 857 2 0 0 0 0 0 1 859 8 2 672 446 522 0 0 0 0 1 859 9 857 845 648 7 0 0 0 0 0 1 863 1 858 1 863 2 5 862 1 863 3 858 5 0 1 863 4 5 770 2 0 1 863 5 858 10 0 0 0 1 863 6 5 300 62 330 1 0 1 863 7 858 1 0 0 0 0 0 1 863 8 5 849 576 765 9 0 0 0 1 863 9 858 1 381 1 0 0 0 0 0 1 877 1 875 1 877 2 2 873 1 877 3 875 5 0 1 877 4 2 604 6 0 1 877 5 875 6 0 0 0 1 877 6 2 855 400 629 0 0 1 877 7 875 3 0 0 0 0 0 1 877 8 2 347 319 767 4 0 0 0 1 877 9 875 278 770 9 0 0 0 0 0 1 881 1 878 1 881 2 3 869 1 881 3 878 1 0 1 881 4 3 447 0 0 1 881 5 878 8 0 0 0 1 881 6 3 231 419 218 1 0 1 881 7 878 6 0 0 0 0 0 1 881 8 3 561 490 635 21 0 0 0 1 881 9 878 510 587 2 0 0 0 0 0 1 883 1 881 1 883 2 2 879 1 883 3 881 6 0 1 883 4 2 715 8 0 1 883 5 881 14 0 0 0 1 883 6 2 871 865 879 0 0 1 883 7 881 6 0 0 0 0 0 1 883 8 2 768 762 740 7 0 0 0 1 883 9 881 557 360 5 0 0 0 0 0 1 887 1 882 1 887 2 5 885 1 887 3 882 1 0 1 887 4 5 883 3 0 1 887 5 882 5 0 0 0 1 887 6 5 28 341 775 1 0 1 887 7 882 8 0 0 0 0 0 1 887 8 5 706 381 781 0 0 0 0 1 887 9 882 345 727 4 0 0 0 0 0 1 907 1 905 1 907 2 2 903 1 907 3 905 4 0 1 907 4 2 478 14 0 1 907 5 905 2 0 0 0 1 907 6 2 266 752 626 0 0 1 907 7 905 2 0 0 0 0 0 1 907 8 2 811 518 584 4 0 0 0 1 907 9 905 57 783 1 0 0 0 0 0 1 911 1 894 1 911 2 17 909 1 911 3 894 1 0 1 911 4 17 887 11 0 1 911 5 894 2 0 0 0 1 911 6 17 19 683 172 1 0 1 911 7 894 4 0 0 0 0 0 1 911 8 17 168 590 708 6 0 0 0 1 911 9 894 116 679 0 0 0 0 0 0 1 919 1 912 1 919 2 7 910 1 919 3 912 2 0 1 919 4 7 602 3 0 1 919 5 912 11 0 0 0 1 919 6 7 113 817 312 0 0 1 919 7 912 9 0 0 0 0 0 1 919 8 7 504 202 708 6 0 0 0 1 919 9 912 623 410 7 0 0 0 0 0 1 929 1 926 1 929 2 3 917 1 929 3 926 5 0 1 929 4 3 787 0 0 1 929 5 926 3 0 0 0 1 929 6 3 86 92 805 2 0 1 929 7 926 7 0 0 0 0 0 1 929 8 3 586 292 699 5 0 0 0 1 929 9 926 199 481 0 0 0 0 0 0 1 937 1 932 1 937 2 5 934 1 937 3 932 3 0 1 937 4 5 585 23 0 1 937 5 932 5 0 0 0 1 937 6 5 934 727 794 0 0 1 937 7 932 24 0 0 0 0 0 1 937 8 5 53 26 658 0 0 0 0 1 937 9 932 483 533 28 0 0 0 0 0 1 941 1 939 1 941 2 2 940 1 941 3 939 3 0 1 941 4 2 505 3 0 1 941 5 939 2 0 0 0 1 941 6 2 538 694 459 2 0 1 941 7 939 4 0 0 0 0 0 1 941 8 2 590 675 805 0 0 0 0 1 941 9 939 197 708 1 0 0 0 0 0 1 947 1 945 1 947 2 2 943 1 947 3 945 3 0 1 947 4 2 894 8 0 1 947 5 945 15 0 0 0 1 947 6 2 95 787 880 2 0 1 947 7 945 6 0 0 0 0 0 1 947 8 2 581 597 845 1 0 0 0 1 947 9 945 808 269 1 0 0 0 0 0 1 953 1 950 1 953 2 3 947 1 953 3 950 7 0 1 953 4 3 865 1 0 1 953 5 950 1 0 0 0 1 953 6 3 730 829 507 1 0 1 953 7 950 5 0 0 0 0 0 1 953 8 3 108 658 579 6 0 0 0 1 953 9 950 316 819 1 0 0 0 0 0 1 967 1 962 1 967 2 5 965 1 967 3 962 1 0 1 967 4 5 963 3 0 1 967 5 962 2 0 0 0 1 967 6 5 831 948 805 0 0 1 967 7 962 9 0 0 0 0 0 1 967 8 5 136 502 840 15 0 0 0 1 967 9 962 783 512 3 0 0 0 0 0 1 971 1 965 1 971 2 6 970 1 971 3 965 3 0 1 971 4 6 527 2 0 1 971 5 965 14 0 0 0 1 971 6 6 718 729 970 1 0 1 971 7 965 13 0 0 0 0 0 1 971 8 6 206 281 725 0 0 0 0 1 971 9 965 473 805 0 0 0 0 0 0 1 977 1 974 1 977 2 3 972 1 977 3 974 1 0 1 977 4 3 800 0 0 1 977 5 974 11 0 0 0 1 977 6 3 753 830 729 2 0 1 977 7 974 7 0 0 0 0 0 1 977 8 3 77 807 855 0 0 0 0 1 977 9 974 740 450 0 0 0 0 0 0 1 983 1 978 1 983 2 5 981 1 983 3 978 1 0 1 983 4 5 567 5 0 1 983 5 978 8 0 0 0 1 983 6 5 228 296 849 2 0 1 983 7 978 3 0 0 0 0 0 1 983 8 5 530 276 738 7 0 0 0 1 983 9 978 87 858 0 0 0 0 0 0 1 991 1 985 1 991 2 6 989 1 991 3 985 4 0 1 991 4 6 794 10 0 1 991 5 985 3 0 0 0 1 991 6 6 278 855 637 0 0 1 991 7 985 7 0 0 0 0 0 1 991 8 6 234 786 941 15 0 0 0 1 991 9 985 222 466 9 0 0 0 0 0 1 997 1 990 1 997 2 7 995 1 997 3 990 2 0 1 997 4 7 622 4 0 1 997 5 990 10 0 0 0 1 997 6 7 260 58 981 0 0 1 997 7 990 1 0 0 0 0 0 1 997 8 7 241 473 934 0 0 0 0 1 997 9 990 616 732 39 0 0 0 0 0 1 1009 1 998 1 1009 2 11 1008 1 1009 3 998 3 0 1 1009 4 11 825 14 0 1 1009 5 998 6 0 0 0 1 1009 6 11 509 515 850 0 0 1 1009 7 998 1 0 0 0 0 0 1 1009 9 998 627 634 2 0 0 0 0 0 1 1013 1 1010 1 1013 2 3 1006 1 1013 3 1010 7 0 1 1013 4 3 728 2 0 1 1013 5 1010 12 0 0 0 1 1013 6 3 319 230 17 2 0 1 1013 7 1010 7 0 0 0 0 0 1 1013 9 1010 451 396 9 0 0 0 0 0 1 1019 1 1017 1 1019 2 2 1015 1 1019 3 1017 3 0 1 1019 4 2 964 8 0 1 1019 5 1017 3 0 0 0 1 1019 6 2 384 359 996 1 0 1 1019 7 1017 9 0 0 0 0 0 1 1019 9 1017 549 971 0 0 0 0 0 0 1 1021 1 1011 1 1021 2 10 1020 1 1021 3 1011 3 0 1 1021 4 10 936 3 0 1 1021 5 1011 2 0 0 0 1 1021 6 10 862 66 684 0 0 1 1021 7 1011 1 0 0 0 0 0 1 1021 9 1011 628 395 2 0 0 0 0 0 1 1031 1 1017 1 1031 2 14 1029 1 1031 3 1017 4 0 1 1031 4 14 864 3 0 1 1031 5 1017 7 0 0 0 1 1031 6 14 327 378 721 4 0 1 1031 7 1017 1 0 0 0 0 0 1 1031 9 1017 158 823 5 0 0 0 0 0 1 1033 1 1028 1 1033 2 5 1030 1 1033 3 1028 2 0 1 1033 4 5 986 16 0 1 1033 5 1028 9 0 0 0 1 1033 6 5 204 680 697 0 0 1 1033 7 1028 13 0 0 0 0 0 1 1033 9 1028 331 447 11 0 0 0 0 0 1 1039 1 1036 1 1039 2 3 1033 1 1039 3 1036 3 0 1 1039 4 3 800 7 0 1 1039 5 1036 1 0 0 0 1 1039 6 3 703 447 1025 0 0 1 1039 7 1036 1 0 0 0 0 0 1 1039 9 1036 17 930 5 0 0 0 0 0 1 1049 1 1046 1 1049 2 3 1038 1 1049 3 1046 1 0 1 1049 4 3 929 4 0 1 1049 5 1046 1 0 0 0 1 1049 6 3 616 685 338 3 0 1 1049 7 1046 13 0 0 0 0 0 1 1049 9 1046 330 422 5 0 0 0 0 0 1 1051 1 1044 1 1051 2 7 1049 1 1051 3 1044 2 0 1 1051 4 7 994 6 0 1 1051 5 1044 8 0 0 0 1 1051 6 7 335 627 680 0 0 1 1051 7 1044 3 0 0 0 0 0 1 1051 9 1044 736 789 13 0 0 0 0 0 1 1061 1 1059 1 1061 2 2 1057 1 1061 3 1059 2 0 1 1061 4 2 649 6 0 1 1061 5 1059 11 0 0 0 1 1061 6 2 95 552 875 1 0 1 1061 7 1059 5 0 0 0 0 0 1 1061 9 1059 180 187 10 0 0 0 0 0 1 1063 1 1060 1 1063 2 3 1062 1 1063 3 1060 3 0 1 1063 4 3 628 2 0 1 1063 5 1060 3 0 0 0 1 1063 6 3 379 917 483 0 0 1 1063 7 1060 8 0 0 0 0 0 1 1063 9 1060 429 979 3 0 0 0 0 0 1 1069 1 1063 1 1069 2 6 1065 1 1069 3 1063 2 0 1 1069 4 6 1065 6 0 1 1069 5 1063 2 0 0 0 1 1069 6 6 497 137 686 0 0 1 1069 7 1063 4 0 0 0 0 0 1 1069 9 1063 452 896 4 0 0 0 0 0 1 1087 1 1084 1 1087 2 3 1085 1 1087 3 1084 6 0 1 1087 4 3 1079 10 0 1 1087 5 1084 23 0 0 0 1 1087 6 3 795 168 171 4 0 1 1087 7 1084 1 0 0 0 0 0 1 1087 9 1084 58 941 5 0 0 0 0 0 1 1091 1 1089 1 1091 2 2 1090 1 1091 3 1089 3 0 1 1091 4 2 947 2 0 1 1091 5 1089 2 0 0 0 1 1091 6 2 93 72 774 2 0 1 1091 7 1089 2 0 0 0 0 0 1 1091 9 1089 1053 784 0 0 0 0 0 0 1 1093 1 1088 1 1093 2 5 1092 1 1093 3 1088 3 0 1 1093 4 5 988 6 0 1 1093 5 1088 7 0 0 0 1 1093 6 5 199 119 720 0 0 1 1093 7 1088 5 0 0 0 0 0 1 1093 9 1088 635 840 39 0 0 0 0 0 1 1097 1 1094 1 1097 2 3 1096 1 1097 3 1094 1 0 1 1097 4 3 987 4 0 1 1097 5 1094 13 0 0 0 1 1097 6 3 74 641 91 1 0 1 1097 7 1094 1 0 0 0 0 0 1 1097 9 1094 625 17 0 0 0 0 0 0 1 1103 1 1098 1 1103 2 5 1091 1 1103 3 1098 6 0 1 1103 4 5 819 2 0 1 1103 5 1098 6 0 0 0 1 1103 6 5 698 931 796 1 0 1 1103 7 1098 23 0 0 0 0 0 1 1103 9 1098 789 448 2 0 0 0 0 0 1 1109 1 1107 1 1109 2 2 1108 1 1109 3 1107 3 0 1 1109 4 2 1102 8 0 1 1109 5 1107 2 0 0 0 1 1109 6 2 86 1031 1004 1 0 1 1109 7 1107 3 0 0 0 0 0 1 1109 9 1107 684 1050 3 0 0 0 0 0 1 1117 1 1115 1 1117 2 2 1113 1 1117 3 1115 4 0 1 1117 4 2 856 6 0 1 1117 5 1115 2 0 0 0 1 1117 6 2 12 1014 996 0 0 1 1117 7 1115 9 0 0 0 0 0 1 1117 9 1115 14 815 2 0 0 0 0 0 1 1123 1 1121 1 1123 2 2 1122 1 1123 3 1121 2 0 1 1123 4 2 1116 8 0 1 1123 5 1121 2 0 0 0 1 1123 6 2 536 187 918 0 0 1 1123 7 1121 3 0 0 0 0 0 1 1123 9 1121 964 522 1 0 0 0 0 0 1 1129 1 1118 1 1129 2 11 1124 1 1129 3 1118 3 0 1 1129 4 11 916 16 0 1 1129 5 1118 8 0 0 0 1 1129 6 11 366 139 1122 2 0 1 1129 7 1118 3 0 0 0 0 0 1 1129 9 1118 885 669 14 0 0 0 0 0 1 1151 1 1134 1 1151 2 17 1148 1 1151 3 1134 1 0 1 1151 4 17 687 4 0 1 1151 5 1134 1 0 0 0 1 1151 6 17 490 331 594 1 0 1 1151 7 1134 4 0 0 0 0 0 1 1151 9 1134 789 953 1 0 0 0 0 0 1 1153 1 1148 1 1153 2 5 1152 1 1153 3 1148 3 0 1 1153 4 5 870 29 0 1 1153 5 1148 1 0 0 0 1 1153 6 5 656 903 254 0 0 1 1153 7 1148 24 0 0 0 0 0 1 1153 9 1148 473 991 3 0 0 0 0 0 1 1163 1 1158 1 1163 2 5 1161 1 1163 3 1158 2 0 1 1163 4 5 1159 3 0 1 1163 5 1158 9 0 0 0 1 1163 6 5 919 503 226 2 0 1 1163 7 1158 1 0 0 0 0 0 1 1163 9 1158 238 281 2 0 0 0 0 0 1 1171 1 1169 1 1171 2 2 1167 1 1171 3 1169 2 0 1 1171 4 2 1112 8 0 1 1171 5 1169 2 0 0 0 1 1171 6 2 1049 594 1042 0 0 1 1171 7 1169 4 0 0 0 0 0 1 1171 9 1169 1092 580 0 0 0 0 0 0 1 1181 1 1174 1 1181 2 7 1180 1 1181 3 1174 1 0 1 1181 4 7 706 3 0 1 1181 5 1174 2 0 0 0 1 1181 6 7 903 1129 989 2 0 1 1181 7 1174 2 0 0 0 0 0 1 1181 9 1174 628 75 6 0 0 0 0 0 1 1187 1 1185 1 1187 2 2 1181 1 1187 3 1185 4 0 1 1187 4 2 758 4 0 1 1187 5 1185 5 0 0 0 1 1187 6 2 324 472 882 2 0 1 1187 7 1185 7 0 0 0 0 0 1 1187 9 1185 699 213 4 0 0 0 0 0 1 1193 1 1190 1 1193 2 3 1187 1 1193 3 1190 4 0 1 1193 4 3 826 11 0 1 1193 5 1190 11 0 0 0 1 1193 6 3 148 475 1120 2 0 1 1193 7 1190 15 0 0 0 0 0 1 1193 9 1190 12 1185 3 0 0 0 0 0 1 1201 1 1190 1 1201 2 11 1192 1 1201 3 1190 2 0 1 1201 4 11 1006 20 0 1 1201 5 1190 17 0 0 0 1 1201 6 11 985 428 917 0 0 1 1201 7 1190 6 0 0 0 0 0 1 1201 9 1190 575 1090 0 0 0 0 0 0 1 1213 1 1211 1 1213 2 2 1209 1 1213 3 1211 4 0 1 1213 4 2 879 9 0 1 1213 5 1211 6 0 0 0 1 1213 6 2 72 125 608 0 0 1 1213 7 1211 9 0 0 0 0 0 1 1213 9 1211 1169 1122 5 0 0 0 0 0 1 1217 1 1214 1 1217 2 3 1211 1 1217 3 1214 3 0 1 1217 4 3 888 9 0 1 1217 5 1214 3 0 0 0 1 1217 6 3 1080 782 304 2 0 1 1217 7 1214 1 0 0 0 0 0 1 1217 9 1214 143 1200 0 0 0 0 0 0 1 1223 1 1218 1 1223 2 5 1220 1 1223 3 1218 2 0 1 1223 4 5 715 4 0 1 1223 5 1218 2 0 0 0 1 1223 6 5 761 50 1041 2 0 1 1223 7 1218 8 0 0 0 0 0 1 1223 9 1218 675 154 4 0 0 0 0 0 1 1229 1 1227 1 1229 2 2 1225 1 1229 3 1227 3 0 1 1229 4 2 1159 6 0 1 1229 5 1227 7 0 0 0 1 1229 6 2 400 1219 1216 1 0 1 1229 7 1227 19 0 0 0 0 0 1 1229 9 1227 953 983 0 0 0 0 0 0 1 1231 1 1228 1 1231 2 3 1229 1 1231 3 1228 3 0 1 1231 4 3 662 3 0 1 1231 5 1228 5 0 0 0 1 1231 6 3 1162 399 1152 0 0 1 1231 7 1228 1 0 0 0 0 0 1 1231 9 1228 85 1121 24 0 0 0 0 0 1 1237 1 1235 1 1237 2 2 1236 1 1237 3 1235 4 0 1 1237 4 2 960 6 0 1 1237 5 1235 4 0 0 0 1 1237 6 2 346 117 849 0 0 1 1237 7 1235 22 0 0 0 0 0 1 1237 9 1235 46 1163 10 0 0 0 0 0 1 1249 1 1242 1 1249 2 7 1246 1 1249 3 1242 5 0 1 1249 4 7 792 17 0 1 1249 5 1242 1 0 0 0 1 1249 6 7 439 679 474 0 0 1 1249 7 1242 2 0 0 0 0 0 1 1249 9 1242 240 1149 0 0 0 0 0 0 1 1259 1 1257 1 1259 2 2 1258 1 1259 3 1257 3 0 1 1259 4 2 1049 6 0 1 1259 5 1257 5 0 0 0 1 1259 6 2 1187 1008 1191 1 0 1 1259 7 1257 5 0 0 0 0 0 1 1259 9 1257 864 794 2 0 0 0 0 0 1 1277 1 1275 1 1277 2 2 1276 1 1277 3 1275 2 0 1 1277 4 2 753 4 0 1 1277 5 1275 9 0 0 0 1 1277 6 2 500 456 996 2 0 1 1277 7 1275 20 0 0 0 0 0 1 1277 9 1275 1270 428 0 0 0 0 0 0 1 1279 1 1276 1 1279 2 3 1277 1 1279 3 1276 6 0 1 1279 4 3 916 6 0 1 1279 5 1276 4 0 0 0 1 1279 6 3 871 896 159 0 0 1 1279 7 1276 7 0 0 0 0 0 1 1279 9 1276 336 1118 0 0 0 0 0 0 1 1283 1 1281 1 1283 2 2 1279 1 1283 3 1281 3 0 1 1283 4 2 672 8 0 1 1283 5 1281 3 0 0 0 1 1283 6 2 386 536 842 1 0 1 1283 7 1281 2 0 0 0 0 0 1 1283 9 1281 1259 1145 1 0 0 0 0 0 1 1289 1 1283 1 1289 2 6 1280 1 1289 3 1283 6 0 1 1289 4 6 1105 3 0 1 1289 5 1283 16 0 0 0 1 1289 6 6 314 308 1117 1 0 1 1289 7 1283 4 0 0 0 0 0 1 1289 9 1283 179 659 3 0 0 0 0 0 1 1291 1 1289 1 1291 2 2 1290 1 1291 3 1289 5 0 1 1291 4 2 899 6 0 1 1291 5 1289 5 0 0 0 1 1291 6 2 183 1164 1044 0 0 1 1291 7 1289 4 0 0 0 0 0 1 1291 9 1289 607 646 4 0 0 0 0 0 1 1297 1 1287 1 1297 2 10 1294 1 1297 3 1287 2 0 1 1297 4 10 807 8 0 1 1297 5 1287 1 0 0 0 1 1297 6 10 531 428 797 0 0 1 1297 7 1287 2 0 0 0 0 0 1 1297 9 1287 709 1093 6 0 0 0 0 0 1 1301 1 1299 1 1301 2 2 1295 1 1301 3 1299 7 0 1 1301 4 2 1152 3 0 1 1301 5 1299 3 0 0 0 1 1301 6 2 160 635 1068 1 0 1 1301 7 1299 8 0 0 0 0 0 1 1301 9 1299 1293 1108 10 0 0 0 0 0 1 1303 1 1297 1 1303 2 6 1302 1 1303 3 1297 2 0 1 1303 4 6 816 2 0 1 1303 5 1297 2 0 0 0 1 1303 6 6 1092 1278 1228 0 0 1 1303 7 1297 4 0 0 0 0 0 1 1303 9 1297 300 865 0 0 0 0 0 0 1 1307 1 1305 1 1307 2 2 1306 1 1307 3 1305 2 0 1 1307 4 2 844 4 0 1 1307 5 1305 4 0 0 0 1 1307 6 2 65 788 130 3 0 1 1307 7 1305 6 0 0 0 0 0 1 1307 9 1305 958 743 0 0 0 0 0 0 1 1319 1 1306 1 1319 2 13 1316 1 1319 3 1306 1 0 1 1319 4 13 1015 5 0 1 1319 5 1306 2 0 0 0 1 1319 6 13 576 1005 957 1 0 1 1319 7 1306 6 0 0 0 0 0 1 1319 9 1306 408 1211 0 0 0 0 0 0 1 1321 1 1308 1 1321 2 13 1320 1 1321 3 1308 5 0 1 1321 4 13 1223 8 0 1 1321 5 1308 1 0 0 0 1 1321 6 13 683 1020 1055 0 0 1 1321 7 1308 6 0 0 0 0 0 1 1321 9 1308 1130 1162 7 0 0 0 0 0 1 1327 1 1324 1 1327 2 3 1326 1 1327 3 1324 1 0 1 1327 4 3 724 2 0 1 1327 5 1324 9 0 0 0 1 1327 6 3 665 911 1208 0 0 1 1327 7 1324 4 0 0 0 0 0 1 1327 9 1324 1153 605 12 0 0 0 0 0 1 1361 1 1358 1 1361 2 3 1355 1 1361 3 1358 13 0 1 1361 4 3 1349 0 0 1 1361 5 1358 29 0 0 0 1 1361 6 3 124 977 824 1 0 1 1361 7 1358 22 0 0 0 0 0 1 1361 9 1358 164 34 3 0 0 0 0 0 1 1367 1 1362 1 1367 2 5 1365 1 1367 3 1362 1 0 1 1367 4 5 1022 8 0 1 1367 5 1362 2 0 0 0 1 1367 6 5 1108 514 507 2 0 1 1367 7 1362 8 0 0 0 0 0 1 1367 9 1362 407 1250 3 0 0 0 0 0 1 1373 1 1371 1 1373 2 2 1365 1 1373 3 1371 7 0 1 1373 4 2 1269 11 0 1 1373 5 1371 2 0 0 0 1 1373 6 2 1177 567 874 2 0 1 1373 7 1371 9 0 0 0 0 0 1 1373 9 1371 104 1202 3 0 0 0 0 0 1 1381 1 1379 1 1381 2 2 1377 1 1381 3 1379 4 0 1 1381 4 2 1307 10 0 1 1381 5 1379 2 0 0 0 1 1381 6 2 746 1373 168 1 0 1 1381 7 1379 12 0 0 0 0 0 1 1381 9 1379 723 970 15 0 0 0 0 0 1 1399 1 1386 1 1399 2 13 1395 1 1399 3 1386 3 0 1 1399 4 13 964 14 0 1 1399 5 1386 28 0 0 0 1 1399 6 13 1222 533 1164 0 0 1 1399 7 1386 5 0 0 0 0 0 1 1399 9 1386 111 696 8 0 0 0 0 0 1 1409 1 1406 1 1409 2 3 1404 1 1409 3 1406 1 0 1 1409 4 3 968 2 0 1 1409 5 1406 10 0 0 0 1 1409 6 3 156 1165 624 1 0 1 1409 7 1406 40 0 0 0 0 0 1 1409 9 1406 55 778 1 0 0 0 0 0 1 1423 1 1420 1 1423 2 3 1421 1 1423 3 1420 7 0 1 1423 4 3 1419 4 0 1 1423 5 1420 10 0 0 0 1 1423 6 3 169 1041 1357 2 0 1 1423 7 1420 4 0 0 0 0 0 1 1423 9 1420 730 830 21 0 0 0 0 0 1 1427 1 1425 1 1427 2 2 1426 1 1427 3 1425 2 0 1 1427 4 2 1089 13 0 1 1427 5 1425 21 0 0 0 1 1427 6 2 770 1252 250 5 0 1 1427 7 1425 10 0 0 0 0 0 1 1427 9 1425 1056 747 1 0 0 0 0 0 1 1429 1 1423 1 1429 2 6 1425 1 1429 3 1423 2 0 1 1429 4 6 1425 6 0 1 1429 5 1423 12 0 0 0 1 1429 6 6 1301 716 1226 1 0 1 1429 7 1423 2 0 0 0 0 0 1 1429 9 1423 469 1214 1 0 0 0 0 0 1 1433 1 1430 1 1433 2 3 1420 1 1433 3 1430 19 0 1 1433 4 3 883 3 0 1 1433 5 1430 12 0 0 0 1 1433 6 3 74 937 1421 1 0 1 1433 7 1430 28 0 0 0 0 0 1 1433 9 1430 283 456 0 0 0 0 0 0 1 1439 1 1432 1 1439 2 7 1438 1 1439 3 1432 7 0 1 1439 4 7 1430 4 0 1 1439 5 1432 2 0 0 0 1 1439 6 7 1336 31 1267 1 0 1 1439 7 1432 9 0 0 0 0 0 1 1439 9 1432 451 1118 0 0 0 0 0 0 1 1447 1 1444 1 1447 2 3 1446 1 1447 3 1444 3 0 1 1447 4 3 909 5 0 1 1447 5 1444 6 0 0 0 1 1447 6 3 1246 33 430 0 0 1 1447 7 1444 1 0 0 0 0 0 1 1447 9 1444 750 1300 10 0 0 0 0 0 1 1451 1 1449 1 1451 2 2 1446 1 1451 3 1449 9 0 1 1451 4 2 759 3 0 1 1451 5 1449 20 0 0 0 1 1451 6 2 1094 208 615 6 0 1 1451 7 1449 5 0 0 0 0 0 1 1451 9 1449 15 193 2 0 0 0 0 0 1 1453 1 1451 1 1453 2 2 1449 1 1453 3 1451 6 0 1 1453 4 2 1368 9 0 1 1453 5 1451 4 0 0 0 1 1453 6 2 1441 1435 1449 0 0 1 1453 7 1451 15 0 0 0 0 0 1 1453 9 1451 23 1381 6 0 0 0 0 0 1 1459 1 1456 1 1459 2 3 1458 1 1459 3 1456 3 0 1 1459 4 3 855 7 0 1 1459 5 1456 21 0 0 0 1 1459 6 3 406 1309 629 0 0 1 1459 7 1456 10 0 0 0 0 0 1 1459 9 1456 73 1115 2 0 0 0 0 0 1 1471 1 1465 1 1471 2 6 1470 1 1471 3 1465 1 0 1 1471 4 6 1287 2 0 1 1471 5 1465 3 0 0 0 1 1471 6 6 1228 728 969 0 0 1 1471 7 1465 2 0 0 0 0 0 1 1471 9 1465 1362 599 34 0 0 0 0 0 1 1481 1 1478 1 1481 2 3 1480 1 1481 3 1478 5 0 1 1481 4 3 1372 4 0 1 1481 5 1478 17 0 0 0 1 1481 6 3 1021 855 1436 1 0 1 1481 7 1478 12 0 0 0 0 0 1 1481 9 1478 968 651 4 0 0 0 0 0 1 1483 1 1481 1 1483 2 2 1482 1 1483 3 1481 2 0 1 1483 4 2 1170 14 0 1 1483 5 1481 3 0 0 0 1 1483 6 2 541 996 1168 0 0 1 1483 7 1481 11 0 0 0 0 0 1 1483 9 1481 1452 1464 7 0 0 0 0 0 1 1487 1 1482 1 1487 2 5 1485 1 1487 3 1482 2 0 1 1487 4 5 1483 3 0 1 1487 5 1482 11 0 0 0 1 1487 6 5 1289 808 1194 1 0 1 1487 7 1482 11 0 0 0 0 0 1 1487 9 1482 866 1283 9 0 0 0 0 0 1 1489 1 1475 1 1489 2 14 1487 1 1489 3 1475 2 0 1 1489 4 14 1299 9 0 1 1489 5 1475 2 0 0 0 1 1489 6 14 1485 269 254 0 0 1 1489 7 1475 1 0 0 0 0 0 1 1489 9 1475 61 1192 7 0 0 0 0 0 1 1493 1 1491 1 1493 2 2 1485 1 1493 3 1491 11 0 1 1493 4 2 1120 3 0 1 1493 5 1491 5 0 0 0 1 1493 6 2 102 499 465 1 0 1 1493 7 1491 3 0 0 0 0 0 1 1493 9 1491 701 1377 0 0 0 0 0 0 1 1499 1 1497 1 1499 2 2 1495 1 1499 3 1497 2 0 1 1499 4 2 1270 7 0 1 1499 5 1497 6 0 0 0 1 1499 6 2 844 588 698 1 0 1 1499 7 1497 2 0 0 0 0 0 1 1499 9 1497 1196 1357 7 0 0 0 0 0 1 1511 1 1500 1 1511 2 11 1509 1 1511 3 1500 2 0 1 1511 4 11 1433 3 0 1 1511 5 1500 5 0 0 0 1 1511 6 11 1032 1278 106 1 0 1 1511 7 1500 16 0 0 0 0 0 1 1511 9 1500 403 142 7 0 0 0 0 0 1 1523 1 1521 1 1523 2 2 1518 1 1523 3 1521 7 0 1 1523 4 2 1123 0 0 1 1523 5 1521 4 0 0 0 1 1523 6 2 1226 1518 67 1 0 1 1523 7 1521 28 0 0 0 0 0 1 1523 9 1521 1286 573 1 0 0 0 0 0 1 1531 1 1529 1 1531 2 2 1530 1 1531 3 1529 6 0 1 1531 4 2 948 2 0 1 1531 5 1529 3 0 0 0 1 1531 6 2 827 122 1129 3 0 1 1531 7 1529 2 0 0 0 0 0 1 1531 9 1529 314 1400 7 0 0 0 0 0 1 1543 1 1538 1 1543 2 5 1541 1 1543 3 1538 2 0 1 1543 4 5 1539 3 0 1 1543 5 1538 15 0 0 0 1 1543 6 5 796 1363 1391 0 0 1 1543 7 1538 5 0 0 0 0 0 1 1543 9 1538 132 1157 7 0 0 0 0 0 1 1549 1 1547 1 1549 2 2 1541 1 1549 3 1547 5 0 1 1549 4 2 1336 0 0 1 1549 5 1547 5 0 0 0 1 1549 6 2 1191 987 1422 0 0 1 1549 7 1547 3 0 0 0 0 0 1 1549 9 1547 311 1322 9 0 0 0 0 0 1 1553 1 1550 1 1553 2 3 1552 1 1553 3 1550 1 0 1 1553 4 3 1330 4 0 1 1553 5 1550 9 0 0 0 1 1553 6 3 804 1242 904 2 0 1 1553 7 1550 8 0 0 0 0 0 1 1553 9 1550 1399 643 0 0 0 0 0 0 1 1559 1 1540 1 1559 2 19 1558 1 1559 3 1540 3 0 1 1559 4 19 1107 2 0 1 1559 5 1540 1 0 0 0 1 1559 6 19 1236 514 1237 1 0 1 1559 7 1540 2 0 0 0 0 0 1 1559 9 1540 1473 514 3 0 0 0 0 0 1 1567 1 1564 1 1567 2 3 1565 1 1567 3 1564 4 0 1 1567 4 3 1563 4 0 1 1567 5 1564 6 0 0 0 1 1567 6 3 988 1370 855 0 0 1 1567 7 1564 18 0 0 0 0 0 1 1567 9 1564 278 1384 5 0 0 0 0 0 1 1571 1 1569 1 1571 2 2 1570 1 1571 3 1569 3 0 1 1571 4 2 838 2 0 1 1571 5 1569 17 0 0 0 1 1571 6 2 1460 986 1541 1 0 1 1571 7 1569 7 0 0 0 0 0 1 1571 9 1569 113 601 6 0 0 0 0 0 1 1579 1 1576 1 1579 2 3 1578 1 1579 3 1576 11 0 1 1579 4 3 1447 6 0 1 1579 5 1576 8 0 0 0 1 1579 6 3 234 358 1245 0 0 1 1579 7 1576 1 0 0 0 0 0 1 1579 9 1576 666 1226 0 0 0 0 0 0 1 1583 1 1578 1 1583 2 5 1581 1 1583 3 1578 1 0 1 1583 4 5 1579 3 0 1 1583 5 1578 2 0 0 0 1 1583 6 5 466 898 271 1 0 1 1583 7 1578 7 0 0 0 0 0 1 1583 9 1578 719 1438 1 0 0 0 0 0 1 1597 1 1586 1 1597 2 11 1594 1 1597 3 1586 5 0 1 1597 4 11 1270 1 0 1 1597 5 1586 2 0 0 0 1 1597 6 11 567 200 793 0 0 1 1597 7 1586 11 0 0 0 0 0 1 1597 9 1586 611 1205 9 0 0 0 0 0 1 1601 1 1598 1 1601 2 3 1600 1 1601 3 1598 15 0 1 1601 4 3 962 7 0 1 1601 5 1598 5 0 0 0 1 1601 6 3 830 956 296 2 0 1 1601 7 1598 1 0 0 0 0 0 1 1601 9 1598 1120 603 5 0 0 0 0 0 1 1607 1 1602 1 1607 2 5 1605 1 1607 3 1602 3 0 1 1607 4 5 1595 11 0 1 1607 5 1602 26 0 0 0 1 1607 6 5 1182 923 203 1 0 1 1607 7 1602 2 0 0 0 0 0 1 1607 9 1602 508 1279 1 0 0 0 0 0 1 1609 1 1602 1 1609 2 7 1597 1 1609 3 1602 4 0 1 1609 4 7 1277 5 0 1 1609 5 1602 8 0 0 0 1 1609 6 7 490 1348 872 0 0 1 1609 7 1602 2 0 0 0 0 0 1 1609 9 1602 518 1578 7 0 0 0 0 0 1 1613 1 1610 1 1613 2 3 1606 1 1613 3 1610 4 0 1 1613 4 3 1279 0 0 1 1613 5 1610 14 0 0 0 1 1613 6 3 812 1085 1532 2 0 1 1613 7 1610 10 0 0 0 0 0 1 1613 9 1610 734 563 5 0 0 0 0 0 1 1619 1 1617 1 1619 2 2 1615 1 1619 3 1617 2 0 1 1619 4 2 1410 8 0 1 1619 5 1617 3 0 0 0 1 1619 6 2 20 1190 330 1 0 1 1619 7 1617 6 0 0 0 0 0 1 1619 9 1617 277 281 9 0 0 0 0 0 1 1621 1 1619 1 1621 2 2 1617 1 1621 3 1619 4 0 1 1621 4 2 957 6 0 1 1621 5 1619 3 0 0 0 1 1621 6 2 1208 679 1337 0 0 1 1621 7 1619 13 0 0 0 0 0 1 1621 9 1619 3 1605 5 0 0 0 0 0 1 1627 1 1624 1 1627 2 3 1622 1 1627 3 1624 1 0 1 1627 4 3 1176 3 0 1 1627 5 1624 5 0 0 0 1 1627 6 3 1257 265 1071 0 0 1 1627 7 1624 11 0 0 0 0 0 1 1627 9 1624 398 1354 0 0 0 0 0 0 1 1637 1 1635 1 1637 2 2 1633 1 1637 3 1635 2 0 1 1637 4 2 864 1 0 1 1637 5 1635 4 0 0 0 1 1637 6 2 1387 1455 1448 1 0 1 1637 7 1635 7 0 0 0 0 0 1 1637 9 1635 1263 1123 5 0 0 0 0 0 1 1657 1 1646 1 1657 2 11 1655 1 1657 3 1646 1 0 1 1657 4 11 915 13 0 1 1657 5 1646 8 0 0 0 1 1657 6 11 692 904 988 2 0 1 1657 7 1646 7 0 0 0 0 0 1 1657 9 1646 1018 956 7 0 0 0 0 0 1 1663 1 1660 1 1663 2 3 1662 1 1663 3 1660 3 0 1 1663 4 3 1534 2 0 1 1663 5 1660 4 0 0 0 1 1663 6 3 1371 1128 1471 0 0 1 1663 7 1660 10 0 0 0 0 0 1 1663 9 1660 559 1500 19 0 0 0 0 0 1 1667 1 1665 1 1667 2 2 1663 1 1667 3 1665 3 0 1 1667 4 2 1267 8 0 1 1667 5 1665 9 0 0 0 1 1667 6 2 255 1656 1508 1 0 1 1667 7 1665 3 0 0 0 0 0 1 1667 9 1665 1126 602 1 0 0 0 0 0 1 1669 1 1667 1 1669 2 2 1665 1 1669 3 1667 4 0 1 1669 4 2 880 6 0 1 1669 5 1667 8 0 0 0 1 1669 6 2 163 99 1328 0 0 1 1669 7 1667 4 0 0 0 0 0 1 1669 9 1667 852 689 6 0 0 0 0 0 1 1693 1 1691 1 1693 2 2 1692 1 1693 3 1691 2 0 1 1693 4 2 1539 3 0 1 1693 5 1691 3 0 0 0 1 1693 6 2 422 793 1299 0 0 1 1693 7 1691 11 0 0 0 0 0 1 1693 9 1691 242 1558 10 0 0 0 0 0 1 1697 1 1694 1 1697 2 3 1692 1 1697 3 1694 3 0 1 1697 4 3 1208 17 0 1 1697 5 1694 15 0 0 0 1 1697 6 3 22 42 1228 1 0 1 1697 7 1694 3 0 0 0 0 0 1 1697 9 1694 806 255 3 0 0 0 0 0 1 1699 1 1696 1 1699 2 3 1686 1 1699 3 1696 3 0 1 1699 4 3 1506 3 0 1 1699 5 1696 13 0 0 0 1 1699 6 3 99 299 590 0 0 1 1699 7 1696 1 0 0 0 0 0 1 1699 9 1696 855 1498 22 0 0 0 0 0 1 1709 1 1706 1 1709 2 3 1696 1 1709 3 1706 1 0 1 1709 4 3 1199 0 0 1 1709 5 1706 5 0 0 0 1 1709 6 3 176 1012 1460 1 0 1 1709 7 1706 6 0 0 0 0 0 1 1709 9 1706 188 658 3 0 0 0 0 0 1 1721 1 1718 1 1721 2 3 1716 1 1721 3 1718 3 0 1 1721 4 3 1662 2 0 1 1721 5 1718 5 0 0 0 1 1721 6 3 1363 1406 424 1 0 1 1721 7 1718 11 0 0 0 0 0 1 1721 9 1718 182 1597 6 0 0 0 0 0 1 1723 1 1720 1 1723 2 3 1722 1 1723 3 1720 1 0 1 1723 4 3 1046 2 0 1 1723 5 1720 1 0 0 0 1 1723 6 3 79 102 1250 2 0 1 1723 7 1720 13 0 0 0 0 0 1 1723 9 1720 331 1513 1 0 0 0 0 0 1 1733 1 1731 1 1733 2 2 1726 1 1733 3 1731 16 0 1 1733 4 2 1072 2 0 1 1733 5 1731 9 0 0 0 1 1733 6 2 1679 69 1638 1 0 1 1733 7 1731 7 0 0 0 0 0 1 1733 9 1731 1640 728 1 0 0 0 0 0 1 1741 1 1739 1 1741 2 2 1740 1 1741 3 1739 5 0 1 1741 4 2 1477 9 0 1 1741 5 1739 17 0 0 0 1 1741 6 2 1515 1720 1643 0 0 1 1741 7 1739 25 0 0 0 0 0 1 1741 9 1739 169 868 4 0 0 0 0 0 1 1747 1 1745 1 1747 2 2 1743 1 1747 3 1745 5 0 1 1747 4 2 1426 8 0 1 1747 5 1745 6 0 0 0 1 1747 6 2 1284 142 545 1 0 1 1747 7 1745 4 0 0 0 0 0 1 1747 9 1745 1407 1329 2 0 0 0 0 0 1 1753 1 1746 1 1753 2 7 1746 1 1753 3 1746 1 0 1 1753 4 7 951 14 0 1 1753 5 1746 1 0 0 0 1 1753 6 7 1199 1699 1534 0 0 1 1753 7 1746 2 0 0 0 0 0 1 1753 9 1746 639 1196 25 0 0 0 0 0 1 1759 1 1753 1 1759 2 6 1757 1 1759 3 1753 3 0 1 1759 4 6 1144 4 0 1 1759 5 1753 6 0 0 0 1 1759 6 6 1665 1526 1332 0 0 1 1759 7 1753 16 0 0 0 0 0 1 1759 9 1753 212 1720 0 0 0 0 0 0 1 1777 1 1772 1 1777 2 5 1774 1 1777 3 1772 2 0 1 1777 4 5 1224 18 0 1 1777 5 1772 1 0 0 0 1 1777 6 5 74 792 1744 0 0 1 1777 7 1772 19 0 0 0 0 0 1 1777 9 1772 731 1365 11 0 0 0 0 0 1 1783 1 1773 1 1783 2 10 1782 1 1783 3 1773 6 0 1 1783 4 10 1380 5 0 1 1783 5 1773 8 0 0 0 1 1783 6 10 1263 639 1202 1 0 1 1783 7 1773 4 0 0 0 0 0 1 1783 9 1773 920 1652 17 0 0 0 0 0 1 1787 1 1785 1 1787 2 2 1783 1 1787 3 1785 8 0 1 1787 4 2 1086 7 0 1 1787 5 1785 13 0 0 0 1 1787 6 2 911 1515 794 1 0 1 1787 7 1785 7 0 0 0 0 0 1 1787 9 1785 1703 1616 1 0 0 0 0 0 1 1789 1 1783 1 1789 2 6 1781 1 1789 3 1783 1 0 1 1789 4 6 1599 0 0 1 1789 5 1783 3 0 0 0 1 1789 6 6 1091 771 688 0 0 1 1789 7 1783 33 0 0 0 0 0 1 1789 9 1783 212 734 11 0 0 0 0 0 1 1801 1 1790 1 1801 2 11 1796 1 1801 3 1790 1 0 1 1801 4 11 1782 24 0 1 1801 5 1790 1 0 0 0 1 1801 6 11 1504 636 1791 0 0 1 1801 7 1790 6 0 0 0 0 0 1 1801 9 1790 787 1424 9 0 0 0 0 0 1 1811 1 1805 1 1811 2 6 1809 1 1811 3 1805 3 0 1 1811 4 6 1396 11 0 1 1811 5 1805 3 0 0 0 1 1811 6 6 1516 1210 364 1 0 1 1811 7 1805 12 0 0 0 0 0 1 1811 9 1805 1098 1569 4 0 0 0 0 0 1 1823 1 1818 1 1823 2 5 1822 1 1823 3 1818 1 0 1 1823 4 5 1574 2 0 1 1823 5 1818 9 0 0 0 1 1823 6 5 555 751 1442 1 0 1 1823 7 1818 31 0 0 0 0 0 1 1823 9 1818 1245 1010 1 0 0 0 0 0 1 1831 1 1828 1 1831 2 3 1829 1 1831 3 1828 10 0 1 1831 4 3 1827 4 0 1 1831 5 1828 1 0 0 0 1 1831 6 3 534 187 1679 0 0 1 1831 7 1828 9 0 0 0 0 0 1 1831 9 1828 1123 818 1 0 0 0 0 0 1 1847 1 1842 1 1847 2 5 1845 1 1847 3 1842 2 0 1 1847 4 5 1150 5 0 1 1847 5 1842 2 0 0 0 1 1847 6 5 844 477 1225 1 0 1 1847 7 1842 2 0 0 0 0 0 1 1847 9 1842 846 815 0 0 0 0 0 0 1 1861 1 1859 1 1861 2 2 1860 1 1861 3 1859 4 0 1 1861 4 2 1641 3 0 1 1861 5 1859 15 0 0 0 1 1861 6 2 515 862 1352 1 0 1 1861 7 1859 12 0 0 0 0 0 1 1861 9 1859 64 776 4 0 0 0 0 0 1 1867 1 1865 1 1867 2 2 1866 1 1867 3 1865 2 0 1 1867 4 2 1297 7 0 1 1867 5 1865 5 0 0 0 1 1867 6 2 323 1719 924 0 0 1 1867 7 1865 6 0 0 0 0 0 1 1867 9 1865 1336 1826 3 0 0 0 0 0 1 1871 1 1857 1 1871 2 14 1869 1 1871 3 1857 1 0 1 1871 4 14 1486 10 0 1 1871 5 1857 7 0 0 0 1 1871 6 14 1351 593 903 1 0 1 1871 7 1857 12 0 0 0 0 0 1 1871 9 1857 1116 1627 4 0 0 0 0 0 1 1873 1 1863 1 1873 2 10 1870 1 1873 3 1863 4 0 1 1873 4 10 1796 13 0 1 1873 5 1863 7 0 0 0 1 1873 6 10 708 47 487 0 0 1 1873 7 1863 2 0 0 0 0 0 1 1873 9 1863 1667 1056 10 0 0 0 0 0 1 1877 1 1875 1 1877 2 2 1873 1 1877 3 1875 3 0 1 1877 4 2 1329 6 0 1 1877 5 1875 6 0 0 0 1 1877 6 2 877 362 1792 1 0 1 1877 7 1875 6 0 0 0 0 0 1 1877 9 1875 1677 1840 3 0 0 0 0 0 1 1879 1 1873 1 1879 2 6 1877 1 1879 3 1873 3 0 1 1879 4 6 1690 3 0 1 1879 5 1873 9 0 0 0 1 1879 6 6 1098 870 1781 0 0 1 1879 7 1873 9 0 0 0 0 0 1 1879 9 1873 850 1570 25 0 0 0 0 0 1 1889 1 1886 1 1889 2 3 1883 1 1889 3 1886 6 0 1 1889 4 3 1877 0 0 1 1889 5 1886 18 0 0 0 1 1889 6 3 822 364 26 1 0 1 1889 7 1886 15 0 0 0 0 0 1 1889 9 1886 1877 991 6 0 0 0 0 0 1 1901 1 1899 1 1901 2 2 1896 1 1901 3 1899 2 0 1 1901 4 2 1198 8 0 1 1901 5 1899 4 0 0 0 1 1901 6 2 467 1830 952 1 0 1 1901 7 1899 13 0 0 0 0 0 1 1901 9 1899 157 1755 1 0 0 0 0 0 1 1907 1 1905 1 1907 2 2 1906 1 1907 3 1905 2 0 1 1907 4 2 1800 2 0 1 1907 5 1905 3 0 0 0 1 1907 6 2 1237 383 1019 4 0 1 1907 7 1905 2 0 0 0 0 0 1 1907 9 1905 1122 572 0 0 0 0 0 0 1 1913 1 1910 1 1913 2 3 1908 1 1913 3 1910 4 0 1 1913 4 3 1815 2 0 1 1913 5 1910 3 0 0 0 1 1913 6 3 1407 956 1266 1 0 1 1913 7 1910 14 0 0 0 0 0 1 1913 9 1910 1499 1049 4 0 0 0 0 0 1 1931 1 1929 1 1931 2 2 1927 1 1931 3 1929 3 0 1 1931 4 2 1239 7 0 1 1931 5 1929 9 0 0 0 1 1931 6 2 786 504 729 1 0 1 1931 7 1929 9 0 0 0 0 0 1 1931 9 1929 939 1464 4 0 0 0 0 0 1 1933 1 1928 1 1933 2 5 1932 1 1933 3 1928 5 0 1 1933 4 5 1144 6 0 1 1933 5 1928 6 0 0 0 1 1933 6 5 86 834 950 3 0 1 1933 7 1928 14 0 0 0 0 0 1 1933 9 1928 816 1400 0 0 0 0 0 0 1 1949 1 1947 1 1949 2 2 1948 1 1949 3 1947 9 0 1 1949 4 2 1024 3 0 1 1949 5 1947 4 0 0 0 1 1949 6 2 454 100 1846 1 0 1 1949 7 1947 2 0 0 0 0 0 1 1949 9 1947 0 1216 2 0 0 0 0 0 1 1951 1 1948 1 1951 2 3 1949 1 1951 3 1948 9 0 1 1951 4 3 1034 3 0 1 1951 5 1948 10 0 0 0 1 1951 6 3 598 1950 1542 0 0 1 1951 7 1948 11 0 0 0 0 0 1 1951 9 1948 1119 702 4 0 0 0 0 0 1 1973 1 1971 1 1973 2 2 1972 1 1973 3 1971 2 0 1 1973 4 2 1505 4 0 1 1973 5 1971 6 0 0 0 1 1973 6 2 1421 1641 85 4 0 1 1973 7 1971 3 0 0 0 0 0 1 1973 9 1971 818 1438 0 0 0 0 0 0 1 1979 1 1977 1 1979 2 2 1975 1 1979 3 1977 3 0 1 1979 4 2 1748 13 0 1 1979 5 1977 2 0 0 0 1 1979 6 2 315 1590 1945 1 0 1 1979 7 1977 11 0 0 0 0 0 1 1979 9 1977 416 823 3 0 0 0 0 0 1 1987 1 1985 1 1987 2 2 1986 1 1987 3 1985 2 0 1 1987 4 2 1727 7 0 1 1987 5 1985 2 0 0 0 1 1987 6 2 478 208 981 0 0 1 1987 7 1985 6 0 0 0 0 0 1 1987 9 1985 1084 1883 2 0 0 0 0 0 1 1993 1 1988 1 1993 2 5 1990 1 1993 3 1988 2 0 1 1993 4 5 1078 18 0 1 1993 5 1988 12 0 0 0 1 1993 6 5 1873 75 1750 0 0 1 1993 7 1988 5 0 0 0 0 0 1 1993 9 1988 1102 1671 40 0 0 0 0 0 1 1997 1 1995 1 1997 2 2 1993 1 1997 3 1995 3 0 1 1997 4 2 1836 9 0 1 1997 5 1995 3 0 0 0 1 1997 6 2 1168 326 1724 1 0 1 1997 7 1995 4 0 0 0 0 0 1 1997 9 1995 1081 1712 3 0 0 0 0 0 1 1999 1 1996 1 1999 2 3 1998 1 1999 3 1996 1 0 1 1999 4 3 1177 3 0 1 1999 5 1996 1 0 0 0 1 1999 6 3 1171 423 1114 0 0 1 1999 7 1996 1 0 0 0 0 0 1 1999 9 1996 651 1798 7 0 0 0 0 0 1 2003 1 1998 1 2003 2 5 2002 1 2003 3 1998 7 0 1 2003 4 5 1333 13 0 1 2003 5 1998 3 0 0 0 1 2003 6 5 350 1856 1981 2 0 1 2003 7 1998 6 0 0 0 0 0 1 2003 9 1998 1532 353 3 0 0 0 0 0 1 2011 1 2008 1 2011 2 3 2004 1 2011 3 2008 3 0 1 2011 4 3 1947 5 0 1 2011 5 2008 6 0 0 0 1 2011 6 3 1530 1650 1233 0 0 1 2011 7 2008 3 0 0 0 0 0 1 2011 9 2008 1256 1168 28 0 0 0 0 0 1 2017 1 2012 1 2017 2 5 2016 1 2017 3 2012 14 0 1 2017 4 5 1393 6 0 1 2017 5 2012 35 0 0 0 1 2017 6 5 943 129 1843 0 0 1 2017 7 2012 2 0 0 0 0 0 1 2017 9 2012 10 1133 9 0 0 0 0 0 1 2027 1 2025 1 2027 2 2 2021 1 2027 3 2025 5 0 1 2027 4 2 1899 0 0 1 2027 5 2025 2 0 0 0 1 2027 6 2 1083 1623 2006 1 0 1 2027 7 2025 3 0 0 0 0 0 1 2027 9 2025 1995 87 6 0 0 0 0 0 1 2029 1 2027 1 2029 2 2 2028 1 2029 3 2027 5 0 1 2029 4 2 1663 7 0 1 2029 5 2027 12 0 0 0 1 2029 6 2 317 1791 1492 0 0 1 2029 7 2027 6 0 0 0 0 0 1 2029 9 2027 1332 1730 20 0 0 0 0 0 1 2039 1 2032 1 2039 2 7 2026 1 2039 3 2032 7 0 1 2039 4 7 1377 14 0 1 2039 5 2032 4 0 0 0 1 2039 6 7 755 1630 1937 2 0 1 2039 7 2032 4 0 0 0 0 0 1 2039 9 2032 1023 1657 0 0 0 0 0 0 1 2053 1 2051 1 2053 2 2 2049 1 2053 3 2051 6 0 1 2053 4 2 1580 10 0 1 2053 5 2051 31 0 0 0 1 2053 6 2 2041 2035 2049 0 0 1 2053 7 2051 6 0 0 0 0 0 1 2053 9 2051 1432 837 1 0 0 0 0 0 1 2063 1 2058 1 2063 2 5 2058 1 2063 3 2058 1 0 1 2063 4 5 1625 8 0 1 2063 5 2058 1 0 0 0 1 2063 6 5 1137 949 608 1 0 1 2063 7 2058 1 0 0 0 0 0 1 2063 9 2058 1964 829 7 0 0 0 0 0 1 2069 1 2067 1 2069 2 2 2065 1 2069 3 2067 2 0 1 2069 4 2 1413 6 0 1 2069 5 2067 8 0 0 0 1 2069 6 2 1268 1157 1365 4 0 1 2069 7 2067 4 0 0 0 0 0 1 2069 9 2067 1924 1763 0 0 0 0 0 0 1 2081 1 2078 1 2081 2 3 2080 1 2081 3 2078 10 0 1 2081 4 3 1796 7 0 1 2081 5 2078 4 0 0 0 1 2081 6 3 873 2034 1765 1 0 1 2081 7 2078 10 0 0 0 0 0 1 2081 9 2078 646 1414 5 0 0 0 0 0 1 2083 1 2081 1 2083 2 2 2079 1 2083 3 2081 4 0 1 2083 4 2 1925 8 0 1 2083 5 2081 3 0 0 0 1 2083 6 2 830 2053 790 0 0 1 2083 7 2081 6 0 0 0 0 0 1 2083 9 2081 1011 1762 8 0 0 0 0 0 1 2087 1 2082 1 2087 2 5 2084 1 2087 3 2082 1 0 1 2087 4 5 1305 6 0 1 2087 5 2082 3 0 0 0 1 2087 6 5 1567 114 517 1 0 1 2087 7 2082 2 0 0 0 0 0 1 2087 9 2082 1970 1931 1 0 0 0 0 0 1 2089 1 2082 1 2089 2 7 2080 1 2089 3 2082 4 0 1 2089 4 7 1985 2 0 1 2089 5 2082 5 0 0 0 1 2089 6 7 1492 977 1737 0 0 1 2089 7 2082 1 0 0 0 0 0 1 2089 9 2082 570 2054 2 0 0 0 0 0 1 2099 1 2097 1 2099 2 2 2095 1 2099 3 2097 3 0 1 2099 4 2 1828 7 0 1 2099 5 2097 6 0 0 0 1 2099 6 2 1169 1728 1204 2 0 1 2099 7 2097 9 0 0 0 0 0 1 2099 9 2097 747 1559 5 0 0 0 0 0 1 2111 1 2104 1 2111 2 7 2110 1 2111 3 2104 9 0 1 2111 4 7 1916 2 0 1 2111 5 2104 1 0 0 0 1 2111 6 7 117 1071 1472 6 0 1 2111 7 2104 8 0 0 0 0 0 1 2111 9 2104 2097 615 0 0 0 0 0 0 1 2113 1 2108 1 2113 2 5 2108 1 2113 3 2108 1 0 1 2113 4 5 1278 18 0 1 2113 5 2108 5 0 0 0 1 2113 6 5 456 1649 1853 0 0 1 2113 7 2108 10 0 0 0 0 0 1 2113 9 2108 1636 1520 1 0 0 0 0 0 1 2129 1 2126 1 2129 2 3 2120 1 2129 3 2126 1 0 1 2129 4 3 1672 6 0 1 2129 5 2126 3 0 0 0 1 2129 6 3 700 1338 1245 3 0 1 2129 7 2126 3 0 0 0 0 0 1 2129 9 2126 844 115 6 0 0 0 0 0 1 2131 1 2129 1 2131 2 2 2130 1 2131 3 2129 5 0 1 2131 4 2 2051 2 0 1 2131 5 2129 17 0 0 0 1 2131 6 2 1622 1717 1000 0 0 1 2131 7 2129 3 0 0 0 0 0 1 2131 9 2129 431 2105 5 0 0 0 0 0 1 2137 1 2127 1 2137 2 10 2136 1 2137 3 2127 6 0 1 2137 4 10 1153 6 0 1 2137 5 2127 5 0 0 0 1 2137 6 10 970 84 734 0 0 1 2137 7 2127 15 0 0 0 0 0 1 2137 9 2127 965 2084 27 0 0 0 0 0 1 2141 1 2139 1 2141 2 2 2140 1 2141 3 2139 3 0 1 2141 4 2 1154 3 0 1 2141 5 2139 2 0 0 0 1 2141 6 2 1939 860 1732 1 0 1 2141 7 2139 7 0 0 0 0 0 1 2141 9 2139 829 278 0 0 0 0 0 0 1 2143 1 2140 1 2143 2 3 2141 1 2143 3 2140 1 0 1 2143 4 3 1638 3 0 1 2143 5 2140 3 0 0 0 1 2143 6 3 802 1443 1616 0 0 1 2143 7 2140 7 0 0 0 0 0 1 2143 9 2140 1518 2089 6 0 0 0 0 0 1 2153 1 2150 1 2153 2 3 2145 1 2153 3 2150 3 0 1 2153 4 3 1925 2 0 1 2153 5 2150 3 0 0 0 1 2153 6 3 1732 2007 1833 1 0 1 2153 7 2150 8 0 0 0 0 0 1 2153 9 2150 1865 2027 1 0 0 0 0 0 1 2161 1 2138 1 2161 2 23 2160 1 2161 3 2138 2 0 1 2161 4 23 1561 15 0 1 2161 5 2138 2 0 0 0 1 2161 6 23 699 821 1898 1 0 1 2161 7 2138 6 0 0 0 0 0 1 2161 9 2138 439 967 6 0 0 0 0 0 1 2179 1 2172 1 2179 2 7 2177 1 2179 3 2172 1 0 1 2179 4 7 2017 6 0 1 2179 5 2172 3 0 0 0 1 2179 6 7 1709 2022 2038 0 0 1 2179 7 2172 15 0 0 0 0 0 1 2179 9 2172 2079 981 3 0 0 0 0 0 1 2203 1 2198 1 2203 2 5 2202 1 2203 3 2198 1 0 1 2203 4 5 1600 7 0 1 2203 5 2198 1 0 0 0 1 2203 6 5 731 1727 742 0 0 1 2203 7 2198 5 0 0 0 0 0 1 2203 9 2198 581 2028 8 0 0 0 0 0 1 2207 1 2202 1 2207 2 5 2205 1 2207 3 2202 3 0 1 2207 4 5 1195 8 0 1 2207 5 2202 2 0 0 0 1 2207 6 5 2074 865 508 1 0 1 2207 7 2202 10 0 0 0 0 0 1 2207 9 2202 1132 1570 0 0 0 0 0 0 1 2213 1 2211 1 2213 2 2 2209 1 2213 3 2211 3 0 1 2213 4 2 2119 6 0 1 2213 5 2211 5 0 0 0 1 2213 6 2 1438 1211 1450 1 0 1 2213 7 2211 6 0 0 0 0 0 1 2213 9 2211 0 2017 2 0 0 0 0 0 1 2221 1 2219 1 2221 2 2 2217 1 2221 3 2219 6 0 1 2221 4 2 1282 6 0 1 2221 5 2219 8 0 0 0 1 2221 6 2 2209 2203 2217 0 0 1 2221 7 2219 2 0 0 0 0 0 1 2221 9 2219 1126 2012 5 0 0 0 0 0 1 2237 1 2235 1 2237 2 2 2232 1 2237 3 2235 4 0 1 2237 4 2 1387 8 0 1 2237 5 2235 7 0 0 0 1 2237 6 2 1978 160 839 1 0 1 2237 7 2235 11 0 0 0 0 0 1 2237 9 2235 1056 797 5 0 0 0 0 0 1 2239 1 2236 1 2239 2 3 2233 1 2239 3 2236 6 0 1 2239 4 3 2145 11 0 1 2239 5 2236 8 0 0 0 1 2239 6 3 1910 490 1124 0 0 1 2239 7 2236 1 0 0 0 0 0 1 2239 9 2236 947 1594 31 0 0 0 0 0 1 2243 1 2241 1 2243 2 2 2234 1 2243 3 2241 2 0 1 2243 4 2 1553 1 0 1 2243 5 2241 2 0 0 0 1 2243 6 2 2141 92 1983 2 0 1 2243 7 2241 5 0 0 0 0 0 1 2243 9 2241 957 1339 0 0 0 0 0 0 1 2251 1 2244 1 2251 2 7 2249 1 2251 3 2244 1 0 1 2251 4 7 1840 6 0 1 2251 5 2244 3 0 0 0 1 2251 6 7 1081 1578 2067 0 0 1 2251 7 2244 7 0 0 0 0 0 1 2251 9 2244 1455 1129 2 0 0 0 0 0 1 2267 1 2265 1 2267 2 2 2266 1 2267 3 2265 2 0 1 2267 4 2 1889 10 0 1 2267 5 2265 9 0 0 0 1 2267 6 2 1447 170 1050 4 0 1 2267 7 2265 12 0 0 0 0 0 1 2267 9 2265 2206 1865 1 0 0 0 0 0 1 2269 1 2267 1 2269 2 2 2265 1 2269 3 2267 2 0 1 2269 4 2 1609 10 0 1 2269 5 2267 3 0 0 0 1 2269 6 2 2181 867 2260 0 0 1 2269 7 2267 4 0 0 0 0 0 1 2269 9 2267 172 2153 9 0 0 0 0 0 1 2273 1 2270 1 2273 2 3 2268 1 2273 3 2270 3 0 1 2273 4 3 1913 2 0 1 2273 5 2270 7 0 0 0 1 2273 6 3 1673 1140 2220 1 0 1 2273 7 2270 20 0 0 0 0 0 1 2273 9 2270 1769 1846 1 0 0 0 0 0 1 2281 1 2274 1 2281 2 7 2274 1 2281 3 2274 5 0 1 2281 4 7 1462 0 0 1 2281 5 2274 3 0 0 0 1 2281 6 7 1814 946 1240 0 0 1 2281 7 2274 1 0 0 0 0 0 1 2281 9 2274 1458 1648 10 0 0 0 0 0 1 2287 1 2268 1 2287 2 19 2283 1 2287 3 2268 1 0 1 2287 4 19 2160 6 0 1 2287 5 2268 4 0 0 0 1 2287 6 19 233 630 1812 0 0 1 2287 7 2268 4 0 0 0 0 0 1 2287 9 2268 386 1670 1 0 0 0 0 0 1 2293 1 2291 1 2293 2 2 2289 1 2293 3 2291 5 0 1 2293 4 2 1256 10 0 1 2293 5 2291 2 0 0 0 1 2293 6 2 435 1415 1935 0 0 1 2293 7 2291 10 0 0 0 0 0 1 2293 9 2291 2124 1905 7 0 0 0 0 0 1 2297 1 2292 1 2297 2 5 2292 1 2297 3 2292 1 0 1 2297 4 5 1772 8 0 1 2297 5 2292 2 0 0 0 1 2297 6 5 607 1036 2147 1 0 1 2297 7 2292 1 0 0 0 0 0 1 2297 9 2292 1213 2134 0 0 0 0 0 0 1 2309 1 2307 1 2309 2 2 2305 1 2309 3 2307 3 0 1 2309 4 2 2173 1 0 1 2309 5 2307 6 0 0 0 1 2309 6 2 94 164 1911 1 0 1 2309 7 2307 14 0 0 0 0 0 1 2309 9 2307 1532 1441 6 0 0 0 0 0 1 2311 1 2308 1 2311 2 3 2309 1 2311 3 2308 3 0 1 2311 4 3 2175 3 0 1 2311 5 2308 11 0 0 0 1 2311 6 3 1099 1270 424 3 0 1 2311 7 2308 7 0 0 0 0 0 1 2311 9 2308 309 1796 1 0 0 0 0 0 1 2333 1 2331 1 2333 2 2 2329 1 2333 3 2331 3 0 1 2333 4 2 1591 7 0 1 2333 5 2331 9 0 0 0 1 2333 6 2 966 990 1899 1 0 1 2333 7 2331 8 0 0 0 0 0 1 2333 9 2331 1892 204 0 0 0 0 0 0 1 2339 1 2337 1 2339 2 2 2329 1 2339 3 2337 20 0 1 2339 4 2 1768 0 0 1 2339 5 2337 6 0 0 0 1 2339 6 2 1112 764 2243 2 0 1 2339 7 2337 17 0 0 0 0 0 1 2339 9 2337 900 1724 0 0 0 0 0 0 1 2341 1 2334 1 2341 2 7 2339 1 2341 3 2334 3 0 1 2341 4 7 1919 9 0 1 2341 5 2334 3 0 0 0 1 2341 6 7 1291 342 1220 0 0 1 2341 7 2334 9 0 0 0 0 0 1 2341 9 2334 328 2061 33 0 0 0 0 0 1 2347 1 2344 1 2347 2 3 2342 1 2347 3 2344 4 0 1 2347 4 3 1254 3 0 1 2347 5 2344 3 0 0 0 1 2347 6 3 889 177 2337 0 0 1 2347 7 2344 6 0 0 0 0 0 1 2347 9 2344 743 2277 5 0 0 0 0 0 1 2351 1 2338 1 2351 2 13 2347 1 2351 3 2338 1 0 1 2351 4 13 1822 6 0 1 2351 5 2338 2 0 0 0 1 2351 6 13 773 1036 1247 1 0 1 2351 7 2338 1 0 0 0 0 0 1 2351 9 2338 1452 1725 3 0 0 0 0 0 1 2357 1 2355 1 2357 2 2 2352 1 2357 3 2355 2 0 1 2357 4 2 2140 8 0 1 2357 5 2355 5 0 0 0 1 2357 6 2 280 2291 1782 1 0 1 2357 7 2355 7 0 0 0 0 0 1 2357 9 2355 2317 1931 0 0 0 0 0 0 1 2371 1 2369 1 2371 2 2 2370 1 2371 3 2369 4 0 1 2371 4 2 2087 7 0 1 2371 5 2369 2 0 0 0 1 2371 6 2 860 370 1269 2 0 1 2371 7 2369 4 0 0 0 0 0 1 2371 9 2369 1314 1457 23 0 0 0 0 0 1 2377 1 2372 1 2377 2 5 2376 1 2377 3 2372 1 0 1 2377 4 5 1684 6 0 1 2377 5 2372 10 0 0 0 1 2377 6 5 299 83 975 0 0 1 2377 7 2372 2 0 0 0 0 0 1 2377 9 2372 1827 2178 28 0 0 0 0 0 1 2381 1 2378 1 2381 2 3 2379 1 2381 3 2378 7 0 1 2381 4 3 2283 12 0 1 2381 5 2378 20 0 0 0 1 2381 6 3 1568 1764 432 1 0 1 2381 7 2378 12 0 0 0 0 0 1 2381 9 2378 2290 74 4 0 0 0 0 0 1 2383 1 2378 1 2383 2 5 2382 1 2383 3 2378 2 0 1 2383 4 5 2159 8 0 1 2383 5 2378 1 0 0 0 1 2383 6 5 767 2110 372 3 0 1 2383 7 2378 34 0 0 0 0 0 1 2383 9 2378 1599 2180 11 0 0 0 0 0 1 2389 1 2387 1 2389 2 2 2385 1 2389 3 2387 2 0 1 2389 4 2 1651 10 0 1 2389 5 2387 5 0 0 0 1 2389 6 2 953 405 1962 0 0 1 2389 7 2387 3 0 0 0 0 0 1 2389 9 2387 1273 1724 4 0 0 0 0 0 1 2393 1 2390 1 2393 2 3 2392 1 2393 3 2390 4 0 1 2393 4 3 2047 7 0 1 2393 5 2390 7 0 0 0 1 2393 6 3 606 861 1633 2 0 1 2393 7 2390 9 0 0 0 0 0 1 2393 9 2390 678 757 1 0 0 0 0 0 1 2399 1 2388 1 2399 2 11 2398 1 2399 3 2388 4 0 1 2399 4 11 1637 3 0 1 2399 5 2388 3 0 0 0 1 2399 6 11 1344 89 1838 2 0 1 2399 7 2388 3 0 0 0 0 0 1 2399 9 2388 1220 30 5 0 0 0 0 0 1 2411 1 2405 1 2411 2 6 2410 1 2411 3 2405 3 0 1 2411 4 6 1681 4 0 1 2411 5 2405 12 0 0 0 1 2411 6 6 1092 1304 2016 1 0 1 2411 7 2405 1 0 0 0 0 0 1 2411 9 2405 813 1670 1 0 0 0 0 0 1 2417 1 2414 1 2417 2 3 2408 1 2417 3 2414 1 0 1 2417 4 3 2350 14 0 1 2417 5 2414 3 0 0 0 1 2417 6 3 167 2026 893 1 0 1 2417 7 2414 4 0 0 0 0 0 1 2417 9 2414 742 1272 0 0 0 0 0 0 1 2423 1 2418 1 2423 2 5 2421 1 2423 3 2418 1 0 1 2423 4 5 1349 10 0 1 2423 5 2418 6 0 0 0 1 2423 6 5 2166 1751 2050 1 0 1 2423 7 2418 7 0 0 0 0 0 1 2423 9 2418 2267 915 5 0 0 0 0 0 1 2437 1 2435 1 2437 2 2 2433 1 2437 3 2435 6 0 1 2437 4 2 1592 6 0 1 2437 5 2435 2 0 0 0 1 2437 6 2 2425 2419 2433 0 0 1 2437 7 2435 14 0 0 0 0 0 1 2437 9 2435 444 2275 5 0 0 0 0 0 1 2441 1 2435 1 2441 2 6 2438 1 2441 3 2435 1 0 1 2441 4 6 2078 0 0 1 2441 5 2435 7 0 0 0 1 2441 6 6 1678 1880 1270 1 0 1 2441 7 2435 4 0 0 0 0 0 1 2441 9 2435 1272 787 0 0 0 0 0 0 1 2447 1 2442 1 2447 2 5 2446 1 2447 3 2442 1 0 1 2447 4 5 1426 2 0 1 2447 5 2442 3 0 0 0 1 2447 6 5 1496 2409 2123 1 0 1 2447 7 2442 9 0 0 0 0 0 1 2447 9 2442 1269 1060 4 0 0 0 0 0 1 2459 1 2457 1 2459 2 2 2455 1 2459 3 2457 3 0 1 2459 4 2 1737 7 0 1 2459 5 2457 2 0 0 0 1 2459 6 2 885 1850 2138 1 0 1 2459 7 2457 4 0 0 0 0 0 1 2459 9 2457 114 849 7 0 0 0 0 0 1 2467 1 2465 1 2467 2 2 2466 1 2467 3 2465 6 0 1 2467 4 2 1277 7 0 1 2467 5 2465 6 0 0 0 1 2467 6 2 1060 1538 1507 0 0 1 2467 7 2465 6 0 0 0 0 0 1 2467 9 2465 1683 1543 9 0 0 0 0 0 1 2473 1 2468 1 2473 2 5 2472 1 2473 3 2468 1 0 1 2473 4 5 1380 11 0 1 2473 5 2468 10 0 0 0 1 2473 6 5 1517 348 2137 1 0 1 2473 7 2468 26 0 0 0 0 0 1 2473 9 2468 1146 1002 4 0 0 0 0 0 1 2477 1 2475 1 2477 2 2 2476 1 2477 3 2475 2 0 1 2477 4 2 1955 3 0 1 2477 5 2475 5 0 0 0 1 2477 6 2 80 1343 959 2 0 1 2477 7 2475 9 0 0 0 0 0 1 2477 9 2475 223 1104 9 0 0 0 0 0 1 2503 1 2500 1 2503 2 3 2502 1 2503 3 2500 14 0 1 2503 4 3 2207 2 0 1 2503 5 2500 9 0 0 0 1 2503 6 3 2195 972 1282 0 0 1 2503 7 2500 5 0 0 0 0 0 1 2503 9 2500 1979 1152 7 0 0 0 0 0 1 2521 1 2504 1 2521 2 17 2520 1 2521 3 2504 1 0 1 2521 4 17 1993 23 0 1 2521 5 2504 6 0 0 0 1 2521 6 17 277 659 1946 1 0 1 2521 7 2504 4 0 0 0 0 0 1 2521 9 2504 822 2454 12 0 0 0 0 0 1 2531 1 2529 1 2531 2 2 2527 1 2531 3 2529 2 0 1 2531 4 2 1375 8 0 1 2531 5 2529 5 0 0 0 1 2531 6 2 1051 184 2346 2 0 1 2531 7 2529 3 0 0 0 0 0 1 2531 9 2529 2207 1381 0 0 0 0 0 0 1 2539 1 2537 1 2539 2 2 2538 1 2539 3 2537 5 0 1 2539 4 2 2069 2 0 1 2539 5 2537 3 0 0 0 1 2539 6 2 1802 1911 1332 0 0 1 2539 7 2537 5 0 0 0 0 0 1 2539 9 2537 822 2293 7 0 0 0 0 0 1 2543 1 2538 1 2543 2 5 2541 1 2543 3 2538 6 0 1 2543 4 5 2539 3 0 1 2543 5 2538 3 0 0 0 1 2543 6 5 860 1428 1634 2 0 1 2543 7 2538 21 0 0 0 0 0 1 2543 9 2538 1813 1024 0 0 0 0 0 0 1 2549 1 2547 1 2549 2 2 2545 1 2549 3 2547 2 0 1 2549 4 2 2242 12 0 1 2549 5 2547 3 0 0 0 1 2549 6 2 2264 1711 1391 1 0 1 2549 7 2547 2 0 0 0 0 0 1 2549 9 2547 1819 2 0 0 0 0 0 0 1 2551 1 2545 1 2551 2 6 2549 1 2551 3 2545 2 0 1 2551 4 6 2007 3 0 1 2551 5 2545 7 0 0 0 1 2551 6 6 1355 1591 1888 0 0 1 2551 7 2545 23 0 0 0 0 0 1 2551 9 2545 1151 2487 4 0 0 0 0 0 1 2557 1 2555 1 2557 2 2 2553 1 2557 3 2555 6 0 1 2557 4 2 2444 6 0 1 2557 5 2555 4 0 0 0 1 2557 6 2 2545 2539 2553 0 0 1 2557 7 2555 2 0 0 0 0 0 1 2557 9 2555 2359 1177 6 0 0 0 0 0 1 2579 1 2577 1 2579 2 2 2560 1 2579 3 2577 5 0 1 2579 4 2 1954 1 0 1 2579 5 2577 12 0 0 0 1 2579 6 2 73 471 1709 1 0 1 2579 7 2577 4 0 0 0 0 0 1 2579 9 2577 1770 866 7 0 0 0 0 0 1 2591 1 2584 1 2591 2 7 2589 1 2591 3 2584 1 0 1 2591 4 7 2159 5 0 1 2591 5 2584 5 0 0 0 1 2591 6 7 1936 607 1663 1 0 1 2591 7 2584 14 0 0 0 0 0 1 2591 9 2584 2384 310 1 0 0 0 0 0 1 2593 1 2586 1 2593 2 7 2586 1 2593 3 2586 3 0 1 2593 4 7 2226 14 0 1 2593 5 2586 12 0 0 0 1 2593 6 7 946 1268 1392 0 0 1 2593 7 2586 3 0 0 0 0 0 1 2593 9 2586 371 1458 11 0 0 0 0 0 1 2609 1 2606 1 2609 2 3 2603 1 2609 3 2606 1 0 1 2609 4 3 2597 0 0 1 2609 5 2606 1 0 0 0 1 2609 6 3 1184 2345 1105 1 0 1 2609 7 2606 6 0 0 0 0 0 1 2609 9 2606 1030 2447 3 0 0 0 0 0 1 2617 1 2612 1 2617 2 5 2614 1 2617 3 2612 5 0 1 2617 4 5 2248 10 0 1 2617 5 2612 2 0 0 0 1 2617 6 5 644 2355 1514 0 0 1 2617 7 2612 3 0 0 0 0 0 1 2617 9 2612 1014 2367 16 0 0 0 0 0 1 2621 1 2619 1 2621 2 2 2620 1 2621 3 2619 3 0 1 2621 4 2 1919 9 0 1 2621 5 2619 10 0 0 0 1 2621 6 2 1136 283 2390 1 0 1 2621 7 2619 6 0 0 0 0 0 1 2621 9 2619 1379 1858 1 0 0 0 0 0 1 2633 1 2630 1 2633 2 3 2627 1 2633 3 2630 3 0 1 2633 4 3 1393 9 0 1 2633 5 2630 4 0 0 0 1 2633 6 3 773 318 1332 1 0 1 2633 7 2630 3 0 0 0 0 0 1 2633 9 2630 1843 111 0 0 0 0 0 0 1 2647 1 2644 1 2647 2 3 2646 1 2647 3 2644 4 0 1 2647 4 3 1656 5 0 1 2647 5 2644 3 0 0 0 1 2647 6 3 234 1628 1100 0 0 1 2647 7 2644 10 0 0 0 0 0 1 2647 9 2644 561 1736 2 0 0 0 0 0 1 2657 1 2654 1 2657 2 3 2652 1 2657 3 2654 3 0 1 2657 4 3 1910 2 0 1 2657 5 2654 8 0 0 0 1 2657 6 3 1392 1071 1723 1 0 1 2657 7 2654 13 0 0 0 0 0 1 2657 9 2654 370 538 1 0 0 0 0 0 1 2659 1 2657 1 2659 2 2 2658 1 2659 3 2657 4 0 1 2659 4 2 1570 2 0 1 2659 5 2657 13 0 0 0 1 2659 6 2 35 998 1901 0 0 1 2659 7 2657 28 0 0 0 0 0 1 2659 9 2657 629 1806 10 0 0 0 0 0 1 2663 1 2658 1 2663 2 5 2655 1 2663 3 2658 12 0 1 2663 4 5 2263 3 0 1 2663 5 2658 3 0 0 0 1 2663 6 5 2428 772 1799 1 0 1 2663 7 2658 1 0 0 0 0 0 1 2663 9 2658 556 349 4 0 0 0 0 0 1 2671 1 2664 1 2671 2 7 2662 1 2671 3 2664 7 0 1 2671 4 7 2226 2 0 1 2671 5 2664 1 0 0 0 1 2671 6 7 2007 1802 2472 0 0 1 2671 7 2664 2 0 0 0 0 0 1 2671 9 2664 338 2358 16 0 0 0 0 0 1 2677 1 2675 1 2677 2 2 2676 1 2677 3 2675 2 0 1 2677 4 2 2358 6 0 1 2677 5 2675 8 0 0 0 1 2677 6 2 271 1113 723 0 0 1 2677 7 2675 14 0 0 0 0 0 1 2677 9 2675 1934 1971 11 0 0 0 0 0 1 2683 1 2681 1 2683 2 2 2679 1 2683 3 2681 13 0 1 2683 4 2 1386 8 0 1 2683 5 2681 7 0 0 0 1 2683 6 2 170 125 1906 0 0 1 2683 7 2681 2 0 0 0 0 0 1 2683 9 2681 259 997 8 0 0 0 0 0 1 2687 1 2682 1 2687 2 5 2686 1 2687 3 2682 1 0 1 2687 4 5 1568 2 0 1 2687 5 2682 7 0 0 0 1 2687 6 5 772 1402 1390 1 0 1 2687 7 2682 7 0 0 0 0 0 1 2687 9 2682 726 2286 3 0 0 0 0 0 1 2689 1 2670 1 2689 2 19 2684 1 2689 3 2670 2 0 1 2689 4 19 1679 24 0 1 2689 5 2670 4 0 0 0 1 2689 6 19 1942 2441 2393 0 0 1 2693 1 2691 1 2693 2 2 2688 1 2693 3 2691 2 0 1 2693 4 2 2281 0 0 1 2693 5 2691 7 0 0 0 1 2693 6 2 1940 68 2650 1 0 1 2693 7 2691 21 0 0 0 0 0 1 2693 9 2691 205 1843 3 0 0 0 0 0 1 2699 1 2697 1 2699 2 2 2693 1 2699 3 2697 2 0 1 2699 4 2 1520 4 0 1 2699 5 2697 8 0 0 0 1 2699 6 2 2046 773 2361 1 0 1 2699 7 2697 2 0 0 0 0 0 1 2699 9 2697 440 1133 5 0 0 0 0 0 1 2707 1 2705 1 2707 2 2 2706 1 2707 3 2705 7 0 1 2707 4 2 1560 2 0 1 2707 5 2705 2 0 0 0 1 2707 6 2 1133 2011 2594 0 0 1 2707 7 2705 13 0 0 0 0 0 1 2707 9 2705 466 2339 19 0 0 0 0 0 1 2711 1 2704 1 2711 2 7 2710 1 2711 3 2704 1 0 1 2711 4 7 1442 2 0 1 2711 5 2704 1 0 0 0 1 2711 6 7 2519 102 1774 1 0 1 2711 7 2704 5 0 0 0 0 0 1 2711 9 2704 2424 2482 0 0 0 0 0 0 1 2713 1 2708 1 2713 2 5 2712 1 2713 3 2708 1 0 1 2713 4 5 2548 6 0 1 2713 5 2708 1 0 0 0 1 2713 6 5 2518 1036 1920 0 0 1 2713 7 2708 11 0 0 0 0 0 1 2713 9 2708 1291 2050 3 0 0 0 0 0 1 2719 1 2716 1 2719 2 3 2718 1 2719 3 2716 4 0 1 2719 4 3 2480 3 0 1 2719 5 2716 19 0 0 0 1 2719 6 3 1769 441 689 1 0 1 2719 7 2716 8 0 0 0 0 0 1 2719 9 2716 1481 2154 2 0 0 0 0 0 1 2729 1 2726 1 2729 2 3 2723 1 2729 3 2726 4 0 1 2729 4 3 2717 0 0 1 2729 5 2726 1 0 0 0 1 2729 6 3 1424 213 2547 1 0 1 2729 7 2726 1 0 0 0 0 0 1 2729 9 2726 1869 1348 0 0 0 0 0 0 1 2731 1 2728 1 2731 2 3 2722 1 2731 3 2728 3 0 1 2731 4 3 2591 2 0 1 2731 5 2728 10 0 0 0 1 2731 6 3 1404 1520 512 0 0 1 2731 7 2728 7 0 0 0 0 0 1 2731 9 2728 2672 1637 1 0 0 0 0 0 1 2741 1 2739 1 2741 2 2 2737 1 2741 3 2739 3 0 1 2741 4 2 2507 12 0 1 2741 5 2739 8 0 0 0 1 2741 6 2 1311 1967 1856 1 0 1 2741 7 2739 5 0 0 0 0 0 1 2741 9 2739 2251 1666 5 0 0 0 0 0 1 2749 1 2743 1 2749 2 6 2741 1 2749 3 2743 1 0 1 2749 4 6 1695 0 0 1 2749 5 2743 20 0 0 0 1 2749 6 6 465 1636 767 0 0 1 2749 7 2743 6 0 0 0 0 0 1 2749 9 2743 2573 2665 10 0 0 0 0 0 1 2753 1 2750 1 2753 2 3 2747 1 2753 3 2750 5 0 1 2753 4 3 1947 9 0 1 2753 5 2750 4 0 0 0 1 2753 6 3 1153 1520 1673 3 0 1 2753 7 2750 4 0 0 0 0 0 1 2753 9 2750 1096 788 4 0 0 0 0 0 1 2767 1 2764 1 2767 2 3 2766 1 2767 3 2764 15 0 1 2767 4 3 2422 5 0 1 2767 5 2764 3 0 0 0 1 2767 6 3 1940 1828 1310 0 0 1 2767 7 2764 1 0 0 0 0 0 1 2767 9 2764 2582 2742 5 0 0 0 0 0 1 2777 1 2774 1 2777 2 3 2772 1 2777 3 2774 1 0 1 2777 4 3 1801 0 0 1 2777 5 2774 1 0 0 0 1 2777 6 3 1761 1143 1344 4 0 1 2777 7 2774 17 0 0 0 0 0 1 2777 9 2774 2399 2419 2 0 0 0 0 0 1 2789 1 2787 1 2789 2 2 2783 1 2789 3 2787 3 0 1 2789 4 2 2423 3 0 1 2789 5 2787 4 0 0 0 1 2789 6 2 2433 781 1923 1 0 1 2789 7 2787 5 0 0 0 0 0 1 2789 9 2787 1610 1475 3 0 0 0 0 0 1 2791 1 2785 1 2791 2 6 2789 1 2791 3 2785 7 0 1 2791 4 6 1653 3 0 1 2791 5 2785 19 0 0 0 1 2791 6 6 1742 1391 1876 0 0 1 2791 7 2785 9 0 0 0 0 0 1 2791 9 2785 1355 2415 3 0 0 0 0 0 1 2797 1 2795 1 2797 2 2 2793 1 2797 3 2795 6 0 1 2797 4 2 2145 9 0 1 2797 5 2795 2 0 0 0 1 2797 6 2 2785 2779 2793 0 0 1 2801 1 2798 1 2801 2 3 2800 1 2801 3 2798 1 0 1 2801 4 3 1614 7 0 1 2801 5 2798 3 0 0 0 1 2801 6 3 964 2436 600 1 0 1 2801 7 2798 6 0 0 0 0 0 1 2801 9 2798 410 1893 2 0 0 0 0 0 1 2803 1 2801 1 2803 2 2 2802 1 2803 3 2801 4 0 1 2803 4 2 2468 16 0 1 2803 5 2801 9 0 0 0 1 2803 6 2 917 2197 1394 0 0 1 2803 7 2801 4 0 0 0 0 0 1 2803 9 2801 179 1929 0 0 0 0 0 0 1 2819 1 2817 1 2819 2 2 2814 1 2819 3 2817 3 0 1 2819 4 2 2651 3 0 1 2819 5 2817 9 0 0 0 1 2819 6 2 1428 1252 2713 2 0 1 2819 7 2817 8 0 0 0 0 0 1 2819 9 2817 2516 1075 1 0 0 0 0 0 1 2833 1 2828 1 2833 2 5 2830 1 2833 3 2828 3 0 1 2833 4 5 2233 22 0 1 2833 5 2828 1 0 0 0 1 2833 6 5 2264 954 685 0 0 1 2837 1 2835 1 2837 2 2 2833 1 2837 3 2835 3 0 1 2837 4 2 2731 18 0 1 2837 5 2835 3 0 0 0 1 2837 6 2 1415 2694 2430 3 0 1 2837 7 2835 5 0 0 0 0 0 1 2837 9 2835 2419 2410 6 0 0 0 0 0 1 2843 1 2841 1 2843 2 2 2839 1 2843 3 2841 3 0 1 2843 4 2 2566 8 0 1 2843 5 2841 12 0 0 0 1 2843 6 2 2629 920 1618 1 0 1 2843 7 2841 5 0 0 0 0 0 1 2843 9 2841 2363 1669 0 0 0 0 0 0 1 2851 1 2849 1 2851 2 2 2847 1 2851 3 2849 12 0 1 2851 4 2 2674 8 0 1 2851 5 2849 3 0 0 0 1 2851 6 2 1398 200 509 0 0 1 2851 7 2849 5 0 0 0 0 0 1 2851 9 2849 656 2167 9 0 0 0 0 0 1 2857 1 2846 1 2857 2 11 2856 1 2857 3 2846 2 0 1 2857 4 11 2703 21 0 1 2857 5 2846 1 0 0 0 1 2857 6 11 1166 2012 2854 0 0 1 2857 7 2846 2 0 0 0 0 0 1 2857 9 2846 1833 2188 1 0 0 0 0 0 1 2861 1 2859 1 2861 2 2 2857 1 2861 3 2859 3 0 1 2861 4 2 1958 1 0 1 2861 5 2859 17 0 0 0 1 2861 6 2 424 459 2461 1 0 1 2861 7 2859 15 0 0 0 0 0 1 2861 9 2859 396 22 0 0 0 0 0 0 1 2879 1 2872 1 2879 2 7 2878 1 2879 3 2872 2 0 1 2879 4 7 1579 2 0 1 2879 5 2872 1 0 0 0 1 2879 6 7 1566 1144 2755 1 0 1 2879 7 2872 18 0 0 0 0 0 1 2879 9 2872 324 2154 0 0 0 0 0 0 1 2887 1 2882 1 2887 2 5 2885 1 2887 3 2882 1 0 1 2887 4 5 1657 9 0 1 2887 5 2882 16 0 0 0 1 2887 6 5 2797 2682 1171 0 0 1 2887 7 2882 9 0 0 0 0 0 1 2887 9 2882 1265 1114 9 0 0 0 0 0 1 2897 1 2894 1 2897 2 3 2891 1 2897 3 2894 3 0 1 2897 4 3 1560 1 0 1 2897 5 2894 9 0 0 0 1 2897 6 3 964 2504 1785 3 0 1 2897 7 2894 18 0 0 0 0 0 1 2897 9 2894 1011 2818 1 0 0 0 0 0 1 2903 1 2898 1 2903 2 5 2902 1 2903 3 2898 1 0 1 2903 4 5 2291 4 0 1 2903 5 2898 11 0 0 0 1 2903 6 5 2600 757 324 3 0 1 2903 7 2898 9 0 0 0 0 0 1 2903 9 2898 2226 558 1 0 0 0 0 0 1 2909 1 2907 1 2909 2 2 2900 1 2909 3 2907 2 0 1 2909 4 2 2786 1 0 1 2909 5 2907 6 0 0 0 1 2909 6 2 1025 2659 683 1 0 1 2909 7 2907 5 0 0 0 0 0 1 2909 9 2907 2338 681 0 0 0 0 0 0 1 2917 1 2912 1 2917 2 5 2916 1 2917 3 2912 2 0 1 2917 4 5 1860 3 0 1 2917 5 2912 2 0 0 0 1 2917 6 5 2643 1589 2181 1 0 1 2917 7 2912 1 0 0 0 0 0 1 2917 9 2912 914 2767 0 0 0 0 0 0 1 2927 1 2922 1 2927 2 5 2925 1 2927 3 2922 7 0 1 2927 4 5 2446 10 0 1 2927 5 2922 3 0 0 0 1 2927 6 5 1521 1142 2191 1 0 1 2927 7 2922 10 0 0 0 0 0 1 2927 9 2922 1741 428 5 0 0 0 0 0 1 2939 1 2937 1 2939 2 2 2938 1 2939 3 2937 3 0 1 2939 4 2 1878 13 0 1 2939 5 2937 5 0 0 0 1 2939 6 2 875 2840 2808 1 0 1 2939 7 2937 20 0 0 0 0 0 1 2939 9 2937 514 1940 1 0 0 0 0 0 1 2953 1 2940 1 2953 2 13 2952 1 2953 3 2940 5 0 1 2953 4 13 2109 14 0 1 2953 5 2940 1 0 0 0 1 2953 6 13 1904 94 702 1 0 1 2953 7 2940 31 0 0 0 0 0 1 2953 9 2940 1830 2020 10 0 0 0 0 0 1 2957 1 2955 1 2957 2 2 2956 1 2957 3 2955 2 0 1 2957 4 2 2502 6 0 1 2957 5 2955 6 0 0 0 1 2957 6 2 2223 2582 2361 1 0 1 2957 7 2955 5 0 0 0 0 0 1 2957 9 2955 1274 2653 4 0 0 0 0 0 1 2963 1 2961 1 2963 2 2 2959 1 2963 3 2961 3 0 1 2963 4 2 1600 8 0 1 2963 5 2961 5 0 0 0 1 2963 6 2 2724 1929 1507 1 0 1 2963 7 2961 17 0 0 0 0 0 1 2963 9 2961 2845 2121 9 0 0 0 0 0 1 2969 1 2966 1 2969 2 3 2968 1 2969 3 2966 3 0 1 2969 4 3 2702 4 0 1 2969 5 2966 3 0 0 0 1 2969 6 3 212 181 1690 1 0 1 2969 7 2966 4 0 0 0 0 0 1 2969 9 2966 2846 1727 0 0 0 0 0 0 1 2971 1 2961 1 2971 2 10 2970 1 2971 3 2961 2 0 1 2971 4 10 1931 5 0 1 2971 5 2961 5 0 0 0 1 2971 6 10 905 1121 2893 0 0 1 2971 7 2961 8 0 0 0 0 0 1 2971 9 2961 1724 2610 15 0 0 0 0 0 1 2999 1 2982 1 2999 2 17 2995 1 2999 3 2982 4 0 1 2999 4 17 2779 12 0 1 2999 5 2982 8 0 0 0 1 2999 6 17 2843 164 1108 7 0 1 2999 7 2982 3 0 0 0 0 0 1 2999 9 2982 506 1970 7 0 0 0 0 0 1 3001 1 2987 1 3001 2 14 2999 1 3001 3 2987 2 0 1 3001 4 14 2975 15 0 1 3001 5 2987 1 0 0 0 1 3001 6 14 1887 1943 1408 2 0 1 3001 7 2987 1 0 0 0 0 0 1 3001 9 2987 639 1829 0 0 0 0 0 0 1 3011 1 3009 1 3011 2 2 3007 1 3011 3 3009 3 0 1 3011 4 2 2235 7 0 1 3011 5 3009 4 0 0 0 1 3011 6 2 452 208 2613 1 0 1 3011 7 3009 2 0 0 0 0 0 1 3011 9 3009 1678 2158 1 0 0 0 0 0 1 3019 1 3017 1 3019 2 2 3015 1 3019 3 3017 4 0 1 3019 4 2 2924 8 0 1 3019 5 3017 4 0 0 0 1 3019 6 2 2983 1076 2099 0 0 1 3023 1 3018 1 3023 2 5 3021 1 3023 3 3018 2 0 1 3023 4 5 3019 3 0 1 3023 5 3018 9 0 0 0 1 3023 6 5 731 1273 1407 1 0 1 3023 7 3018 8 0 0 0 0 0 1 3023 9 3018 104 971 0 0 0 0 0 0 1 3037 1 3035 1 3037 2 2 3036 1 3037 3 3035 2 0 1 3037 4 2 1881 9 0 1 3037 5 3035 5 0 0 0 1 3037 6 2 2415 1532 928 0 0 1 3037 7 3035 22 0 0 0 0 0 1 3037 9 3035 272 2593 4 0 0 0 0 0 1 3041 1 3038 1 3041 2 3 3030 1 3041 3 3038 1 0 1 3041 4 3 2059 8 0 1 3041 5 3038 1 0 0 0 1 3041 6 3 1279 1713 2942 4 0 1 3041 7 3038 6 0 0 0 0 0 1 3041 9 3038 2606 1279 0 0 0 0 0 0 1 3049 1 3038 1 3049 2 11 3048 1 3049 3 3038 3 0 1 3049 4 11 2806 27 0 1 3049 5 3038 5 0 0 0 1 3049 6 11 453 1501 2406 0 0 1 3049 7 3038 2 0 0 0 0 0 1 3049 9 3038 1727 1617 3 0 0 0 0 0 1 3061 1 3055 1 3061 2 6 3057 1 3061 3 3055 2 0 1 3061 4 6 2404 10 0 1 3061 5 3055 12 0 0 0 1 3061 6 6 2164 914 1417 1 0 1 3061 7 3055 1 0 0 0 0 0 1 3061 9 3055 704 1540 0 0 0 0 0 0 1 3067 1 3065 1 3067 2 2 3063 1 3067 3 3065 4 0 1 3067 4 2 2516 8 0 1 3067 5 3065 5 0 0 0 1 3067 6 2 2295 2309 2709 0 0 1 3067 7 3065 2 0 0 0 0 0 1 3067 9 3065 304 1495 12 0 0 0 0 0 1 3079 1 3073 1 3079 2 6 3078 1 3079 3 3073 1 0 1 3079 4 6 2775 3 0 1 3079 5 3073 2 0 0 0 1 3079 6 6 2589 1176 1907 0 0 1 3079 7 3073 4 0 0 0 0 0 1 3079 9 3073 513 1559 2 0 0 0 0 0 1 3083 1 3081 1 3083 2 2 3079 1 3083 3 3081 2 0 1 3083 4 2 1589 11 0 1 3083 5 3081 5 0 0 0 1 3083 6 2 1552 662 2261 5 0 1 3083 7 3081 20 0 0 0 0 0 1 3083 9 3081 124 2 6 0 0 0 0 0 1 3089 1 3086 1 3089 2 3 3082 1 3089 3 3086 3 0 1 3089 4 3 3009 1 0 1 3089 5 3086 5 0 0 0 1 3089 6 3 822 2198 2929 5 0 1 3089 7 3086 22 0 0 0 0 0 1 3089 9 3086 1304 2593 1 0 0 0 0 0 1 3109 1 3103 1 3109 2 6 3105 1 3109 3 3103 4 0 1 3109 4 6 3105 6 0 1 3109 5 3103 3 0 0 0 1 3109 6 6 174 2325 2041 0 0 1 3109 7 3103 8 0 0 0 0 0 1 3109 9 3103 2388 1654 18 0 0 0 0 0 1 3119 1 3112 1 3119 2 7 3118 1 3119 3 3112 8 0 1 3119 4 7 2052 3 0 1 3119 5 3112 1 0 0 0 1 3119 6 7 2363 2315 1459 1 0 1 3119 7 3112 1 0 0 0 0 0 1 3119 9 3112 1849 450 1 0 0 0 0 0 1 3121 1 3114 1 3121 2 7 3114 1 3121 3 3114 1 0 1 3121 4 7 1779 0 0 1 3121 5 3114 1 0 0 0 1 3121 6 7 1798 478 2851 0 0 1 3121 7 3114 5 0 0 0 0 0 1 3121 9 3114 2996 1972 11 0 0 0 0 0 1 3137 1 3134 1 3137 2 3 3131 1 3137 3 3134 4 0 1 3137 4 3 2714 1 0 1 3137 5 3134 15 0 0 0 1 3137 6 3 3061 2685 3099 1 0 1 3137 7 3134 23 0 0 0 0 0 1 3137 9 3134 610 703 8 0 0 0 0 0 1 3163 1 3160 1 3163 2 3 3162 1 3163 3 3160 4 0 1 3163 4 3 1675 5 0 1 3163 5 3160 6 0 0 0 1 3163 6 3 1181 2392 3096 0 0 1 3167 1 3162 1 3167 2 5 3164 1 3167 3 3162 1 0 1 3167 4 5 1750 4 0 1 3167 5 3162 5 0 0 0 1 3167 6 5 1333 321 2821 1 0 1 3167 7 3162 13 0 0 0 0 0 1 3167 9 3162 2779 2174 1 0 0 0 0 0 1 3169 1 3162 1 3169 2 7 3162 1 3169 3 3162 1 0 1 3169 4 7 2295 0 0 1 3169 5 3162 8 0 0 0 1 3169 6 7 2744 731 3147 0 0 1 3169 7 3162 10 0 0 0 0 0 1 3169 9 3162 2562 1570 9 0 0 0 0 0 1 3181 1 3174 1 3181 2 7 3179 1 3181 3 3174 4 0 1 3181 4 7 1885 4 0 1 3181 5 3174 1 0 0 0 1 3181 6 7 937 2559 801 0 0 1 3181 7 3174 1 0 0 0 0 0 1 3181 9 3174 2312 2637 4 0 0 0 0 0 1 3187 1 3185 1 3187 2 2 3183 1 3187 3 3185 5 0 1 3187 4 2 1795 8 0 1 3187 5 3185 3 0 0 0 1 3187 6 2 134 564 1147 0 0 1 3187 7 3185 7 0 0 0 0 0 1 3187 9 3185 2880 1947 5 0 0 0 0 0 1 3191 1 3180 1 3191 2 11 3189 1 3191 3 3180 6 0 1 3191 4 11 1986 5 0 1 3191 5 3180 4 0 0 0 1 3191 6 11 1308 2065 2741 2 0 1 3191 7 3180 1 0 0 0 0 0 1 3191 9 3180 1632 2601 7 0 0 0 0 0 1 3203 1 3201 1 3203 2 2 3199 1 3203 3 3201 3 0 1 3203 4 2 2883 16 0 1 3203 5 3201 18 0 0 0 1 3203 6 2 610 1778 248 1 0 1 3203 7 3201 4 0 0 0 0 0 1 3203 9 3201 2402 1490 1 0 0 0 0 0 1 3209 1 3206 1 3209 2 3 3204 1 3209 3 3206 3 0 1 3209 4 3 2273 2 0 1 3209 5 3206 12 0 0 0 1 3209 6 3 911 304 2745 1 0 1 3217 1 3212 1 3217 2 5 3212 1 3217 3 3212 1 0 1 3217 4 5 2588 15 0 1 3217 5 3212 1 0 0 0 1 3217 6 5 1673 2408 2630 0 0 1 3217 7 3212 5 0 0 0 0 0 1 3217 9 3212 1567 3004 6 0 0 0 0 0 1 3221 1 3211 1 3221 2 10 3211 1 3221 3 3211 2 0 1 3221 4 10 1741 8 0 1 3221 5 3211 4 0 0 0 1 3221 6 10 2289 3027 2712 1 0 1 3221 7 3211 5 0 0 0 0 0 1 3221 9 3211 1296 1226 5 0 0 0 0 0 1 3229 1 3223 1 3229 2 6 3221 1 3229 3 3223 1 0 1 3229 4 6 3001 0 0 1 3229 5 3223 6 0 0 0 1 3229 6 6 2758 3091 1986 2 0 1 3229 7 3223 2 0 0 0 0 0 1 3229 9 3223 586 2272 18 0 0 0 0 0 1 3251 1 3245 1 3251 2 6 3249 1 3251 3 3245 1 0 1 3251 4 6 3241 7 0 1 3251 5 3245 7 0 0 0 1 3251 6 6 1634 696 2665 2 0 1 3251 7 3245 2 0 0 0 0 0 1 3251 9 3245 1022 2372 11 0 0 0 0 0 1 3253 1 3251 1 3253 2 2 3252 1 3253 3 3251 2 0 1 3253 4 2 2830 3 0 1 3253 5 3251 3 0 0 0 1 3253 6 2 1160 736 2923 0 0 1 3253 7 3251 8 0 0 0 0 0 1 3253 9 3251 1654 2858 3 0 0 0 0 0 1 3257 1 3254 1 3257 2 3 3252 1 3257 3 3254 1 0 1 3257 4 3 2302 0 0 1 3257 5 3254 20 0 0 0 1 3257 6 3 1992 1026 2176 2 0 1 3257 7 3254 22 0 0 0 0 0 1 3257 9 3254 2081 1711 1 0 0 0 0 0 1 3259 1 3256 1 3259 2 3 3248 1 3259 3 3256 6 0 1 3259 4 3 2888 4 0 1 3259 5 3256 17 0 0 0 1 3259 6 3 2050 892 1791 0 0 1 3259 7 3256 1 0 0 0 0 0 1 3259 9 3256 2286 3016 3 0 0 0 0 0 1 3271 1 3268 1 3271 2 3 3269 1 3271 3 3268 1 0 1 3271 4 3 2843 3 0 1 3271 5 3268 1 0 0 0 1 3271 6 3 959 2172 3031 0 0 1 3271 7 3268 4 0 0 0 0 0 1 3271 9 3268 1765 3006 11 0 0 0 0 0 1 3299 1 3297 1 3299 2 2 3293 1 3299 3 3297 2 0 1 3299 4 2 1855 0 0 1 3299 5 3297 8 0 0 0 1 3299 6 2 1901 1806 965 1 0 1 3299 7 3297 7 0 0 0 0 0 1 3299 9 3297 2403 100 1 0 0 0 0 0 1 3301 1 3295 1 3301 2 6 3297 1 3301 3 3295 2 0 1 3301 4 6 1754 2 0 1 3301 5 3295 2 0 0 0 1 3301 6 6 893 732 2883 0 0 1 3301 7 3295 6 0 0 0 0 0 1 3301 9 3295 2830 3284 9 0 0 0 0 0 1 3307 1 3305 1 3307 2 2 3306 1 3307 3 3305 2 0 1 3307 4 2 2555 2 0 1 3307 5 3305 9 0 0 0 1 3307 6 2 1264 2264 1625 0 0 1 3307 7 3305 7 0 0 0 0 0 1 3307 9 3305 2128 2558 2 0 0 0 0 0 1 3313 1 3303 1 3313 2 10 3312 1 3313 3 3303 15 0 1 3313 4 10 3105 6 0 1 3313 5 3303 5 0 0 0 1 3313 6 10 2527 1900 3133 0 0 1 3313 7 3303 5 0 0 0 0 0 1 3313 9 3303 193 1954 8 0 0 0 0 0 1 3319 1 3313 1 3319 2 6 3317 1 3319 3 3313 3 0 1 3319 4 6 3309 7 0 1 3319 5 3313 12 0 0 0 1 3319 6 6 3276 833 1883 0 0 1 3319 7 3313 1 0 0 0 0 0 1 3319 9 3313 2553 2265 6 0 0 0 0 0 1 3323 1 3321 1 3323 2 2 3319 1 3323 3 3321 2 0 1 3323 4 2 2982 7 0 1 3323 5 3321 3 0 0 0 1 3323 6 2 1089 591 1836 1 0 1 3323 7 3321 4 0 0 0 0 0 1 3323 9 3321 987 1801 0 0 0 0 0 0 1 3329 1 3326 1 3329 2 3 3328 1 3329 3 3326 5 0 1 3329 4 3 3247 7 0 1 3329 5 3326 9 0 0 0 1 3329 6 3 631 1163 1915 1 0 1 3329 7 3326 7 0 0 0 0 0 1 3329 9 3326 982 204 3 0 0 0 0 0 1 3331 1 3328 1 3331 2 3 3322 1 3331 3 3328 1 0 1 3331 4 3 1902 7 0 1 3331 5 3328 5 0 0 0 1 3331 6 3 419 756 2615 0 0 1 3343 1 3338 1 3343 2 5 3342 1 3343 3 3338 10 0 1 3343 4 5 3261 3 0 1 3343 5 3338 15 0 0 0 1 3343 6 5 1284 436 3081 0 0 1 3343 7 3338 10 0 0 0 0 0 1 3343 9 3338 1109 2343 16 0 0 0 0 0 1 3347 1 3345 1 3347 2 2 3343 1 3347 3 3345 3 0 1 3347 4 2 2846 7 0 1 3347 5 3345 6 0 0 0 1 3347 6 2 1196 1277 1699 1 0 1 3347 7 3345 3 0 0 0 0 0 1 3347 9 3345 1310 551 4 0 0 0 0 0 1 3359 1 3348 1 3359 2 11 3357 1 3359 3 3348 2 0 1 3359 4 11 3075 3 0 1 3359 5 3348 2 0 0 0 1 3359 6 11 1811 2201 3024 1 0 1 3359 7 3348 5 0 0 0 0 0 1 3359 9 3348 3082 3330 6 0 0 0 0 0 1 3361 1 3339 1 3361 2 22 3360 1 3361 3 3339 4 0 1 3361 4 22 1909 12 0 1 3361 5 3339 5 0 0 0 1 3361 6 22 429 102 468 0 0 1 3361 7 3339 5 0 0 0 0 0 1 3361 9 3339 3147 1704 5 0 0 0 0 0 1 3371 1 3369 1 3371 2 2 3366 1 3371 3 3369 2 0 1 3371 4 2 2291 3 0 1 3371 5 3369 4 0 0 0 1 3371 6 2 2408 1283 2758 3 0 1 3373 1 3368 1 3373 2 5 3372 1 3373 3 3368 2 0 1 3373 4 5 3354 20 0 1 3373 5 3368 1 0 0 0 1 3373 6 5 1701 2205 2230 0 0 1 3389 1 3386 1 3389 2 3 3387 1 3389 3 3386 6 0 1 3389 4 3 3385 4 0 1 3389 5 3386 4 0 0 0 1 3389 6 3 2246 619 3370 3 0 1 3391 1 3388 1 3391 2 3 3389 1 3391 3 3388 7 0 1 3391 4 3 2209 6 0 1 3391 5 3388 5 0 0 0 1 3391 6 3 38 1728 3156 0 0 1 3407 1 3402 1 3407 2 5 3405 1 3407 3 3402 2 0 1 3407 4 5 2792 5 0 1 3407 5 3402 22 0 0 0 1 3407 6 5 1933 3127 1959 1 0 1 3413 1 3411 1 3413 2 2 3405 1 3413 3 3411 5 0 1 3413 4 2 2381 5 0 1 3413 5 3411 9 0 0 0 1 3413 6 2 1557 3367 2318 2 0 1 3433 1 3428 1 3433 2 5 3432 1 3433 3 3428 5 0 1 3433 4 5 1930 6 0 1 3433 5 3428 1 0 0 0 1 3433 6 5 2465 1603 1777 0 0 1 3449 1 3446 1 3449 2 3 3448 1 3449 3 3446 4 0 1 3449 4 3 2833 7 0 1 3449 5 3446 7 0 0 0 1 3449 6 3 1525 1591 526 1 0 1 3457 1 3450 1 3457 2 7 3454 1 3457 3 3450 8 0 1 3457 4 7 2376 8 0 1 3457 5 3450 8 0 0 0 1 3457 6 7 3136 2416 3421 0 0 1 3461 1 3459 1 3461 2 2 3460 1 3461 3 3459 3 0 1 3461 4 2 3161 3 0 1 3461 5 3459 9 0 0 0 1 3461 6 2 1077 1453 3380 1 0 1 3463 1 3460 1 3463 2 3 3461 1 3463 3 3460 5 0 1 3463 4 3 3459 4 0 1 3463 5 3460 1 0 0 0 1 3463 6 3 2512 2050 491 0 0 1 3467 1 3465 1 3467 2 2 3455 1 3467 3 3465 4 0 1 3467 4 2 2489 15 0 1 3467 5 3465 2 0 0 0 1 3467 6 2 1625 364 3455 1 0 1 3469 1 3467 1 3469 2 2 3465 1 3469 3 3467 6 0 1 3469 4 2 2383 12 0 1 3469 5 3467 3 0 0 0 1 3469 6 2 3457 3451 3465 0 0 1 3491 1 3489 1 3491 2 2 3490 1 3491 3 3489 3 0 1 3491 4 2 1980 2 0 1 3491 5 3489 6 0 0 0 1 3491 6 2 681 1056 2910 2 0 1 3499 1 3497 1 3499 2 2 3498 1 3499 3 3497 4 0 1 3499 4 2 3149 6 0 1 3499 5 3497 6 0 0 0 1 3499 6 2 1570 3394 2404 0 0 1 3511 1 3504 1 3511 2 7 3508 1 3511 3 3504 1 0 1 3511 4 7 2456 5 0 1 3511 5 3504 1 0 0 0 1 3511 6 7 1811 3091 2649 0 0 1 3517 1 3515 1 3517 2 2 3516 1 3517 3 3515 2 0 1 3517 4 2 2895 3 0 1 3517 5 3515 2 0 0 0 1 3517 6 2 646 1777 3426 0 0 1 3527 1 3522 1 3527 2 5 3526 1 3527 3 3522 2 0 1 3527 4 5 2323 2 0 1 3527 5 3522 2 0 0 0 1 3527 6 5 766 3357 2445 2 0 1 3529 1 3512 1 3529 2 17 3525 1 3529 3 3512 1 0 1 3529 4 17 1957 21 0 1 3529 5 3512 9 0 0 0 1 3529 6 17 559 3222 338 0 0 1 3533 1 3531 1 3533 2 2 3532 1 3533 3 3531 2 0 1 3533 4 2 3345 3 0 1 3533 5 3531 5 0 0 0 1 3533 6 2 746 1540 1167 2 0 1 3539 1 3537 1 3539 2 2 3525 1 3539 3 3537 2 0 1 3539 4 2 3080 4 0 1 3539 5 3537 8 0 0 0 1 3539 6 2 294 3273 2694 1 0 1 3541 1 3534 1 3541 2 7 3535 1 3541 3 3534 1 0 1 3541 4 7 3537 4 0 1 3541 5 3534 4 0 0 0 1 3541 6 7 1620 3281 2886 0 0 1 3547 1 3545 1 3547 2 2 3546 1 3547 3 3545 2 0 1 3547 4 2 3540 8 0 1 3547 5 3545 6 0 0 0 1 3547 6 2 3029 624 2127 0 0 1 3557 1 3555 1 3557 2 2 3553 1 3557 3 3555 3 0 1 3557 4 2 3127 12 0 1 3557 5 3555 4 0 0 0 1 3557 6 2 2418 1690 2780 1 0 1 3559 1 3556 1 3559 2 3 3558 1 3559 3 3556 1 0 1 3559 4 3 1956 2 0 1 3559 5 3556 3 0 0 0 1 3559 6 3 3488 412 1908 0 0 1 3571 1 3569 1 3571 2 2 3567 1 3571 3 3569 2 0 1 3571 4 2 2653 8 0 1 3571 5 3569 2 0 0 0 1 3571 6 2 1424 2222 3504 0 0 1 3581 1 3579 1 3581 2 2 3577 1 3581 3 3579 3 0 1 3581 4 2 2125 6 0 1 3581 5 3579 14 0 0 0 1 3581 6 2 1283 1744 316 2 0 1 3583 1 3580 1 3583 2 3 3582 1 3583 3 3580 11 0 1 3583 4 3 3572 12 0 1 3583 5 3580 1 0 0 0 1 3583 6 3 549 607 2464 0 0 1 3593 1 3590 1 3593 2 3 3585 1 3593 3 3590 1 0 1 3593 4 3 3195 2 0 1 3593 5 3590 6 0 0 0 1 3593 6 3 3077 1496 2356 1 0 1 3607 1 3602 1 3607 2 5 3605 1 3607 3 3602 1 0 1 3607 4 5 2930 17 0 1 3607 5 3602 10 0 0 0 1 3607 6 5 3486 3024 913 2 0 1 3613 1 3611 1 3613 2 2 3609 1 3613 3 3611 5 0 1 3613 4 2 3295 9 0 1 3613 5 3611 14 0 0 0 1 3613 6 2 1181 2771 2217 0 0 1 3617 1 3614 1 3617 2 3 3605 1 3617 3 3614 1 0 1 3617 4 3 2714 0 0 1 3617 5 3614 4 0 0 0 1 3617 6 3 825 2384 42 1 0 1 3623 1 3618 1 3623 2 5 3616 1 3623 3 3618 3 0 1 3623 4 5 1865 2 0 1 3623 5 3618 12 0 0 0 1 3623 6 5 3350 1960 2559 3 0 1 3631 1 3616 1 3631 2 15 3630 1 3631 3 3616 1 0 1 3631 4 15 3231 5 0 1 3631 5 3616 3 0 0 0 1 3631 6 15 2672 2089 3556 0 0 1 3637 1 3635 1 3637 2 2 3630 1 3637 3 3635 5 0 1 3637 4 2 1942 12 0 1 3637 5 3635 7 0 0 0 1 3637 6 2 3284 865 1745 0 0 1 3643 1 3641 1 3643 2 2 3642 1 3643 3 3641 5 0 1 3643 4 2 2103 2 0 1 3643 5 3641 3 0 0 0 1 3643 6 2 2646 2013 2118 0 0 1 3659 1 3657 1 3659 2 2 3658 1 3659 3 3657 4 0 1 3659 4 2 2273 4 0 1 3659 5 3657 2 0 0 0 1 3659 6 2 1806 2084 2998 2 0 1 3671 1 3658 1 3671 2 13 3667 1 3671 3 3658 4 0 1 3671 4 13 3010 6 0 1 3671 5 3658 9 0 0 0 1 3671 6 13 1907 728 579 4 0 1 3673 1 3668 1 3673 2 5 3670 1 3673 3 3668 5 0 1 3673 4 5 2625 10 0 1 3673 5 3668 2 0 0 0 1 3673 6 5 54 1117 3020 0 0 1 3677 1 3675 1 3677 2 2 3673 1 3677 3 3675 3 0 1 3677 4 2 2118 6 0 1 3677 5 3675 2 0 0 0 1 3677 6 2 3242 690 3160 2 0 1 3691 1 3689 1 3691 2 2 3685 1 3691 3 3689 2 0 1 3691 4 2 3456 11 0 1 3691 5 3689 9 0 0 0 1 3691 6 2 2293 2814 3611 0 0 1 3697 1 3692 1 3697 2 5 3692 1 3697 3 3692 1 0 1 3697 4 5 2023 15 0 1 3697 5 3692 1 0 0 0 1 3697 6 5 2968 780 3552 0 0 1 3701 1 3699 1 3701 2 2 3697 1 3701 3 3699 3 0 1 3701 4 2 2072 1 0 1 3701 5 3699 7 0 0 0 1 3701 6 2 2528 2741 2061 2 0 1 3709 1 3707 1 3709 2 2 3708 1 3709 3 3707 6 0 1 3709 4 2 2816 3 0 1 3709 5 3707 3 0 0 0 1 3709 6 2 2504 2011 181 0 0 1 3719 1 3712 1 3719 2 7 3716 1 3719 3 3712 5 0 1 3719 4 7 3402 7 0 1 3719 5 3712 9 0 0 0 1 3719 6 7 1864 1919 3182 3 0 1 3727 1 3724 1 3727 2 3 3725 1 3727 3 3724 3 0 1 3727 4 3 2722 3 0 1 3727 5 3724 11 0 0 0 1 3727 6 3 2653 1052 1194 0 0 1 3733 1 3731 1 3733 2 2 3729 1 3733 3 3731 6 0 1 3733 4 2 3404 6 0 1 3733 5 3731 11 0 0 0 1 3733 6 2 3721 3715 3729 0 0 1 3739 1 3732 1 3739 2 7 3736 1 3739 3 3732 11 0 1 3739 4 7 2830 1 0 1 3739 5 3732 1 0 0 0 1 3739 6 7 3724 475 2935 0 0 1 3761 1 3758 1 3761 2 3 3760 1 3761 3 3758 4 0 1 3761 4 3 3323 4 0 1 3761 5 3758 8 0 0 0 1 3761 6 3 2793 2314 272 3 0 1 3767 1 3762 1 3767 2 5 3765 1 3767 3 3762 1 0 1 3767 4 5 2094 5 0 1 3767 5 3762 2 0 0 0 1 3767 6 5 2774 504 2920 1 0 1 3769 1 3762 1 3769 2 7 3751 1 3769 3 3762 1 0 1 3769 4 7 3487 4 0 1 3769 5 3762 2 0 0 0 1 3769 6 7 371 1049 2185 0 0 1 3779 1 3777 1 3779 2 2 3774 1 3779 3 3777 14 0 1 3779 4 2 2807 3 0 1 3779 5 3777 11 0 0 0 1 3779 6 2 158 3225 191 1 0 1 3793 1 3788 1 3793 2 5 3788 1 3793 3 3788 1 0 1 3793 4 5 3571 10 0 1 3793 5 3788 7 0 0 0 1 3793 6 5 2860 3155 3660 0 0 1 3797 1 3795 1 3797 2 2 3796 1 3797 3 3795 2 0 1 3797 4 2 3340 3 0 1 3797 5 3795 5 0 0 0 1 3797 6 2 3487 2754 1721 1 0 1 3803 1 3801 1 3803 2 2 3799 1 3803 3 3801 3 0 1 3803 4 2 2826 7 0 1 3803 5 3801 3 0 0 0 1 3803 6 2 2899 2520 2493 1 0 1 3821 1 3818 1 3821 2 3 3819 1 3821 3 3818 5 0 1 3821 4 3 2640 14 0 1 3821 5 3818 4 0 0 0 1 3821 6 3 242 2236 2523 2 0 1 3823 1 3820 1 3823 2 3 3822 1 3823 3 3820 3 0 1 3823 4 3 2316 18 0 1 3823 5 3820 3 0 0 0 1 3823 6 3 3256 688 2440 0 0 1 3833 1 3830 1 3833 2 3 3827 1 3833 3 3830 7 0 1 3833 4 3 2810 1 0 1 3833 5 3830 3 0 0 0 1 3833 6 3 2090 3555 3536 1 0 1 3847 1 3842 1 3847 2 5 3845 1 3847 3 3842 1 0 1 3847 4 5 2007 17 0 1 3847 5 3842 2 0 0 0 1 3847 6 5 2960 2951 3576 0 0 1 3851 1 3849 1 3851 2 2 3847 1 3851 3 3849 2 0 1 3851 4 2 2109 7 0 1 3851 5 3849 2 0 0 0 1 3851 6 2 538 2883 1595 1 0 1 3853 1 3851 1 3853 2 2 3852 1 3853 3 3851 2 0 1 3853 4 2 3714 9 0 1 3853 5 3851 7 0 0 0 1 3853 6 2 1061 683 3379 0 0 1 3863 1 3858 1 3863 2 5 3858 1 3863 3 3858 1 0 1 3863 4 5 3343 7 0 1 3863 5 3858 6 0 0 0 1 3863 6 5 2842 3189 2955 1 0 1 3877 1 3875 1 3877 2 2 3876 1 3877 3 3875 2 0 1 3877 4 2 2067 6 0 1 3877 5 3875 4 0 0 0 1 3877 6 2 2388 1029 2690 0 0 1 3881 1 3868 1 3881 2 13 3879 1 3881 3 3868 18 0 1 3881 4 13 3449 9 0 1 3881 5 3868 6 0 0 0 1 3881 6 13 1214 1806 2289 2 0 1 3889 1 3878 1 3889 2 11 3888 1 3889 3 3878 4 0 1 3889 4 11 2189 12 0 1 3889 5 3878 3 0 0 0 1 3889 6 11 418 1211 2603 0 0 1 3907 1 3905 1 3907 2 2 3903 1 3907 3 3905 5 0 1 3907 4 2 2057 8 0 1 3907 5 3905 2 0 0 0 1 3907 6 2 2140 3244 3396 4 0 1 3911 1 3898 1 3911 2 13 3909 1 3911 3 3898 2 0 1 3911 4 13 3384 3 0 1 3911 5 3898 7 0 0 0 1 3911 6 13 509 2434 770 3 0 1 3917 1 3915 1 3917 2 2 3913 1 3917 3 3915 3 0 1 3917 4 2 3340 6 0 1 3917 5 3915 6 0 0 0 1 3917 6 2 2753 2025 635 2 0 1 3919 1 3916 1 3919 2 3 3914 1 3919 3 3916 20 0 1 3919 4 3 3459 7 0 1 3919 5 3916 1 0 0 0 1 3919 6 3 3364 1782 1393 0 0 1 3923 1 3921 1 3923 2 2 3922 1 3923 3 3921 2 0 1 3923 4 2 3517 11 0 1 3923 5 3921 2 0 0 0 1 3923 6 2 2908 1332 444 2 0 1 3929 1 3926 1 3929 2 3 3928 1 3929 3 3926 4 0 1 3929 4 3 3318 7 0 1 3929 5 3926 4 0 0 0 1 3929 6 3 3588 3864 2235 1 0 1 3931 1 3929 1 3931 2 2 3927 1 3931 3 3929 6 0 1 3931 4 2 2867 8 0 1 3931 5 3929 5 0 0 0 1 3931 6 2 3919 3913 3927 0 0 1 3943 1 3940 1 3943 2 3 3941 1 3943 3 3940 5 0 1 3943 4 3 3258 3 0 1 3943 5 3940 18 0 0 0 1 3943 6 3 344 3559 2762 0 0 1 3947 1 3945 1 3947 2 2 3946 1 3947 3 3945 3 0 1 3947 4 2 3940 8 0 1 3947 5 3945 29 0 0 0 1 3947 6 2 2244 2906 2996 1 0 1 3967 1 3961 1 3967 2 6 3966 1 3967 3 3961 1 0 1 3967 4 6 2458 2 0 1 3967 5 3961 4 0 0 0 1 3967 6 6 768 313 254 1 0 1 3989 1 3987 1 3989 2 2 3988 1 3989 3 3987 10 0 1 3989 4 2 3348 3 0 1 3989 5 3987 21 0 0 0 1 3989 6 2 1169 1437 2331 2 0 1 4001 1 3998 1 4001 2 3 4000 1 4001 3 3998 4 0 1 4001 4 3 2873 7 0 1 4001 5 3998 5 0 0 0 1 4001 6 3 1714 3347 624 3 0 1 4003 1 4001 1 4003 2 2 4002 1 4003 3 4001 2 0 1 4003 4 2 3996 8 0 1 4003 5 4001 28 0 0 0 1 4003 6 2 139 3070 2275 0 0 1 4007 1 4002 1 4007 2 5 4005 1 4007 3 4002 9 0 1 4007 4 5 2773 8 0 1 4007 5 4002 9 0 0 0 1 4007 6 5 738 297 3896 1 0 1 4013 1 4011 1 4013 2 2 4009 1 4013 3 4011 3 0 1 4013 4 2 2953 9 0 1 4013 5 4011 8 0 0 0 1 4013 6 2 312 1603 3671 1 0 1 4019 1 4017 1 4019 2 2 4015 1 4019 3 4017 3 0 1 4019 4 2 3470 7 0 1 4019 5 4017 7 0 0 0 1 4019 6 2 3869 2830 3408 1 0 1 4021 1 4019 1 4021 2 2 4020 1 4021 3 4019 5 0 1 4021 4 2 2365 3 0 1 4021 5 4019 5 0 0 0 1 4021 6 2 3492 2818 1504 0 0 1 4027 1 4024 1 4027 2 3 4020 1 4027 3 4024 3 0 1 4027 4 3 3765 2 0 1 4027 5 4024 1 0 0 0 1 4027 6 3 423 4007 3986 0 0 1 4049 1 4046 1 4049 2 3 4043 1 4049 3 4046 3 0 1 4049 4 3 4037 0 0 1 4049 5 4046 12 0 0 0 1 4049 6 3 1007 3235 653 2 0 1 4051 1 4041 1 4051 2 10 4050 1 4051 3 4041 2 0 1 4051 4 10 2367 5 0 1 4051 5 4041 1 0 0 0 1 4051 6 10 1767 3082 701 0 0 1 4057 1 4052 1 4057 2 5 4056 1 4057 3 4052 2 0 1 4057 4 5 2914 6 0 1 4057 5 4052 2 0 0 0 1 4057 6 5 1797 3212 2395 2 0 1 4073 1 4070 1 4073 2 3 4061 1 4073 3 4070 4 0 1 4073 4 3 3117 0 0 1 4073 5 4070 8 0 0 0 1 4073 6 3 2900 4001 3356 3 0 1 4079 1 4068 1 4079 2 11 4076 1 4079 3 4068 2 0 1 4079 4 11 3922 8 0 1 4079 5 4068 3 0 0 0 1 4079 6 11 265 679 1978 1 0 1 4091 1 4089 1 4091 2 2 4090 1 4091 3 4089 3 0 1 4091 4 2 4084 8 0 1 4091 5 4089 12 0 0 0 1 4091 6 2 155 771 4021 2 0 1 4093 1 4091 1 4093 2 2 4092 1 4093 3 4091 4 0 1 4093 4 2 3106 6 0 1 4093 5 4091 2 0 0 0 1 4093 6 2 1942 1514 2807 0 0 1 4099 1 4097 1 4099 2 2 4095 1 4099 3 4097 2 0 1 4099 4 2 3462 8 0 1 4099 5 4097 2 0 0 0 1 4099 6 2 2299 633 3078 0 0 1 4111 1 4099 1 4111 2 12 4110 1 4111 3 4099 4 0 1 4111 4 12 3586 5 0 1 4111 5 4099 4 0 0 0 1 4111 6 12 1053 973 3920 0 0 1 4127 1 4122 1 4127 2 5 4125 1 4127 3 4122 1 0 1 4127 4 5 2630 5 0 1 4127 5 4122 3 0 0 0 1 4127 6 5 1872 1197 3436 1 0 1 4129 1 4116 1 4129 2 13 4120 1 4129 3 4116 1 0 1 4129 4 13 3348 48 0 1 4129 5 4116 7 0 0 0 1 4129 6 13 64 3902 3622 0 0 1 4133 1 4131 1 4133 2 2 4132 1 4133 3 4131 3 0 1 4133 4 2 2646 3 0 1 4133 5 4131 12 0 0 0 1 4133 6 2 849 3596 3591 1 0 1 4139 1 4137 1 4139 2 2 4135 1 4139 3 4137 2 0 1 4139 4 2 3367 8 0 1 4139 5 4137 5 0 0 0 1 4139 6 2 3148 2490 3012 2 0 1 4153 1 4148 1 4153 2 5 4150 1 4153 3 4148 1 0 1 4153 4 5 2470 16 0 1 4153 5 4148 7 0 0 0 1 4153 6 5 1334 1363 1137 0 0 1 4157 1 4155 1 4157 2 2 4156 1 4157 3 4155 3 0 1 4157 4 2 3798 3 0 1 4157 5 4155 6 0 0 0 1 4157 6 2 1241 1691 2413 1 0 1 4159 1 4156 1 4159 2 3 4157 1 4159 3 4156 3 0 1 4159 4 3 4155 4 0 1 4159 5 4156 1 0 0 0 1 4159 6 3 524 318 2954 0 0 1 4177 1 4172 1 4177 2 5 4174 1 4177 3 4172 3 0 1 4177 4 5 2899 10 0 1 4177 5 4172 2 0 0 0 1 4177 6 5 2637 2547 2641 0 0 1 4201 1 4190 1 4201 2 11 4200 1 4201 3 4190 1 0 1 4201 4 11 2944 12 0 1 4201 5 4190 1 0 0 0 1 4201 6 11 4121 1043 4040 0 0 1 4211 1 4205 1 4211 2 6 4208 1 4211 3 4205 3 0 1 4211 4 6 4052 4 0 1 4211 5 4205 11 0 0 0 1 4211 6 6 2570 1635 4208 3 0 1 4217 1 4214 1 4217 2 3 4212 1 4217 3 4214 1 0 1 4217 4 3 4045 0 0 1 4217 5 4214 9 0 0 0 1 4217 6 3 2712 633 2499 1 0 1 4219 1 4217 1 4219 2 2 4218 1 4219 3 4217 6 0 1 4219 4 2 4212 8 0 1 4219 5 4217 6 0 0 0 1 4219 6 2 2522 1265 3909 0 0 1 4229 1 4227 1 4229 2 2 4225 1 4229 3 4227 3 0 1 4229 4 2 2478 7 0 1 4229 5 4227 3 0 0 0 1 4229 6 2 1927 83 427 1 0 1 4231 1 4228 1 4231 2 3 4230 1 4231 3 4228 4 0 1 4231 4 3 3325 3 0 1 4231 5 4228 10 0 0 0 1 4231 6 3 956 953 3565 0 0 1 4241 1 4238 1 4241 2 3 4235 1 4241 3 4238 5 0 1 4241 4 3 4229 0 0 1 4241 5 4238 19 0 0 0 1 4241 6 3 1001 170 2946 1 0 1 4243 1 4241 1 4243 2 2 4239 1 4243 3 4241 6 0 1 4243 4 2 2742 8 0 1 4243 5 4241 5 0 0 0 1 4243 6 2 4231 4225 4239 0 0 1 4253 1 4251 1 4253 2 2 4249 1 4253 3 4251 3 0 1 4253 4 2 2244 6 0 1 4253 5 4251 2 0 0 0 1 4253 6 2 3397 1152 2531 5 0 1 4259 1 4257 1 4259 2 2 4246 1 4259 3 4257 4 0 1 4259 4 2 3422 0 0 1 4259 5 4257 6 0 0 0 1 4259 6 2 3885 1573 4168 3 0 1 4261 1 4259 1 4261 2 2 4260 1 4261 3 4259 6 0 1 4261 4 2 4254 8 0 1 4261 5 4259 4 0 0 0 1 4261 6 2 3462 1719 2416 0 0 1 4271 1 4264 1 4271 2 7 4269 1 4271 3 4264 3 0 1 4271 4 7 2992 4 0 1 4271 5 4264 8 0 0 0 1 4271 6 7 2631 1442 2342 2 0 1 4273 1 4268 1 4273 2 5 4268 1 4273 3 4268 1 0 1 4273 4 5 2546 10 0 1 4273 5 4268 1 0 0 0 1 4273 6 5 1236 2690 1754 0 0 1 4283 1 4281 1 4283 2 2 4279 1 4283 3 4281 2 0 1 4283 4 2 3405 11 0 1 4283 5 4281 2 0 0 0 1 4283 6 2 187 3765 1768 3 0 1 4289 1 4286 1 4289 2 3 4283 1 4289 3 4286 4 0 1 4289 4 3 4277 0 0 1 4289 5 4286 1 0 0 0 1 4289 6 3 295 148 3642 1 0 1 4297 1 4292 1 4297 2 5 4296 1 4297 3 4292 3 0 1 4297 4 5 3648 6 0 1 4297 5 4292 1 0 0 0 1 4297 6 5 3561 3069 3822 0 0 1 4327 1 4324 1 4327 2 3 4325 1 4327 3 4324 4 0 1 4327 4 3 2389 3 0 1 4327 5 4324 1 0 0 0 1 4327 6 3 1155 3649 3566 0 0 1 4337 1 4334 1 4337 2 3 4330 1 4337 3 4334 3 0 1 4337 4 3 4175 1 0 1 4337 5 4334 1 0 0 0 1 4337 6 3 55 176 3754 1 0 1 4339 1 4329 1 4339 2 10 4337 1 4339 3 4329 11 0 1 4339 4 10 2523 8 0 1 4339 5 4329 1 0 0 0 1 4339 6 10 2434 2335 3625 0 0 1 4349 1 4347 1 4349 2 2 4345 1 4349 3 4347 2 0 1 4349 4 2 2432 6 0 1 4349 5 4347 8 0 0 0 1 4349 6 2 4221 3320 4068 2 0 1 4357 1 4355 1 4357 2 2 4356 1 4357 3 4355 2 0 1 4357 4 2 3793 6 0 1 4357 5 4355 6 0 0 0 1 4357 6 2 2229 1623 3187 0 0 1 4363 1 4361 1 4363 2 2 4359 1 4363 3 4361 6 0 1 4363 4 2 4144 8 0 1 4363 5 4361 14 0 0 0 1 4363 6 2 4351 4345 4359 0 0 1 4373 1 4371 1 4373 2 2 4367 1 4373 3 4371 2 0 1 4373 4 2 2568 1 0 1 4373 5 4371 7 0 0 0 1 4373 6 2 3528 4263 3992 4 0 1 4391 1 4377 1 4391 2 14 4388 1 4391 3 4377 1 0 1 4391 4 14 2791 4 0 1 4391 5 4377 2 0 0 0 1 4391 6 14 3177 2954 3175 1 0 1 4397 1 4395 1 4397 2 2 4393 1 4397 3 4395 3 0 1 4397 4 2 2377 6 0 1 4397 5 4395 5 0 0 0 1 4397 6 2 1409 3598 4101 1 0 1 4409 1 4406 1 4409 2 3 4403 1 4409 3 4406 3 0 1 4409 4 3 4397 0 0 1 4409 5 4406 11 0 0 0 1 4409 6 3 2342 2421 2996 2 0 1 4421 1 4418 1 4421 2 3 4420 1 4421 3 4418 6 0 1 4421 4 3 3830 3 0 1 4421 5 4418 18 0 0 0 1 4421 6 3 1494 1122 4112 2 0 1 4423 1 4420 1 4423 2 3 4417 1 4423 3 4420 3 0 1 4423 4 3 4411 0 0 1 4423 5 4420 3 0 0 0 1 4423 6 3 3440 4067 3428 0 0 1 4441 1 4420 1 4441 2 21 4440 1 4441 3 4420 2 0 1 4441 4 21 4142 8 0 1 4441 5 4420 5 0 0 0 1 4441 6 21 3103 3247 629 1 0 1 4447 1 4444 1 4447 2 3 4445 1 4447 3 4444 1 0 1 4447 4 3 2739 6 0 1 4447 5 4444 3 0 0 0 1 4447 6 3 775 3099 2489 0 0 1 4451 1 4449 1 4451 2 2 4447 1 4451 3 4449 3 0 1 4451 4 2 3166 16 0 1 4451 5 4449 3 0 0 0 1 4451 6 2 256 3346 1419 1 0 1 4457 1 4454 1 4457 2 3 4452 1 4457 3 4454 3 0 1 4457 4 3 4268 0 0 1 4457 5 4454 1 0 0 0 1 4457 6 3 2943 3671 2423 1 0 1 4463 1 4458 1 4463 2 5 4460 1 4463 3 4458 1 0 1 4463 4 5 2602 6 0 1 4463 5 4458 2 0 0 0 1 4463 6 5 280 3180 1205 2 0 1 4481 1 4478 1 4481 2 3 4468 1 4481 3 4478 4 0 1 4481 4 3 3892 1 0 1 4481 5 4478 1 0 0 0 1 4481 6 3 4213 3703 3999 1 0 1 4483 1 4481 1 4483 2 2 4482 1 4483 3 4481 2 0 1 4483 4 2 4367 2 0 1 4483 5 4481 6 0 0 0 1 4483 6 2 2616 1198 695 0 0 1 4493 1 4491 1 4493 2 2 4489 1 4493 3 4491 2 0 1 4493 4 2 4132 1 0 1 4493 5 4491 2 0 0 0 1 4493 6 2 3144 2017 1085 1 0 1 4507 1 4505 1 4507 2 2 4503 1 4507 3 4505 6 0 1 4507 4 2 2907 1 0 1 4507 5 4505 11 0 0 0 1 4507 6 2 4495 4489 4503 0 0 1 4513 1 4506 1 4513 2 7 4510 1 4513 3 4506 1 0 1 4513 4 7 2378 8 0 1 4513 5 4506 2 0 0 0 1 4513 6 7 3674 235 3867 0 0 1 4517 1 4515 1 4517 2 2 4512 1 4517 3 4515 11 0 1 4517 4 2 4284 0 0 1 4517 5 4515 3 0 0 0 1 4517 6 2 1108 3536 3489 2 0 1 4519 1 4516 1 4519 2 3 4517 1 4519 3 4516 6 0 1 4519 4 3 4515 4 0 1 4519 5 4516 1 0 0 0 1 4519 6 3 2478 149 3566 2 0 1 4523 1 4518 1 4523 2 5 4520 1 4523 3 4518 2 0 1 4523 4 5 3148 4 0 1 4523 5 4518 11 0 0 0 1 4523 6 5 1902 3411 3259 2 0 1 4547 1 4545 1 4547 2 2 4541 1 4547 3 4545 4 0 1 4547 4 2 4148 4 0 1 4547 5 4545 2 0 0 0 1 4547 6 2 1387 3790 2417 2 0 1 4549 1 4543 1 4549 2 6 4545 1 4549 3 4543 2 0 1 4549 4 6 4058 2 0 1 4549 5 4543 3 0 0 0 1 4549 6 6 46 4336 886 0 0 1 4561 1 4550 1 4561 2 11 4560 1 4561 3 4550 2 0 1 4561 4 11 4381 12 0 1 4561 5 4550 9 0 0 0 1 4561 6 11 1145 3578 2777 0 0 1 4567 1 4564 1 4567 2 3 4566 1 4567 3 4564 1 0 1 4567 4 3 2779 5 0 1 4567 5 4564 13 0 0 0 1 4567 6 3 3246 976 4123 3 0 1 4583 1 4578 1 4583 2 5 4581 1 4583 3 4578 2 0 1 4583 4 5 4571 11 0 1 4583 5 4578 1 0 0 0 1 4583 6 5 53 4496 4242 1 0 1 4591 1 4580 1 4591 2 11 4590 1 4591 3 4580 2 0 1 4591 4 11 2962 2 0 1 4591 5 4580 6 0 0 0 1 4591 6 11 957 2109 2806 0 0 1 4597 1 4592 1 4597 2 5 4596 1 4597 3 4592 1 0 1 4597 4 5 4179 3 0 1 4597 5 4592 6 0 0 0 1 4597 6 5 2664 3847 2401 0 0 1 4603 1 4601 1 4603 2 2 4599 1 4603 3 4601 6 0 1 4603 4 2 4153 8 0 1 4603 5 4601 3 0 0 0 1 4603 6 2 4591 4585 4599 0 0 1 4621 1 4619 1 4621 2 2 4617 1 4621 3 4619 2 0 1 4621 4 2 4013 6 0 1 4621 5 4619 7 0 0 0 1 4621 6 2 1100 2174 879 0 0 1 4637 1 4635 1 4637 2 2 4631 1 4637 3 4635 9 0 1 4637 4 2 2395 4 0 1 4637 5 4635 2 0 0 0 1 4637 6 2 305 4319 808 1 0 1 4639 1 4636 1 4639 2 3 4637 1 4639 3 4636 1 0 1 4639 4 3 3896 3 0 1 4639 5 4636 19 0 0 0 1 4639 6 3 1317 1809 1606 0 0 1 4643 1 4638 1 4643 2 5 4634 1 4643 3 4638 3 0 1 4643 4 5 2546 1 0 1 4643 5 4638 11 0 0 0 1 4643 6 5 3845 2560 4022 1 0 1 4649 1 4646 1 4649 2 3 4648 1 4649 3 4646 1 0 1 4649 4 3 4013 4 0 1 4649 5 4646 8 0 0 0 1 4649 6 3 2396 3040 479 2 0 1 4651 1 4648 1 4651 2 3 4642 1 4651 3 4648 6 0 1 4651 4 3 3318 6 0 1 4651 5 4648 8 0 0 0 1 4651 6 3 843 1576 4195 0 0 1 4657 1 4642 1 4657 2 15 4652 1 4657 3 4642 6 0 1 4657 4 15 3692 0 0 1 4657 5 4642 24 0 0 0 1 4657 6 15 2713 2474 4346 0 0 1 4663 1 4660 1 4663 2 3 4662 1 4663 3 4660 3 0 1 4663 4 3 3855 5 0 1 4663 5 4660 13 0 0 0 1 4663 6 3 4017 2517 4263 0 0 1 4673 1 4670 1 4673 2 3 4668 1 4673 3 4670 1 0 1 4673 4 3 2460 0 0 1 4673 5 4670 15 0 0 0 1 4673 6 3 865 3238 160 4 0 1 4679 1 4668 1 4679 2 11 4677 1 4679 3 4668 2 0 1 4679 4 11 4414 3 0 1 4679 5 4668 2 0 0 0 1 4679 6 11 184 2733 3552 1 0 1 4691 1 4689 1 4691 2 2 4684 1 4691 3 4689 2 0 1 4691 4 2 4509 0 0 1 4691 5 4689 9 0 0 0 1 4691 6 2 4288 4489 3051 1 0 1 4703 1 4698 1 4703 2 5 4702 1 4703 3 4698 5 0 1 4703 4 5 3012 4 0 1 4703 5 4698 1 0 0 0 1 4703 6 5 3972 487 3929 3 0 1 4721 1 4715 1 4721 2 6 4718 1 4721 3 4715 7 0 1 4721 4 6 4464 0 0 1 4721 5 4715 2 0 0 0 1 4721 6 6 693 182 858 1 0 1 4723 1 4721 1 4723 2 2 4722 1 4723 3 4721 2 0 1 4723 4 2 4408 7 0 1 4723 5 4721 5 0 0 0 1 4723 6 2 4018 2920 2673 2 0 1 4729 1 4712 1 4729 2 17 4718 1 4729 3 4712 1 0 1 4729 4 17 4536 22 0 1 4729 5 4712 4 0 0 0 1 4729 6 17 2614 4300 4551 0 0 1 4733 1 4728 1 4733 2 5 4721 1 4733 3 4728 7 0 1 4733 4 5 3462 0 0 1 4733 5 4728 10 0 0 0 1 4733 6 5 1 969 4094 5 0 1 4751 1 4732 1 4751 2 19 4747 1 4751 3 4732 4 0 1 4751 4 19 3565 9 0 1 4751 5 4732 1 0 0 0 1 4751 6 19 4544 1906 704 1 0 1 4759 1 4756 1 4759 2 3 4753 1 4759 3 4756 1 0 1 4759 4 3 2513 7 0 1 4759 5 4756 5 0 0 0 1 4759 6 3 3147 1700 1939 0 0 1 4783 1 4777 1 4783 2 6 4782 1 4783 3 4777 8 0 1 4783 4 6 4466 3 0 1 4783 5 4777 11 0 0 0 1 4783 6 6 4214 3223 2342 0 0 1 4787 1 4785 1 4787 2 2 4783 1 4787 3 4785 2 0 1 4787 4 2 3115 7 0 1 4787 5 4785 8 0 0 0 1 4787 6 2 4307 4559 3742 2 0 1 4789 1 4787 1 4789 2 2 4784 1 4789 3 4787 2 0 1 4789 4 2 3684 15 0 1 4789 5 4787 3 0 0 0 1 4789 6 2 1158 1476 1036 0 0 1 4793 1 4790 1 4793 2 3 4792 1 4793 3 4790 16 0 1 4793 4 3 2583 4 0 1 4793 5 4790 1 0 0 0 1 4793 6 3 4483 930 3 2 0 1 4799 1 4792 1 4799 2 7 4798 1 4799 3 4792 8 0 1 4799 4 7 4439 2 0 1 4799 5 4792 1 0 0 0 1 4799 6 7 4125 600 2053 1 0 1 4801 1 4794 1 4801 2 7 4798 1 4801 3 4794 1 0 1 4801 4 7 2998 31 0 1 4801 5 4794 1 0 0 0 1 4801 6 7 3631 2238 4495 0 0 1 4813 1 4811 1 4813 2 2 4809 1 4813 3 4811 4 0 1 4813 4 2 4308 12 0 1 4813 5 4811 4 0 0 0 1 4813 6 2 1051 1931 2681 0 0 1 4817 1 4814 1 4817 2 3 4816 1 4817 3 4814 1 0 1 4817 4 3 3744 7 0 1 4817 5 4814 3 0 0 0 1 4817 6 3 4496 2100 3364 1 0 1 4831 1 4828 1 4831 2 3 4830 1 4831 3 4828 5 0 1 4831 4 3 2775 2 0 1 4831 5 4828 3 0 0 0 1 4831 6 3 1713 4453 2779 0 0 1 4861 1 4850 1 4861 2 11 4859 1 4861 3 4850 5 0 1 4861 4 11 3500 9 0 1 4861 5 4850 4 0 0 0 1 4861 6 11 2959 2621 2014 0 0 1 4871 1 4860 1 4871 2 11 4870 1 4871 3 4860 7 0 1 4871 4 11 3209 10 0 1 4871 5 4860 1 0 0 0 1 4871 6 11 812 73 4465 2 0 1 4877 1 4875 1 4877 2 2 4876 1 4877 3 4875 3 0 1 4877 4 2 4589 6 0 1 4877 5 4875 2 0 0 0 1 4877 6 2 3454 4507 1653 2 0 1 4889 1 4886 1 4889 2 3 4883 1 4889 3 4886 1 0 1 4889 4 3 4877 0 0 1 4889 5 4886 7 0 0 0 1 4889 6 3 1718 2917 4840 2 0 1 4903 1 4900 1 4903 2 3 4902 1 4903 3 4900 4 0 1 4903 4 3 2979 2 0 1 4903 5 4900 8 0 0 0 1 4903 6 3 1702 1305 1797 0 0 1 4909 1 4903 1 4909 2 6 4908 1 4909 3 4903 6 0 1 4909 4 6 3865 7 0 1 4909 5 4903 6 0 0 0 1 4909 6 6 2599 3481 4769 0 0 1 4919 1 4906 1 4919 2 13 4915 1 4919 3 4906 1 0 1 4919 4 13 4686 9 0 1 4919 5 4906 6 0 0 0 1 4919 6 13 2943 4045 3643 2 0 1 4931 1 4925 1 4931 2 6 4928 1 4931 3 4925 3 0 1 4931 4 6 3112 7 0 1 4931 5 4925 7 0 0 0 1 4931 6 6 1657 4017 1703 1 0 1 4933 1 4931 1 4933 2 2 4932 1 4933 3 4931 2 0 1 4933 4 2 4500 6 0 1 4933 5 4931 2 0 0 0 1 4933 6 2 129 4255 3313 0 0 1 4937 1 4934 1 4937 2 3 4926 1 4937 3 4934 1 0 1 4937 4 3 4763 5 0 1 4937 5 4934 7 0 0 0 1 4937 6 3 3800 3340 3079 6 0 1 4943 1 4936 1 4943 2 7 4940 1 4943 3 4936 2 0 1 4943 4 7 4276 4 0 1 4943 5 4936 1 0 0 0 1 4943 6 7 4160 1268 4619 1 0 1 4951 1 4945 1 4951 2 6 4949 1 4951 3 4945 1 0 1 4951 4 6 3348 4 0 1 4951 5 4945 4 0 0 0 1 4951 6 6 3464 4044 4102 0 0 1 4957 1 4955 1 4957 2 2 4953 1 4957 3 4955 6 0 1 4957 4 2 3521 6 0 1 4957 5 4955 3 0 0 0 1 4957 6 2 4945 4939 4953 0 0 1 4967 1 4962 1 4967 2 5 4966 1 4967 3 4962 3 0 1 4967 4 5 3184 12 0 1 4967 5 4962 1 0 0 0 1 4967 6 5 950 3727 466 3 0 1 4969 1 4958 1 4969 2 11 4966 1 4969 3 4958 1 0 1 4969 4 11 4047 14 0 1 4969 5 4958 3 0 0 0 1 4969 6 11 639 155 4528 0 0 1 4973 1 4971 1 4973 2 2 4972 1 4973 3 4971 2 0 1 4973 4 2 2632 6 0 1 4973 5 4971 11 0 0 0 1 4973 6 2 4155 4621 2573 3 0 1 4987 1 4985 1 4987 2 2 4986 1 4987 3 4985 2 0 1 4987 4 2 4814 2 0 1 4987 5 4985 5 0 0 0 1 4987 6 2 3525 4440 4786 0 0 1 4993 1 4988 1 4993 2 5 4992 1 4993 3 4988 3 0 1 4993 4 5 4297 6 0 1 4993 5 4988 2 0 0 0 1 4993 6 5 1106 3867 2646 2 0 1 4999 1 4996 1 4999 2 3 4997 1 4999 3 4996 1 0 1 4999 4 3 4799 3 0 1 4999 5 4996 26 0 0 0 1 4999 6 3 2779 360 4996 0 0 1 5003 1 5001 1 5003 2 2 4999 1 5003 3 5001 2 0 1 5003 4 2 4493 11 0 1 5003 5 5001 6 0 0 0 1 5003 6 2 4980 1719 2697 1 0 1 5009 1 5006 1 5009 2 3 5003 1 5009 3 5006 6 0 1 5009 4 3 4997 0 0 1 5009 5 5006 7 0 0 0 1 5009 6 3 2797 3783 4178 2 0 1 5011 1 5009 1 5011 2 2 5010 1 5011 3 5009 4 0 1 5011 4 2 4242 10 0 1 5011 5 5009 3 0 0 0 1 5011 6 2 4952 3074 3137 0 0 1 5021 1 5018 1 5021 2 3 5000 1 5021 3 5018 1 0 1 5021 4 3 3369 3 0 1 5021 5 5018 4 0 0 0 1 5021 6 3 536 4470 3582 1 0 1 5023 1 5020 1 5023 2 3 5022 1 5023 3 5020 4 0 1 5023 4 3 2666 2 0 1 5023 5 5020 1 0 0 0 1 5023 6 3 4661 406 4842 0 0 1 5039 1 5028 1 5039 2 11 5035 1 5039 3 5028 1 0 1 5039 4 11 2763 7 0 1 5039 5 5028 2 0 0 0 1 5039 6 11 1402 3485 389 1 0 1 5051 1 5049 1 5051 2 2 5047 1 5051 3 5049 2 0 1 5051 4 2 3758 8 0 1 5051 5 5049 7 0 0 0 1 5051 6 2 2908 2629 3492 2 0 1 5059 1 5057 1 5059 2 2 5055 1 5059 3 5057 6 0 1 5059 4 2 3985 1 0 1 5059 5 5057 2 0 0 0 1 5059 6 2 5047 5041 5055 0 0 1 5077 1 5075 1 5077 2 2 5073 1 5077 3 5075 6 0 1 5077 4 2 3432 6 0 1 5077 5 5075 3 0 0 0 1 5077 6 2 5065 5059 5073 0 0 1 5081 1 5078 1 5081 2 3 5070 1 5081 3 5078 1 0 1 5081 4 3 3582 0 0 1 5081 5 5078 5 0 0 0 1 5081 6 3 1571 2217 3364 3 0 1 5087 1 5082 1 5087 2 5 5086 1 5087 3 5082 19 0 1 5087 4 5 3574 2 0 1 5087 5 5082 5 0 0 0 1 5087 6 5 1424 3477 3422 1 0 1 5099 1 5097 1 5099 2 2 5098 1 5099 3 5097 3 0 1 5099 4 2 5092 8 0 1 5099 5 5097 4 0 0 0 1 5099 6 2 4903 38 759 1 0 1 5101 1 5095 1 5101 2 6 5097 1 5101 3 5095 2 0 1 5101 4 6 5097 6 0 1 5101 5 5095 4 0 0 0 1 5101 6 6 3421 4320 4789 0 0 1 5107 1 5105 1 5107 2 2 5103 1 5107 3 5105 5 0 1 5107 4 2 4396 13 0 1 5107 5 5105 5 0 0 0 1 5107 6 2 2785 1583 3796 0 0 1 5113 1 5094 1 5113 2 19 5109 1 5113 3 5094 11 0 1 5113 4 19 3501 23 0 1 5113 5 5094 5 0 0 0 1 5113 6 19 1417 4051 4963 2 0 1 5119 1 5116 1 5119 2 3 5117 1 5119 3 5116 3 0 1 5119 4 3 4529 3 0 1 5119 5 5116 4 0 0 0 1 5119 6 3 4512 2247 5016 0 0 1 5147 1 5145 1 5147 2 2 5143 1 5147 3 5145 3 0 1 5147 4 2 3705 7 0 1 5147 5 5145 12 0 0 0 1 5147 6 2 890 4432 3125 2 0 1 5153 1 5148 1 5153 2 5 5148 1 5153 3 5148 1 0 1 5153 4 5 3288 15 0 1 5153 5 5148 9 0 0 0 1 5153 6 5 4040 3661 3222 2 0 1 5167 1 5161 1 5167 2 6 5166 1 5167 3 5161 2 0 1 5167 4 6 2756 3 0 1 5167 5 5161 28 0 0 0 1 5167 6 6 2012 4295 4940 0 0 1 5171 1 5169 1 5171 2 2 5170 1 5171 3 5169 3 0 1 5171 4 2 4578 4 0 1 5171 5 5169 2 0 0 0 1 5171 6 2 2532 605 2542 1 0 1 5179 1 5177 1 5179 2 2 5175 1 5179 3 5177 4 0 1 5179 4 2 4114 1 0 1 5179 5 5177 7 0 0 0 1 5179 6 2 3903 3978 4616 1 0 1 5189 1 5187 1 5189 2 2 5179 1 5189 3 5187 2 0 1 5189 4 2 3521 0 0 1 5189 5 5187 2 0 0 0 1 5189 6 2 4015 1142 1147 2 0 1 5197 1 5190 1 5197 2 7 5195 1 5197 3 5190 2 0 1 5197 4 7 3172 10 0 1 5197 5 5190 1 0 0 0 1 5197 6 7 3064 949 3188 0 0 1 5209 1 5192 1 5209 2 17 5208 1 5209 3 5192 2 0 1 5209 4 17 3547 23 0 1 5209 5 5192 1 0 0 0 1 5209 6 17 1317 1227 4296 0 0 1 5227 1 5225 1 5227 2 2 5226 1 5227 3 5225 2 0 1 5227 4 2 3673 7 0 1 5227 5 5225 18 0 0 0 1 5227 6 2 1338 3492 1839 0 0 1 5231 1 5224 1 5231 2 7 5230 1 5231 3 5224 1 0 1 5231 4 7 2945 2 0 1 5231 5 5224 4 0 0 0 1 5231 6 7 2064 124 829 3 0 1 5233 1 5223 1 5233 2 10 5232 1 5233 3 5223 12 0 1 5233 4 10 4917 12 0 1 5233 5 5223 13 0 0 0 1 5233 6 10 5172 4218 4161 0 0 1 5237 1 5234 1 5237 2 3 5235 1 5237 3 5234 1 0 1 5237 4 3 4976 7 0 1 5237 5 5234 15 0 0 0 1 5237 6 3 1244 3085 651 5 0 1 5261 1 5259 1 5261 2 2 5257 1 5261 3 5259 2 0 1 5261 4 2 3906 12 0 1 5261 5 5259 5 0 0 0 1 5261 6 2 237 2891 1780 1 0 1 5273 1 5270 1 5273 2 3 5268 1 5273 3 5270 1 0 1 5273 4 3 3736 0 0 1 5273 5 5270 3 0 0 0 1 5273 6 3 2525 568 4238 1 0 1 5279 1 5272 1 5279 2 7 5275 1 5279 3 5272 3 0 1 5279 4 7 3255 10 0 1 5279 5 5272 2 0 0 0 1 5279 6 7 812 3859 3442 1 0 1 5281 1 5274 1 5281 2 7 5278 1 5281 3 5274 1 0 1 5281 4 7 4529 26 0 1 5281 5 5274 3 0 0 0 1 5281 6 7 1574 4991 4876 0 0 1 5297 1 5294 1 5297 2 3 5296 1 5297 3 5294 3 0 1 5297 4 3 2780 8 0 1 5297 5 5294 1 0 0 0 1 5297 6 3 4813 693 1723 2 0 1 5303 1 5298 1 5303 2 5 5298 1 5303 3 5298 8 0 1 5303 4 5 4664 7 0 1 5303 5 5298 14 0 0 0 1 5303 6 5 2210 3779 1797 3 0 1 5309 1 5307 1 5309 2 2 5305 1 5309 3 5307 3 0 1 5309 4 2 3402 6 0 1 5309 5 5307 9 0 0 0 1 5309 6 2 1374 1244 3426 3 0 1 5323 1 5318 1 5323 2 5 5322 1 5323 3 5318 3 0 1 5323 4 5 4544 2 0 1 5323 5 5318 2 0 0 0 1 5323 6 5 4678 449 4833 0 0 1 5333 1 5331 1 5333 2 2 5332 1 5333 3 5331 2 0 1 5333 4 2 3011 4 0 1 5333 5 5331 7 0 0 0 1 5333 6 2 4173 4880 4665 1 0 1 5347 1 5344 1 5347 2 3 5340 1 5347 3 5344 3 0 1 5347 4 3 4300 5 0 1 5347 5 5344 1 0 0 0 1 5347 6 3 3872 3767 4767 0 0 1 5351 1 5340 1 5351 2 11 5349 1 5351 3 5340 2 0 1 5351 4 11 2904 3 0 1 5351 5 5340 3 0 0 0 1 5351 6 11 2813 3018 1365 1 0 1 5381 1 5378 1 5381 2 3 5379 1 5381 3 5378 1 0 1 5381 4 3 5373 10 0 1 5381 5 5378 4 0 0 0 1 5381 6 3 591 3442 2419 2 0 1 5387 1 5385 1 5387 2 2 5381 1 5387 3 5385 5 0 1 5387 4 2 5179 0 0 1 5387 5 5385 2 0 0 0 1 5387 6 2 294 2140 4831 1 0 1 5393 1 5390 1 5393 2 3 5388 1 5393 3 5390 5 0 1 5393 4 3 2779 0 0 1 5393 5 5390 9 0 0 0 1 5393 6 3 3959 3645 1417 2 0 1 5399 1 5392 1 5399 2 7 5398 1 5399 3 5392 2 0 1 5399 4 7 4859 3 0 1 5399 5 5392 5 0 0 0 1 5399 6 7 2407 4443 3793 1 0 1 5407 1 5404 1 5407 2 3 5406 1 5407 3 5404 1 0 1 5407 4 3 2801 5 0 1 5407 5 5404 5 0 0 0 1 5407 6 3 5256 3948 4841 0 0 1 5413 1 5408 1 5413 2 5 5408 1 5413 3 5408 5 0 1 5413 4 5 3179 11 0 1 5413 5 5408 5 0 0 0 1 5413 6 5 648 4784 5019 0 0 1 5417 1 5414 1 5417 2 3 5411 1 5417 3 5414 4 0 1 5417 4 3 3351 16 0 1 5417 5 5414 4 0 0 0 1 5417 6 3 5229 2844 2225 2 0 1 5419 1 5416 1 5419 2 3 5414 1 5419 3 5416 5 0 1 5419 4 3 4003 3 0 1 5419 5 5416 4 0 0 0 1 5419 6 3 3470 5375 4215 2 0 1 5431 1 5428 1 5431 2 3 5430 1 5431 3 5428 3 0 1 5431 4 3 4493 3 0 1 5431 5 5428 1 0 0 0 1 5431 6 3 5406 3798 5206 0 0 1 5437 1 5432 1 5437 2 5 5436 1 5437 3 5432 1 0 1 5437 4 5 3703 6 0 1 5437 5 5432 10 0 0 0 1 5437 6 5 16 180 4983 0 0 1 5441 1 5438 1 5441 2 3 5435 1 5441 3 5438 4 0 1 5441 4 3 5429 0 0 1 5441 5 5438 5 0 0 0 1 5441 6 3 2825 1966 2329 1 0 1 5443 1 5441 1 5443 2 2 5439 1 5443 3 5441 6 0 1 5443 4 2 3215 8 0 1 5443 5 5441 13 0 0 0 1 5443 6 2 5431 5425 5439 0 0 1 5449 1 5442 1 5449 2 7 5446 1 5449 3 5442 3 0 1 5449 4 7 5215 17 0 1 5449 5 5442 1 0 0 0 1 5449 6 7 3651 1577 918 0 0 1 5471 1 5464 1 5471 2 7 5470 1 5471 3 5464 1 0 1 5471 4 7 4654 2 0 1 5471 5 5464 3 0 0 0 1 5471 6 7 1611 5284 4877 1 0 1 5477 1 5475 1 5477 2 2 5476 1 5477 3 5475 9 0 1 5477 4 2 4592 3 0 1 5477 5 5475 5 0 0 0 1 5477 6 2 1630 2737 726 3 0 1 5479 1 5476 1 5479 2 3 5477 1 5479 3 5476 4 0 1 5479 4 3 5475 4 0 1 5479 5 5476 1 0 0 0 1 5479 6 3 4310 4043 3121 0 0 1 5483 1 5481 1 5483 2 2 5479 1 5483 3 5481 3 0 1 5483 4 2 4428 7 0 1 5483 5 5481 3 0 0 0 1 5483 6 2 15 761 4423 1 0 1 5501 1 5499 1 5501 2 2 5500 1 5501 3 5499 3 0 1 5501 4 2 5494 8 0 1 5501 5 5499 9 0 0 0 1 5501 6 2 3141 1376 2152 2 0 1 5503 1 5500 1 5503 2 3 5501 1 5503 3 5500 3 0 1 5503 4 3 4553 3 0 1 5503 5 5500 9 0 0 0 1 5503 6 3 807 3098 4862 1 0 1 5507 1 5505 1 5507 2 2 5506 1 5507 3 5505 3 0 1 5507 4 2 4674 2 0 1 5507 5 5505 7 0 0 0 1 5507 6 2 4320 3265 1486 1 0 1 5519 1 5506 1 5519 2 13 5517 1 5519 3 5506 3 0 1 5519 4 13 4514 3 0 1 5519 5 5506 8 0 0 0 1 5519 6 13 1728 77 3957 2 0 1 5521 1 5510 1 5521 2 11 5518 1 5521 3 5510 1 0 1 5521 4 11 5107 10 0 1 5521 5 5510 2 0 0 0 1 5521 6 11 1127 3611 4199 0 0 1 5527 1 5522 1 5527 2 5 5525 1 5527 3 5522 5 0 1 5527 4 5 3244 10 0 1 5527 5 5522 2 0 0 0 1 5527 6 5 1602 4694 291 3 0 1 5531 1 5521 1 5531 2 10 5523 1 5531 3 5521 5 0 1 5531 4 10 5284 1 0 1 5531 5 5521 13 0 0 0 1 5531 6 10 3780 522 2818 1 0 1 5557 1 5555 1 5557 2 2 5556 1 5557 3 5555 4 0 1 5557 4 2 5232 7 0 1 5557 5 5555 2 0 0 0 1 5557 6 2 4509 1414 5195 0 0 1 5563 1 5561 1 5563 2 2 5562 1 5563 3 5561 2 0 1 5563 4 2 4029 2 0 1 5563 5 5561 7 0 0 0 1 5563 6 2 824 2629 3660 0 0 1 5569 1 5556 1 5569 2 13 5568 1 5569 3 5556 1 0 1 5569 4 13 5005 14 0 1 5569 5 5556 3 0 0 0 1 5569 6 13 2058 4630 3619 0 0 1 5573 1 5571 1 5573 2 2 5569 1 5573 3 5571 3 0 1 5573 4 2 4990 12 0 1 5573 5 5571 9 0 0 0 1 5573 6 2 458 5276 1540 1 0 1 5581 1 5575 1 5581 2 6 5580 1 5581 3 5575 8 0 1 5581 4 6 2877 23 0 1 5581 5 5575 7 0 0 0 1 5581 6 6 5084 5293 4711 0 0 1 5591 1 5580 1 5591 2 11 5589 1 5591 3 5580 7 0 1 5591 4 11 4672 10 0 1 5591 5 5580 2 0 0 0 1 5591 6 11 1604 4049 1141 1 0 1 5623 1 5618 1 5623 2 5 5622 1 5623 3 5618 1 0 1 5623 4 5 4471 5 0 1 5623 5 5618 3 0 0 0 1 5623 6 5 2026 3434 2370 0 0 1 5639 1 5632 1 5639 2 7 5632 1 5639 3 5632 3 0 1 5639 4 7 5533 9 0 1 5639 5 5632 4 0 0 0 1 5639 6 7 3109 2719 1858 1 0 1 5641 1 5627 1 5641 2 14 5627 1 5641 3 5627 1 0 1 5641 4 14 3065 0 0 1 5641 5 5627 14 0 0 0 1 5641 6 14 2049 1341 2687 0 0 1 5647 1 5644 1 5647 2 3 5645 1 5647 3 5644 7 0 1 5647 4 3 5643 4 0 1 5647 5 5644 4 0 0 0 1 5647 6 3 469 92 4939 0 0 1 5651 1 5649 1 5651 2 2 5645 1 5651 3 5649 2 0 1 5651 4 2 5114 0 0 1 5651 5 5649 10 0 0 0 1 5651 6 2 4954 2981 3352 1 0 1 5653 1 5648 1 5653 2 5 5652 1 5653 3 5648 1 0 1 5653 4 5 5415 7 0 1 5653 5 5648 1 0 0 0 1 5653 6 5 2467 4995 4874 1 0 1 5657 1 5654 1 5657 2 3 5652 1 5657 3 5654 3 0 1 5657 4 3 4685 0 0 1 5657 5 5654 7 0 0 0 1 5657 6 3 2612 4118 5555 1 0 1 5659 1 5657 1 5659 2 2 5658 1 5659 3 5657 6 0 1 5659 4 2 3882 2 0 1 5659 5 5657 3 0 0 0 1 5659 6 2 2138 5546 3119 0 0 1 5669 1 5666 1 5669 2 3 5657 1 5669 3 5666 1 0 1 5669 4 3 2924 5 0 1 5669 5 5666 6 0 0 0 1 5669 6 3 2120 1592 657 1 0 1 5683 1 5681 1 5683 2 2 5682 1 5683 3 5681 4 0 1 5683 4 2 4164 10 0 1 5683 5 5681 2 0 0 0 1 5683 6 2 2285 1361 5120 0 0 1 5689 1 5678 1 5689 2 11 5686 1 5689 3 5678 2 0 1 5689 4 11 4145 10 0 1 5689 5 5678 8 0 0 0 1 5689 6 11 2179 909 5572 0 0 1 5693 1 5691 1 5693 2 2 5689 1 5693 3 5691 3 0 1 5693 4 2 4512 7 0 1 5693 5 5691 2 0 0 0 1 5693 6 2 4455 2355 3472 2 0 1 5701 1 5699 1 5701 2 2 5700 1 5701 3 5699 6 0 1 5701 4 2 4705 7 0 1 5701 5 5699 10 0 0 0 1 5701 6 2 1099 3264 3092 0 0 1 5711 1 5692 1 5711 2 19 5710 1 5711 3 5692 1 0 1 5711 4 19 3629 2 0 1 5711 5 5692 3 0 0 0 1 5711 6 19 5210 5696 2375 1 0 1 5717 1 5715 1 5717 2 2 5716 1 5717 3 5715 2 0 1 5717 4 2 4875 9 0 1 5717 5 5715 3 0 0 0 1 5717 6 2 5001 2337 4666 7 0 1 5737 1 5732 1 5737 2 5 5736 1 5737 3 5732 2 0 1 5737 4 5 3985 12 0 1 5737 5 5732 2 0 0 0 1 5737 6 5 5307 2532 5344 0 0 1 5741 1 5739 1 5741 2 2 5736 1 5741 3 5739 2 0 1 5741 4 2 4555 2 0 1 5741 5 5739 6 0 0 0 1 5741 6 2 1063 5658 2348 2 0 1 5743 1 5733 1 5743 2 10 5741 1 5743 3 5733 6 0 1 5743 4 10 4715 4 0 1 5743 5 5733 14 0 0 0 1 5743 6 10 169 4833 5621 0 0 1 5749 1 5747 1 5749 2 2 5745 1 5749 3 5747 4 0 1 5749 4 2 3224 6 0 1 5749 5 5747 9 0 0 0 1 5749 6 2 3786 1618 3265 0 0 1 5779 1 5777 1 5779 2 2 5775 1 5779 3 5777 2 0 1 5779 4 2 4989 8 0 1 5779 5 5777 5 0 0 0 1 5779 6 2 520 936 4860 0 0 1 5783 1 5776 1 5783 2 7 5779 1 5783 3 5776 2 0 1 5783 4 7 3417 5 0 1 5783 5 5776 7 0 0 0 1 5783 6 7 3792 2474 3363 1 0 1 5791 1 5785 1 5791 2 6 5789 1 5791 3 5785 10 0 1 5791 4 6 5496 10 0 1 5791 5 5785 12 0 0 0 1 5791 6 6 5626 3300 3847 0 0 1 5801 1 5798 1 5801 2 3 5795 1 5801 3 5798 5 0 1 5801 4 3 5789 0 0 1 5801 5 5798 9 0 0 0 1 5801 6 3 3402 1709 4616 2 0 1 5807 1 5802 1 5807 2 5 5806 1 5807 3 5802 12 0 1 5807 4 5 5319 4 0 1 5807 5 5802 2 0 0 0 1 5807 6 5 3822 3004 2936 1 0 1 5813 1 5811 1 5813 2 2 5812 1 5813 3 5811 5 0 1 5813 4 2 5538 9 0 1 5813 5 5811 8 0 0 0 1 5813 6 2 3366 3540 2594 1 0 1 5821 1 5815 1 5821 2 6 5817 1 5821 3 5815 2 0 1 5821 4 6 4968 2 0 1 5821 5 5815 6 0 0 0 1 5821 6 6 5593 3825 5161 4 0 1 5827 1 5825 1 5827 2 2 5826 1 5827 3 5825 2 0 1 5827 4 2 4800 7 0 1 5827 5 5825 3 0 0 0 1 5827 6 2 2659 4815 4660 0 0 1 5839 1 5833 1 5839 2 6 5837 1 5839 3 5833 2 0 1 5839 4 6 3944 4 0 1 5839 5 5833 4 0 0 0 1 5839 6 6 1721 5345 2750 0 0 1 5843 1 5841 1 5843 2 2 5839 1 5843 3 5841 3 0 1 5843 4 2 5271 7 0 1 5843 5 5841 8 0 0 0 1 5843 6 2 1733 1896 3818 1 0 1 5849 1 5846 1 5849 2 3 5848 1 5849 3 5846 1 0 1 5849 4 3 4466 7 0 1 5849 5 5846 9 0 0 0 1 5849 6 3 1028 1241 4207 3 0 1 5851 1 5849 1 5851 2 2 5847 1 5851 3 5849 6 0 1 5851 4 2 4062 1 0 1 5851 5 5849 2 0 0 0 1 5851 6 2 5839 5833 5847 0 0 1 5857 1 5850 1 5857 2 7 5850 1 5857 3 5850 9 0 1 5857 4 7 5725 14 0 1 5857 5 5850 4 0 0 0 1 5857 6 7 1880 4090 2563 1 0 1 5861 1 5858 1 5861 2 3 5859 1 5861 3 5858 7 0 1 5861 4 3 4246 12 0 1 5861 5 5858 8 0 0 0 1 5861 6 3 4521 1056 2999 2 0 1 5867 1 5862 1 5867 2 5 5865 1 5867 3 5862 2 0 1 5867 4 5 5859 6 0 1 5867 5 5862 1 0 0 0 1 5867 6 5 4508 3300 3178 1 0 1 5869 1 5867 1 5869 2 2 5868 1 5869 3 5867 4 0 1 5869 4 2 3845 3 0 1 5869 5 5867 10 0 0 0 1 5869 6 2 767 5450 4506 0 0 1 5879 1 5868 1 5879 2 11 5877 1 5879 3 5868 11 0 1 5879 4 11 5039 5 0 1 5879 5 5868 5 0 0 0 1 5879 6 11 5094 4222 4253 2 0 1 5881 1 5850 1 5881 2 31 5876 1 5881 3 5850 5 0 1 5881 4 31 5848 16 0 1 5881 5 5850 2 0 0 0 1 5881 6 31 4546 2592 4096 0 0 1 5897 1 5894 1 5897 2 3 5892 1 5897 3 5894 9 0 1 5897 4 3 4016 8 0 1 5897 5 5894 3 0 0 0 1 5897 6 3 1149 1348 716 1 0 1 5903 1 5898 1 5903 2 5 5901 1 5903 3 5898 2 0 1 5903 4 5 5899 3 0 1 5903 5 5898 2 0 0 0 1 5903 6 5 3098 1573 314 3 0 1 5923 1 5921 1 5923 2 2 5919 1 5923 3 5921 5 0 1 5923 4 2 3089 8 0 1 5923 5 5921 4 0 0 0 1 5923 6 2 4010 5787 3895 0 0 1 5927 1 5922 1 5927 2 5 5926 1 5927 3 5922 2 0 1 5927 4 5 3813 3 0 1 5927 5 5922 6 0 0 0 1 5927 6 5 4057 5756 5257 1 0 1 5939 1 5937 1 5939 2 2 5935 1 5939 3 5937 3 0 1 5939 4 2 5109 7 0 1 5939 5 5937 2 0 0 0 1 5939 6 2 1341 2001 5778 1 0 1 5953 1 5946 1 5953 2 7 5946 1 5953 3 5946 2 0 1 5953 4 7 5381 18 0 1 5953 5 5946 1 0 0 0 1 5953 6 7 834 2240 4791 0 0 1 5981 1 5978 1 5981 2 3 5980 1 5981 3 5978 5 0 1 5981 4 3 3130 3 0 1 5981 5 5978 5 0 0 0 1 5981 6 3 5402 5980 3703 2 0 1 5987 1 5985 1 5987 2 2 5983 1 5987 3 5985 3 0 1 5987 4 2 5641 7 0 1 5987 5 5985 16 0 0 0 1 5987 6 2 3661 3911 205 3 0 1 6007 1 6004 1 6007 2 3 6005 1 6007 3 6004 3 0 1 6007 4 3 5427 3 0 1 6007 5 6004 9 0 0 0 1 6007 6 3 1729 5799 285 0 0 1 6011 1 6009 1 6011 2 2 6007 1 6011 3 6009 3 0 1 6011 4 2 3814 7 0 1 6011 5 6009 18 0 0 0 1 6011 6 2 2903 5566 956 2 0 1 6029 1 6027 1 6029 2 2 6025 1 6029 3 6027 3 0 1 6029 4 2 4854 6 0 1 6029 5 6027 11 0 0 0 1 6029 6 2 3826 933 1263 1 0 1 6037 1 6032 1 6037 2 5 6036 1 6037 3 6032 3 0 1 6037 4 5 4169 3 0 1 6037 5 6032 2 0 0 0 1 6037 6 5 2142 5518 2213 1 0 1 6043 1 6038 1 6043 2 5 6041 1 6043 3 6038 2 0 1 6043 4 5 6035 6 0 1 6043 5 6038 5 0 0 0 1 6043 6 5 2565 3936 3603 1 0 1 6047 1 6042 1 6047 2 5 6044 1 6047 3 6042 8 0 1 6047 4 5 4284 4 0 1 6047 5 6042 3 0 0 0 1 6047 6 5 5019 3051 3663 2 0 1 6053 1 6051 1 6053 2 2 6052 1 6053 3 6051 2 0 1 6053 4 2 6046 8 0 1 6053 5 6051 3 0 0 0 1 6053 6 2 376 426 4554 1 0 1 6067 1 6065 1 6067 2 2 6066 1 6067 3 6065 6 0 1 6067 4 2 5710 7 0 1 6067 5 6065 2 0 0 0 1 6067 6 2 876 3284 3354 0 0 1 6073 1 6063 1 6073 2 10 6072 1 6073 3 6063 4 0 1 6073 4 10 3299 16 0 1 6073 5 6063 2 0 0 0 1 6073 6 10 5420 1253 6051 1 0 1 6079 1 6062 1 6079 2 17 6077 1 6079 3 6062 6 0 1 6079 4 17 6071 3 0 1 6079 5 6062 1 0 0 0 1 6079 6 17 1413 5393 513 0 0 1 6089 1 6086 1 6089 2 3 6088 1 6089 3 6086 3 0 1 6089 4 3 4969 7 0 1 6089 5 6086 7 0 0 0 1 6089 6 3 485 1448 2643 1 0 1 6091 1 6084 1 6091 2 7 6089 1 6091 3 6084 2 0 1 6091 4 7 4936 6 0 1 6091 5 6084 1 0 0 0 1 6091 6 7 2839 484 5594 2 0 1 6101 1 6099 1 6101 2 2 6097 1 6101 3 6099 3 0 1 6101 4 2 4125 12 0 1 6101 5 6099 3 0 0 0 1 6101 6 2 1347 940 4989 1 0 1 6113 1 6110 1 6113 2 3 6112 1 6113 3 6110 5 0 1 6113 4 3 4935 4 0 1 6113 5 6110 4 0 0 0 1 6113 6 3 3957 4751 4691 2 0 1 6121 1 6114 1 6121 2 7 6118 1 6121 3 6114 5 0 1 6121 4 7 4176 16 0 1 6121 5 6114 1 0 0 0 1 6121 6 7 4024 2225 4299 0 0 1 6131 1 6129 1 6131 2 2 6126 1 6131 3 6129 5 0 1 6131 4 2 4866 3 0 1 6131 5 6129 10 0 0 0 1 6131 6 2 840 3151 3592 1 0 1 6133 1 6128 1 6133 2 5 6132 1 6133 3 6128 12 0 1 6133 4 5 4719 3 0 1 6133 5 6128 3 0 0 0 1 6133 6 5 187 5292 2412 0 0 1 6143 1 6138 1 6143 2 5 6141 1 6143 3 6138 6 0 1 6143 4 5 5375 8 0 1 6143 5 6138 5 0 0 0 1 6143 6 5 2112 319 5720 3 0 1 6151 1 6148 1 6151 2 3 6150 1 6151 3 6148 1 0 1 6151 4 3 5687 2 0 1 6151 5 6148 3 0 0 0 1 6151 6 3 1739 781 4259 0 0 1 6163 1 6160 1 6163 2 3 6154 1 6163 3 6160 1 0 1 6163 4 3 4191 10 0 1 6163 5 6160 11 0 0 0 1 6163 6 3 3969 1252 6155 0 0 1 6173 1 6171 1 6173 2 2 6172 1 6173 3 6171 2 0 1 6173 4 2 5879 3 0 1 6173 5 6171 16 0 0 0 1 6173 6 2 1787 5731 2807 2 0 1 6197 1 6195 1 6197 2 2 6193 1 6197 3 6195 3 0 1 6197 4 2 4395 7 0 1 6197 5 6195 2 0 0 0 1 6197 6 2 4487 2745 5836 1 0 1 6199 1 6196 1 6199 2 3 6197 1 6199 3 6196 11 0 1 6199 4 3 6195 4 0 1 6199 5 6196 12 0 0 0 1 6199 6 3 5339 3145 1684 0 0 1 6203 1 6201 1 6203 2 2 6197 1 6203 3 6201 7 0 1 6203 4 2 4407 4 0 1 6203 5 6201 16 0 0 0 1 6203 6 2 3723 3336 317 2 0 1 6211 1 6209 1 6211 2 2 6207 1 6211 3 6209 2 0 1 6211 4 2 3831 8 0 1 6211 5 6209 6 0 0 0 1 6211 6 2 4401 3423 1452 0 0 1 6217 1 6212 1 6217 2 5 6214 1 6217 3 6212 1 0 1 6217 4 5 4005 18 0 1 6217 5 6212 6 0 0 0 1 6217 6 5 4686 324 3426 0 0 1 6221 1 6218 1 6221 2 3 6220 1 6221 3 6218 1 0 1 6221 4 3 4737 3 0 1 6221 5 6218 5 0 0 0 1 6221 6 3 767 4690 2283 4 0 1 6229 1 6227 1 6229 2 2 6225 1 6229 3 6227 6 0 1 6229 4 2 5804 6 0 1 6229 5 6227 3 0 0 0 1 6229 6 2 6217 6211 6225 0 0 1 6247 1 6242 1 6247 2 5 6246 1 6247 3 6242 1 0 1 6247 4 5 4249 10 0 1 6247 5 6242 2 0 0 0 1 6247 6 5 5013 3016 863 0 0 1 6257 1 6254 1 6257 2 3 6248 1 6257 3 6254 1 0 1 6257 4 3 5301 3 0 1 6257 5 6254 5 0 0 0 1 6257 6 3 3820 902 764 1 0 1 6263 1 6258 1 6263 2 5 6262 1 6263 3 6258 1 0 1 6263 4 5 3733 7 0 1 6263 5 6258 2 0 0 0 1 6263 6 5 2635 2176 743 4 0 1 6269 1 6267 1 6269 2 2 6265 1 6269 3 6267 2 0 1 6269 4 2 5915 12 0 1 6269 5 6267 19 0 0 0 1 6269 6 2 4080 614 5113 1 0 1 6271 1 6260 1 6271 2 11 6267 1 6271 3 6260 3 0 1 6271 4 11 3429 1 0 1 6271 5 6260 3 0 0 0 1 6271 6 11 4877 5120 2956 0 0 1 6277 1 6275 1 6277 2 2 6276 1 6277 3 6275 2 0 1 6277 4 2 5873 3 0 1 6277 5 6275 3 0 0 0 1 6277 6 2 2132 1671 4081 0 0 1 6287 1 6280 1 6287 2 7 6285 1 6287 3 6280 2 0 1 6287 4 7 5422 5 0 1 6287 5 6280 7 0 0 0 1 6287 6 7 4689 149 2056 1 0 1 6299 1 6297 1 6299 2 2 6288 1 6299 3 6297 5 0 1 6299 4 2 5835 1 0 1 6299 5 6297 5 0 0 0 1 6299 6 2 5417 5643 2902 1 0 1 6301 1 6291 1 6301 2 10 6297 1 6301 3 6291 6 0 1 6301 4 10 3648 12 0 1 6301 5 6291 1 0 0 0 1 6301 6 10 1594 3503 229 0 0 1 6311 1 6304 1 6311 2 7 6310 1 6311 3 6304 2 0 1 6311 4 7 5361 2 0 1 6311 5 6304 7 0 0 0 1 6311 6 7 3661 4292 3292 1 0 1 6317 1 6315 1 6317 2 2 6316 1 6317 3 6315 2 0 1 6317 4 2 5652 6 0 1 6317 5 6315 2 0 0 0 1 6317 6 2 4441 2796 4421 1 0 1 6323 1 6321 1 6323 2 2 6311 1 6323 3 6321 8 0 1 6323 4 2 5598 6 0 1 6323 5 6321 2 0 0 0 1 6323 6 2 5335 6243 547 1 0 1 6329 1 6326 1 6329 2 3 6324 1 6329 3 6326 1 0 1 6329 4 3 6151 2 0 1 6329 5 6326 4 0 0 0 1 6329 6 3 1099 3130 695 1 0 1 6337 1 6327 1 6337 2 10 6336 1 6337 3 6327 2 0 1 6337 4 10 5231 6 0 1 6337 5 6327 6 0 0 0 1 6337 6 10 6074 4620 4918 0 0 1 6343 1 6340 1 6343 2 3 6342 1 6343 3 6340 1 0 1 6343 4 3 3971 14 0 1 6343 5 6340 5 0 0 0 1 6343 6 3 5827 5075 5042 1 0 1 6353 1 6350 1 6353 2 3 6352 1 6353 3 6350 7 0 1 6353 4 3 5517 7 0 1 6353 5 6350 1 0 0 0 1 6353 6 3 1406 6344 1479 1 0 1 6359 1 6346 1 6359 2 13 6358 1 6359 3 6346 1 0 1 6359 4 13 6246 2 0 1 6359 5 6346 17 0 0 0 1 6359 6 13 852 4721 6094 1 0 1 6361 1 6342 1 6361 2 19 6358 1 6361 3 6342 5 0 1 6361 4 19 4383 10 0 1 6361 5 6342 13 0 0 0 1 6361 6 19 1181 629 5908 0 0 1 6367 1 6364 1 6367 2 3 6365 1 6367 3 6364 3 0 1 6367 4 3 5709 3 0 1 6367 5 6364 3 0 0 0 1 6367 6 3 1894 5862 4612 0 0 1 6373 1 6371 1 6373 2 2 6372 1 6373 3 6371 2 0 1 6373 4 2 6366 8 0 1 6373 5 6371 3 0 0 0 1 6373 6 2 5239 3274 6004 0 0 1 6379 1 6377 1 6379 2 2 6370 1 6379 3 6377 4 0 1 6379 4 2 3885 2 0 1 6379 5 6377 5 0 0 0 1 6379 6 2 5798 2466 757 3 0 1 6389 1 6387 1 6389 2 2 6388 1 6389 3 6387 3 0 1 6389 4 2 6382 8 0 1 6389 5 6387 2 0 0 0 1 6389 6 2 1872 576 4136 4 0 1 6397 1 6395 1 6397 2 2 6396 1 6397 3 6395 2 0 1 6397 4 2 6218 9 0 1 6397 5 6395 2 0 0 0 1 6397 6 2 2137 983 1992 0 0 1 6421 1 6415 1 6421 2 6 6417 1 6421 3 6415 9 0 1 6421 4 6 3300 2 0 1 6421 5 6415 6 0 0 0 1 6421 6 6 1652 805 3697 1 0 1 6427 1 6424 1 6427 2 3 6422 1 6427 3 6424 6 0 1 6427 4 3 5590 3 0 1 6427 5 6424 9 0 0 0 1 6427 6 3 1225 4193 4170 0 0 1 6449 1 6446 1 6449 2 3 6443 1 6449 3 6446 6 0 1 6449 4 3 6437 0 0 1 6449 5 6446 7 0 0 0 1 6449 6 3 3985 2704 1378 4 0 1 6451 1 6448 1 6451 2 3 6444 1 6451 3 6448 3 0 1 6451 4 3 5883 5 0 1 6451 5 6448 8 0 0 0 1 6451 6 3 4522 5757 4142 0 0 1 6469 1 6467 1 6469 2 2 6465 1 6469 3 6467 2 0 1 6469 4 2 4409 12 0 1 6469 5 6467 7 0 0 0 1 6469 6 2 5646 1235 1560 2 0 1 6473 1 6470 1 6473 2 3 6467 1 6473 3 6470 7 0 1 6473 4 3 3818 9 0 1 6473 5 6470 1 0 0 0 1 6473 6 3 524 1141 2150 3 0 1 6481 1 6474 1 6481 2 7 6478 1 6481 3 6474 1 0 1 6481 4 7 5873 16 0 1 6481 5 6474 8 0 0 0 1 6481 6 7 1488 3948 2363 0 0 1 6491 1 6489 1 6491 2 2 6487 1 6491 3 6489 3 0 1 6491 4 2 3747 7 0 1 6491 5 6489 4 0 0 0 1 6491 6 2 5503 6117 837 1 0 1 6521 1 6515 1 6521 2 6 6515 1 6521 3 6515 6 0 1 6521 4 6 3760 0 0 1 6521 5 6515 6 0 0 0 1 6521 6 6 2751 1750 6329 2 0 1 6529 1 6522 1 6529 2 7 6526 1 6529 3 6522 1 0 1 6529 4 7 5221 17 0 1 6529 5 6522 1 0 0 0 1 6529 6 7 2223 2089 1712 0 0 1 6547 1 6545 1 6547 2 2 6543 1 6547 3 6545 6 0 1 6547 4 2 3676 8 0 1 6547 5 6545 9 0 0 0 1 6547 6 2 6535 6529 6543 0 0 1 6551 1 6534 1 6551 2 17 6550 1 6551 3 6534 1 0 1 6551 4 17 3541 2 0 1 6551 5 6534 11 0 0 0 1 6551 6 17 757 3626 3950 1 0 1 6553 1 6543 1 6553 2 10 6550 1 6553 3 6543 3 0 1 6553 4 10 6219 8 0 1 6553 5 6543 24 0 0 0 1 6553 6 10 1417 2186 6188 0 0 1 6563 1 6558 1 6563 2 5 6561 1 6563 3 6558 1 0 1 6563 4 5 6555 6 0 1 6563 5 6558 9 0 0 0 1 6563 6 5 2323 4178 4246 1 0 1 6569 1 6566 1 6569 2 3 6568 1 6569 3 6566 4 0 1 6569 4 3 6125 7 0 1 6569 5 6566 16 0 0 0 1 6569 6 3 1853 3838 6126 1 0 1 6571 1 6568 1 6571 2 3 6566 1 6571 3 6568 4 0 1 6571 4 3 4564 3 0 1 6571 5 6568 1 0 0 0 1 6571 6 3 410 3112 3877 0 0 1 6577 1 6572 1 6577 2 5 6576 1 6577 3 6572 3 0 1 6577 4 5 4769 6 0 1 6577 5 6572 1 0 0 0 1 6577 6 5 1408 995 6264 0 0 1 6581 1 6567 1 6581 2 14 6577 1 6581 3 6567 2 0 1 6581 4 14 6043 1 0 1 6581 5 6567 3 0 0 0 1 6581 6 14 3255 2186 5790 1 0 1 6599 1 6586 1 6599 2 13 6586 1 6599 3 6586 2 0 1 6599 4 13 6418 15 0 1 6599 5 6586 5 0 0 0 1 6599 6 13 2581 5600 2426 2 0 1 6607 1 6604 1 6607 2 3 6606 1 6607 3 6604 3 0 1 6607 4 3 6492 2 0 1 6607 5 6604 3 0 0 0 1 6607 6 3 1568 6135 2932 0 0 1 6619 1 6617 1 6619 2 2 6614 1 6619 3 6617 6 0 1 6619 4 2 4540 3 0 1 6619 5 6617 3 0 0 0 1 6619 6 2 5406 784 1425 0 0 1 6637 1 6635 1 6637 2 2 6633 1 6637 3 6635 6 0 1 6637 4 2 4675 6 0 1 6637 5 6635 2 0 0 0 1 6637 6 2 6625 6619 6633 0 0 1 6653 1 6651 1 6653 2 2 6652 1 6653 3 6651 2 0 1 6653 4 2 3675 6 0 1 6653 5 6651 3 0 0 0 1 6653 6 2 6102 1495 3732 1 0 1 6659 1 6657 1 6659 2 2 6655 1 6659 3 6657 3 0 1 6659 4 2 5754 8 0 1 6659 5 6657 7 0 0 0 1 6659 6 2 4969 5657 6486 1 0 1 6661 1 6655 1 6661 2 6 6660 1 6661 3 6655 1 0 1 6661 4 6 3579 7 0 1 6661 5 6655 4 0 0 0 1 6661 6 6 198 5037 4210 1 0 1 6673 1 6668 1 6673 2 5 6670 1 6673 3 6668 7 0 1 6673 4 5 6662 14 0 1 6673 5 6668 2 0 0 0 1 6673 6 5 3662 844 4835 3 0 1 6679 1 6672 1 6679 2 7 6676 1 6679 3 6672 1 0 1 6679 4 7 6084 5 0 1 6679 5 6672 10 0 0 0 1 6679 6 7 3803 3644 2537 0 0 1 6689 1 6686 1 6689 2 3 6684 1 6689 3 6686 3 0 1 6689 4 3 3532 2 0 1 6689 5 6686 3 0 0 0 1 6689 6 3 5708 4934 6026 4 0 1 6691 1 6689 1 6691 2 2 6690 1 6691 3 6689 5 0 1 6691 4 2 5612 2 0 1 6691 5 6689 13 0 0 0 1 6691 6 2 4749 150 6099 0 0 1 6701 1 6699 1 6701 2 2 6697 1 6701 3 6699 3 0 1 6701 4 2 6518 6 0 1 6701 5 6699 2 0 0 0 1 6701 6 2 278 2145 3624 1 0 1 6703 1 6698 1 6703 2 5 6702 1 6703 3 6698 3 0 1 6703 4 5 5107 5 0 1 6703 5 6698 6 0 0 0 1 6703 6 5 4801 5837 6622 1 0 1 6709 1 6707 1 6709 2 2 6708 1 6709 3 6707 5 0 1 6709 4 2 4545 3 0 1 6709 5 6707 12 0 0 0 1 6709 6 2 2390 5583 1108 0 0 1 6719 1 6708 1 6719 2 11 6716 1 6719 3 6708 1 0 1 6719 4 11 5879 6 0 1 6719 5 6708 5 0 0 0 1 6719 6 11 5545 2901 2787 1 0 1 6733 1 6731 1 6733 2 2 6732 1 6733 3 6731 2 0 1 6733 4 2 5096 6 0 1 6733 5 6731 6 0 0 0 1 6733 6 2 5670 4209 5611 0 0 1 6737 1 6734 1 6737 2 3 6731 1 6737 3 6734 5 0 1 6737 4 3 4969 12 0 1 6737 5 6734 3 0 0 0 1 6737 6 3 4305 3010 3041 1 0 1 6761 1 6758 1 6761 2 3 6760 1 6761 3 6758 5 0 1 6761 4 3 3691 7 0 1 6761 5 6758 9 0 0 0 1 6761 6 3 5874 5625 5122 2 0 1 6763 1 6761 1 6763 2 2 6758 1 6763 3 6761 6 0 1 6763 4 2 3708 0 0 1 6763 5 6761 3 0 0 0 1 6763 6 2 2068 1859 6719 0 0 1 6779 1 6777 1 6779 2 2 6775 1 6779 3 6777 3 0 1 6779 4 2 3633 7 0 1 6779 5 6777 2 0 0 0 1 6779 6 2 762 1713 5811 1 0 1 6781 1 6779 1 6781 2 2 6780 1 6781 3 6779 4 0 1 6781 4 2 6422 7 0 1 6781 5 6779 4 0 0 0 1 6781 6 2 4279 2576 5639 0 0 1 6791 1 6784 1 6791 2 7 6789 1 6791 3 6784 2 0 1 6791 4 7 6226 4 0 1 6791 5 6784 14 0 0 0 1 6791 6 7 4446 4602 2743 2 0 1 6793 1 6783 1 6793 2 10 6792 1 6793 3 6783 2 0 1 6793 4 10 3546 8 0 1 6793 5 6783 6 0 0 0 1 6793 6 10 2987 917 4415 0 0 1 6803 1 6801 1 6803 2 2 6799 1 6803 3 6801 2 0 1 6803 4 2 5750 14 0 1 6803 5 6801 5 0 0 0 1 6803 6 2 612 2018 6190 1 0 1 6823 1 6820 1 6823 2 3 6821 1 6823 3 6820 8 0 1 6823 4 3 6819 4 0 1 6823 5 6820 1 0 0 0 1 6823 6 3 1630 3578 6433 0 0 1 6827 1 6825 1 6827 2 2 6823 1 6827 3 6825 3 0 1 6827 4 2 4068 7 0 1 6827 5 6825 5 0 0 0 1 6827 6 2 5263 3597 6226 1 0 1 6829 1 6827 1 6829 2 2 6825 1 6829 3 6827 2 0 1 6829 4 2 6384 6 0 1 6829 5 6827 2 0 0 0 1 6829 6 2 4259 4000 6425 0 0 1 6833 1 6830 1 6833 2 3 6832 1 6833 3 6830 1 0 1 6833 4 3 6428 4 0 1 6833 5 6830 3 0 0 0 1 6833 6 3 3213 4297 4331 2 0 1 6841 1 6819 1 6841 2 22 6840 1 6841 3 6819 1 0 1 6841 4 22 5338 18 0 1 6841 5 6819 2 0 0 0 1 6841 6 22 53 1004 6303 0 0 1 6857 1 6854 1 6857 2 3 6852 1 6857 3 6854 4 0 1 6857 4 3 3578 0 0 1 6857 5 6854 1 0 0 0 1 6857 6 3 4241 4549 6371 1 0 1 6863 1 6858 1 6863 2 5 6860 1 6863 3 6858 3 0 1 6863 4 5 3569 6 0 1 6863 5 6858 3 0 0 0 1 6863 6 5 1806 5646 3396 1 0 1 6869 1 6867 1 6869 2 2 6865 1 6869 3 6867 3 0 1 6869 4 2 5754 12 0 1 6869 5 6867 3 0 0 0 1 6869 6 2 1589 4498 1535 2 0 1 6871 1 6868 1 6871 2 3 6870 1 6871 3 6868 1 0 1 6871 4 3 3573 2 0 1 6871 5 6868 1 0 0 0 1 6871 6 3 2819 4821 4520 0 0 1 6883 1 6881 1 6883 2 2 6879 1 6883 3 6881 6 0 1 6883 4 2 4187 8 0 1 6883 5 6881 11 0 0 0 1 6883 6 2 6871 6865 6879 0 0 1 6899 1 6897 1 6899 2 2 6895 1 6899 3 6897 3 0 1 6899 4 2 5297 7 0 1 6899 5 6897 19 0 0 0 1 6899 6 2 3996 6687 5926 2 0 1 6907 1 6905 1 6907 2 2 6906 1 6907 3 6905 9 0 1 6907 4 2 6900 8 0 1 6907 5 6905 6 0 0 0 1 6907 6 2 226 1334 5841 0 0 1 6911 1 6904 1 6911 2 7 6910 1 6911 3 6904 3 0 1 6911 4 7 6479 2 0 1 6911 5 6904 25 0 0 0 1 6911 6 7 3787 3523 646 1 0 1 6917 1 6915 1 6917 2 2 6913 1 6917 3 6915 3 0 1 6917 4 2 4673 9 0 1 6917 5 6915 28 0 0 0 1 6917 6 2 2784 5776 3952 1 0 1 6947 1 6945 1 6947 2 2 6942 1 6947 3 6945 2 0 1 6947 4 2 6296 3 0 1 6947 5 6945 15 0 0 0 1 6947 6 2 5933 5914 5586 3 0 1 6949 1 6947 1 6949 2 2 6948 1 6949 3 6947 4 0 1 6949 4 2 5165 3 0 1 6949 5 6947 3 0 0 0 1 6949 6 2 6814 4446 4030 0 0 1 6959 1 6952 1 6959 2 7 6957 1 6959 3 6952 10 0 1 6959 4 7 5088 13 0 1 6959 5 6952 3 0 0 0 1 6959 6 7 395 5933 3213 1 0 1 6961 1 6948 1 6961 2 13 6950 1 6961 3 6948 3 0 1 6961 4 13 5425 18 0 1 6961 5 6948 1 0 0 0 1 6961 6 13 787 5199 2288 2 0 1 6967 1 6962 1 6967 2 5 6965 1 6967 3 6962 12 0 1 6967 4 5 3595 17 0 1 6967 5 6962 2 0 0 0 1 6967 6 5 6552 1246 6016 0 0 1 6971 1 6969 1 6971 2 2 6970 1 6971 3 6969 10 0 1 6971 4 2 5192 2 0 1 6971 5 6969 13 0 0 0 1 6971 6 2 6619 3007 3606 2 0 1 6977 1 6974 1 6977 2 3 6971 1 6977 3 6974 5 0 1 6977 4 3 6423 9 0 1 6977 5 6974 17 0 0 0 1 6977 6 3 3216 6689 1076 1 0 1 6983 1 6978 1 6983 2 5 6974 1 6983 3 6978 9 0 1 6983 4 5 6746 4 0 1 6983 5 6978 2 0 0 0 1 6983 6 5 704 6370 5285 4 0 1 6991 1 6985 1 6991 2 6 6990 1 6991 3 6985 1 0 1 6991 4 6 4491 3 0 1 6991 5 6985 2 0 0 0 1 6991 6 6 1313 1793 3115 0 0 1 6997 1 6992 1 6997 2 5 6992 1 6997 3 6992 9 0 1 6997 4 5 5900 20 0 1 6997 5 6992 10 0 0 0 1 6997 6 5 5945 458 2575 0 0 1 7001 1 6998 1 7001 2 3 6994 1 7001 3 6998 3 0 1 7001 4 3 4330 1 0 1 7001 5 6998 4 0 0 0 1 7001 6 3 4025 3151 2368 1 0 1 7013 1 7011 1 7013 2 2 7012 1 7013 3 7011 2 0 1 7013 4 2 5076 3 0 1 7013 5 7011 21 0 0 0 1 7013 6 2 6926 5439 4350 1 0 1 7019 1 7017 1 7019 2 2 7015 1 7019 3 7017 3 0 1 7019 4 2 4031 7 0 1 7019 5 7017 3 0 0 0 1 7019 6 2 461 5640 2328 2 0 1 7027 1 7025 1 7027 2 2 7026 1 7027 3 7025 4 0 1 7027 4 2 4903 7 0 1 7027 5 7025 8 0 0 0 1 7027 6 2 421 4131 6876 0 0 1 7039 1 7036 1 7039 2 3 7038 1 7039 3 7036 5 0 1 7039 4 3 4087 3 0 1 7039 5 7036 9 0 0 0 1 7039 6 3 6693 3074 3617 0 0 1 7043 1 7041 1 7043 2 2 7037 1 7043 3 7041 4 0 1 7043 4 2 6012 25 0 1 7043 5 7041 4 0 0 0 1 7043 6 2 1762 2987 3991 2 0 1 7057 1 7052 1 7057 2 5 7056 1 7057 3 7052 2 0 1 7057 4 5 4013 6 0 1 7057 5 7052 7 0 0 0 1 7057 6 5 326 1378 6981 0 0 1 7069 1 7067 1 7069 2 2 7065 1 7069 3 7067 6 0 1 7069 4 2 6317 6 0 1 7069 5 7067 2 0 0 0 1 7069 6 2 7057 7051 7065 0 0 1 7079 1 7072 1 7079 2 7 7077 1 7079 3 7072 1 0 1 7079 4 7 6370 5 0 1 7079 5 7072 8 0 0 0 1 7079 6 7 6760 944 5256 1 0 1 7103 1 7098 1 7103 2 5 7101 1 7103 3 7098 3 0 1 7103 4 5 6519 9 0 1 7103 5 7098 16 0 0 0 1 7103 6 5 6748 5159 5353 3 0 1 7109 1 7107 1 7109 2 2 7100 1 7109 3 7107 2 0 1 7109 4 2 5252 1 0 1 7109 5 7107 6 0 0 0 1 7109 6 2 4001 1752 258 1 0 1 7121 1 7118 1 7121 2 3 7115 1 7121 3 7118 6 0 1 7121 4 3 7109 0 0 1 7121 5 7118 1 0 0 0 1 7121 6 3 1471 4940 2839 1 0 1 7127 1 7122 1 7127 2 5 7126 1 7127 3 7122 8 0 1 7127 4 5 3637 4 0 1 7127 5 7122 1 0 0 0 1 7127 6 5 5469 402 644 3 0 1 7129 1 7122 1 7129 2 7 7120 1 7129 3 7122 2 0 1 7129 4 7 3757 16 0 1 7129 5 7122 1 0 0 0 1 7129 6 7 1515 6041 2103 0 0 1 7151 1 7144 1 7151 2 7 7150 1 7151 3 7144 5 0 1 7151 4 7 3932 7 0 1 7151 5 7144 3 0 0 0 1 7151 6 7 1854 1423 1105 1 0 1 7159 1 7156 1 7159 2 3 7157 1 7159 3 7156 3 0 1 7159 4 3 6236 3 0 1 7159 5 7156 3 0 0 0 1 7159 6 3 1474 193 3635 0 0 1 7177 1 7167 1 7177 2 10 7172 1 7177 3 7167 3 0 1 7177 4 10 4338 15 0 1 7177 5 7167 1 0 0 0 1 7177 6 10 3113 6174 3830 0 0 1 7187 1 7185 1 7187 2 2 7186 1 7187 3 7185 2 0 1 7187 4 2 6410 4 0 1 7187 5 7185 6 0 0 0 1 7187 6 2 4440 6639 5701 1 0 1 7193 1 7190 1 7193 2 3 7187 1 7193 3 7190 1 0 1 7193 4 3 3771 11 0 1 7193 5 7190 4 0 0 0 1 7193 6 3 2785 6600 3366 1 0 1 7207 1 7204 1 7207 2 3 7206 1 7207 3 7204 4 0 1 7207 4 3 3716 5 0 1 7207 5 7204 3 0 0 0 1 7207 6 3 5204 2384 180 0 0 1 7211 1 7209 1 7211 2 2 7207 1 7211 3 7209 3 0 1 7211 4 2 6379 8 0 1 7211 5 7209 8 0 0 0 1 7211 6 2 402 5798 1605 1 0 1 7213 1 7208 1 7213 2 5 7212 1 7213 3 7208 2 0 1 7213 4 5 4303 3 0 1 7213 5 7208 1 0 0 0 1 7213 6 5 5006 6932 3215 0 0 1 7219 1 7217 1 7219 2 2 7215 1 7219 3 7217 2 0 1 7219 4 2 4165 8 0 1 7219 5 7217 7 0 0 0 1 7219 6 2 1767 795 5732 4 0 1 7229 1 7227 1 7229 2 2 7228 1 7229 3 7227 3 0 1 7229 4 2 4625 3 0 1 7229 5 7227 11 0 0 0 1 7229 6 2 1002 52 6435 2 0 1 7237 1 7235 1 7237 2 2 7236 1 7237 3 7235 6 0 1 7237 4 2 3772 7 0 1 7237 5 7235 3 0 0 0 1 7237 6 2 6719 3532 4691 0 0 1 7243 1 7241 1 7243 2 2 7242 1 7243 3 7241 2 0 1 7243 4 2 4257 10 0 1 7243 5 7241 2 0 0 0 1 7243 6 2 1410 5830 2864 2 0 1 7247 1 7242 1 7247 2 5 7246 1 7247 3 7242 2 0 1 7247 4 5 6940 3 0 1 7247 5 7242 2 0 0 0 1 7247 6 5 5700 7009 4641 1 0 1 7253 1 7251 1 7253 2 2 7249 1 7253 3 7251 3 0 1 7253 4 2 5662 6 0 1 7253 5 7251 2 0 0 0 1 7253 6 2 21 6469 7159 1 0 1 7283 1 7281 1 7283 2 2 7282 1 7283 3 7281 3 0 1 7283 4 2 6911 2 0 1 7283 5 7281 2 0 0 0 1 7283 6 2 2502 1631 6658 1 0 1 7297 1 7292 1 7297 2 5 7292 1 7297 3 7292 5 0 1 7297 4 5 4126 10 0 1 7297 5 7292 5 0 0 0 1 7297 6 5 5735 2750 4830 0 0 1 7307 1 7305 1 7307 2 2 7306 1 7307 3 7305 2 0 1 7307 4 2 5047 2 0 1 7307 5 7305 9 0 0 0 1 7307 6 2 585 5601 130 1 0 1 7309 1 7303 1 7309 2 6 7305 1 7309 3 7303 4 0 1 7309 4 6 5705 10 0 1 7309 5 7303 7 0 0 0 1 7309 6 6 6166 5665 5038 1 0 1 7321 1 7314 1 7321 2 7 7314 1 7321 3 7314 2 0 1 7321 4 7 4513 0 0 1 7321 5 7314 1 0 0 0 1 7321 6 7 6092 2104 6562 0 0 1 7331 1 7329 1 7331 2 2 7327 1 7331 3 7329 2 0 1 7331 4 2 5535 7 0 1 7331 5 7329 5 0 0 0 1 7331 6 2 5844 3873 6972 1 0 1 7333 1 7327 1 7333 2 6 7332 1 7333 3 7327 1 0 1 7333 4 6 6200 19 0 1 7333 5 7327 13 0 0 0 1 7333 6 6 5415 5266 2398 0 0 1 7349 1 7347 1 7349 2 2 7348 1 7349 3 7347 3 0 1 7349 4 2 7052 4 0 1 7349 5 7347 2 0 0 0 1 7349 6 2 5790 252 6222 1 0 1 7351 1 7345 1 7351 2 6 7350 1 7351 3 7345 3 0 1 7351 4 6 4268 3 0 1 7351 5 7345 6 0 0 0 1 7351 6 6 5578 1302 7044 0 0 1 7369 1 7362 1 7369 2 7 7362 1 7369 3 7362 5 0 1 7369 4 7 4712 0 0 1 7369 5 7362 13 0 0 0 1 7369 6 7 2196 3185 6895 2 0 1 7393 1 7388 1 7393 2 5 7392 1 7393 3 7388 2 0 1 7393 4 5 4462 6 0 1 7393 5 7388 13 0 0 0 1 7393 6 5 259 1460 1063 0 0 1 7411 1 7409 1 7411 2 2 7410 1 7411 3 7409 6 0 1 7411 4 2 5186 12 0 1 7411 5 7409 14 0 0 0 1 7411 6 2 3431 5822 5540 0 0 1 7417 1 7412 1 7417 2 5 7412 1 7417 3 7412 7 0 1 7417 4 5 6268 10 0 1 7417 5 7412 2 0 0 0 1 7417 6 5 5540 4355 4108 0 0 1 7433 1 7430 1 7433 2 3 7432 1 7433 3 7430 4 0 1 7433 4 3 7147 4 0 1 7433 5 7430 4 0 0 0 1 7433 6 3 3233 2366 6076 1 0 1 7451 1 7449 1 7451 2 2 7444 1 7451 3 7449 4 0 1 7451 4 2 5087 1 0 1 7451 5 7449 10 0 0 0 1 7451 6 2 2909 3645 3008 1 0 1 7457 1 7454 1 7457 2 3 7456 1 7457 3 7454 3 0 1 7457 4 3 7446 12 0 1 7457 5 7454 24 0 0 0 1 7457 6 3 1190 2527 3235 1 0 1 7459 1 7457 1 7459 2 2 7455 1 7459 3 7457 6 0 1 7459 4 2 5760 8 0 1 7459 5 7457 10 0 0 0 1 7459 6 2 7447 7441 7455 0 0 1 7477 1 7475 1 7477 2 2 7473 1 7477 3 7475 5 0 1 7477 4 2 6608 6 0 1 7477 5 7475 7 0 0 0 1 7477 6 2 4847 3501 6488 0 0 1 7481 1 7475 1 7481 2 6 7478 1 7481 3 7475 4 0 1 7481 4 6 5095 0 0 1 7481 5 7475 4 0 0 0 1 7481 6 6 5246 6853 3117 1 0 1 7487 1 7482 1 7487 2 5 7485 1 7487 3 7482 1 0 1 7487 4 5 6913 5 0 1 7487 5 7482 7 0 0 0 1 7487 6 5 1146 949 6607 1 0 1 7489 1 7482 1 7489 2 7 7486 1 7489 3 7482 9 0 1 7489 4 7 4900 17 0 1 7489 5 7482 1 0 0 0 1 7489 6 7 3602 5586 3832 0 0 1 7499 1 7497 1 7499 2 2 7493 1 7499 3 7497 2 0 1 7499 4 2 5082 0 0 1 7499 5 7497 4 0 0 0 1 7499 6 2 796 3707 5190 1 0 1 7507 1 7505 1 7507 2 2 7506 1 7507 3 7505 4 0 1 7507 4 2 7500 8 0 1 7507 5 7505 2 0 0 0 1 7507 6 2 7435 2078 5967 0 0 1 7517 1 7515 1 7517 2 2 7516 1 7517 3 7515 2 0 1 7517 4 2 4573 6 0 1 7517 5 7515 11 0 0 0 1 7517 6 2 5797 5676 6158 1 0 1 7523 1 7521 1 7523 2 2 7522 1 7523 3 7521 3 0 1 7523 4 2 7329 4 0 1 7523 5 7521 4 0 0 0 1 7523 6 2 6910 7216 6368 1 0 1 7529 1 7526 1 7529 2 3 7524 1 7529 3 7526 5 0 1 7529 4 3 6670 2 0 1 7529 5 7526 1 0 0 0 1 7529 6 3 2780 3909 6608 2 0 1 7537 1 7530 1 7537 2 7 7534 1 7537 3 7530 7 0 1 7537 4 7 4898 10 0 1 7537 5 7530 2 0 0 0 1 7537 6 7 895 6822 2291 0 0 1 7541 1 7539 1 7541 2 2 7537 1 7541 3 7539 2 0 1 7541 4 2 3927 6 0 1 7541 5 7539 13 0 0 0 1 7541 6 2 4749 4047 3247 2 0 1 7547 1 7545 1 7547 2 2 7543 1 7547 3 7545 3 0 1 7547 4 2 4129 8 0 1 7547 5 7545 2 0 0 0 1 7547 6 2 5032 3183 3233 1 0 1 7549 1 7547 1 7549 2 2 7548 1 7549 3 7547 6 0 1 7549 4 2 5562 7 0 1 7549 5 7547 5 0 0 0 1 7549 6 2 5305 4439 6900 0 0 1 7559 1 7546 1 7559 2 13 7557 1 7559 3 7546 2 0 1 7559 4 13 5754 4 0 1 7559 5 7546 9 0 0 0 1 7559 6 13 1411 1583 5606 1 0 1 7561 1 7548 1 7561 2 13 7552 1 7561 3 7548 3 0 1 7561 4 13 5370 35 0 1 7561 5 7548 7 0 0 0 1 7561 6 13 3226 6576 6950 0 0 1 7573 1 7571 1 7573 2 2 7572 1 7573 3 7571 4 0 1 7573 4 2 3966 6 0 1 7573 5 7571 4 0 0 0 1 7573 6 2 3595 7410 1807 0 0 1 7577 1 7574 1 7577 2 3 7572 1 7577 3 7574 1 0 1 7577 4 3 4887 0 0 1 7577 5 7574 8 0 0 0 1 7577 6 3 1333 6254 189 1 0 1 7583 1 7578 1 7583 2 5 7578 1 7583 3 7578 3 0 1 7583 4 5 6405 6 0 1 7583 5 7578 15 0 0 0 1 7583 6 5 6021 6421 2469 1 0 1 7589 1 7587 1 7589 2 2 7585 1 7589 3 7587 3 0 1 7589 4 2 5491 6 0 1 7589 5 7587 3 0 0 0 1 7589 6 2 1436 3574 7495 2 0 1 7591 1 7585 1 7591 2 6 7589 1 7591 3 7585 4 0 1 7591 4 6 7302 3 0 1 7591 5 7585 6 0 0 0 1 7591 6 6 6269 6080 4565 0 0 1 7603 1 7601 1 7603 2 2 7599 1 7603 3 7601 5 0 1 7603 4 2 7301 8 0 1 7603 5 7601 8 0 0 0 1 7603 6 2 7353 3297 5880 1 0 1 7607 1 7602 1 7607 2 5 7605 1 7607 3 7602 1 0 1 7607 4 5 5918 8 0 1 7607 5 7602 6 0 0 0 1 7607 6 5 2945 5588 5572 1 0 1 7621 1 7619 1 7621 2 2 7620 1 7621 3 7619 5 0 1 7621 4 2 7159 9 0 1 7621 5 7619 2 0 0 0 1 7621 6 2 2265 1419 1558 0 0 1 7639 1 7632 1 7639 2 7 7628 1 7639 3 7632 1 0 1 7639 4 7 4871 12 0 1 7639 5 7632 1 0 0 0 1 7639 6 7 2491 5805 3494 0 0 1 7643 1 7641 1 7643 2 2 7642 1 7643 3 7641 8 0 1 7643 4 2 7636 8 0 1 7643 5 7641 5 0 0 0 1 7643 6 2 5555 2982 7211 1 0 1 7649 1 7646 1 7649 2 3 7644 1 7649 3 7646 3 0 1 7649 4 3 7359 8 0 1 7649 5 7646 12 0 0 0 1 7649 6 3 5418 6712 1749 3 0 1 7669 1 7667 1 7669 2 2 7665 1 7669 3 7667 2 0 1 7669 4 2 4671 12 0 1 7669 5 7667 2 0 0 0 1 7669 6 2 4020 5683 5971 0 0 1 7673 1 7670 1 7673 2 3 7667 1 7673 3 7670 5 0 1 7673 4 3 7312 11 0 1 7673 5 7670 4 0 0 0 1 7673 6 3 1329 930 6164 1 0 1 7681 1 7664 1 7681 2 17 7680 1 7681 3 7664 1 0 1 7681 4 17 7308 14 0 1 7681 5 7664 12 0 0 0 1 7681 6 17 7076 4925 6113 0 0 1 7687 1 7681 1 7687 2 6 7686 1 7687 3 7681 13 0 1 7687 4 6 5032 3 0 1 7687 5 7681 10 0 0 0 1 7687 6 6 4875 2718 4602 0 0 1 7691 1 7689 1 7691 2 2 7687 1 7691 3 7689 3 0 1 7691 4 2 7443 7 0 1 7691 5 7689 12 0 0 0 1 7691 6 2 6510 1487 1304 2 0 1 7699 1 7696 1 7699 2 3 7698 1 7699 3 7696 3 0 1 7699 4 3 6377 2 0 1 7699 5 7696 1 0 0 0 1 7699 6 3 1172 5156 5599 0 0 1 7703 1 7698 1 7703 2 5 7702 1 7703 3 7698 1 0 1 7703 4 5 6237 2 0 1 7703 5 7698 6 0 0 0 1 7703 6 5 826 6494 6471 1 0 1 7717 1 7715 1 7717 2 2 7716 1 7717 3 7715 4 0 1 7717 4 2 3957 9 0 1 7717 5 7715 7 0 0 0 1 7717 6 2 1202 2249 2931 0 0 1 7723 1 7720 1 7723 2 3 7708 1 7723 3 7720 1 0 1 7723 4 3 4643 3 0 1 7723 5 7720 3 0 0 0 1 7723 6 3 886 7164 3978 1 0 1 7727 1 7722 1 7727 2 5 7726 1 7727 3 7722 2 0 1 7727 4 5 3940 4 0 1 7727 5 7722 3 0 0 0 1 7727 6 5 3518 2100 7081 2 0 1 7741 1 7734 1 7741 2 7 7739 1 7741 3 7734 9 0 1 7741 4 7 7389 4 0 1 7741 5 7734 12 0 0 0 1 7741 6 7 6003 5031 2290 0 0 1 7753 1 7743 1 7753 2 10 7752 1 7753 3 7743 7 0 1 7753 4 10 5369 14 0 1 7753 5 7743 2 0 0 0 1 7753 6 10 6896 4162 6595 0 0 1 7757 1 7755 1 7757 2 2 7749 1 7757 3 7755 4 0 1 7757 4 2 6682 11 0 1 7757 5 7755 4 0 0 0 1 7757 6 2 6662 7212 1941 1 0 1 7759 1 7756 1 7759 2 3 7754 1 7759 3 7756 11 0 1 7759 4 3 4050 7 0 1 7759 5 7756 8 0 0 0 1 7759 6 3 3196 2762 2236 0 0 1 7789 1 7787 1 7789 2 2 7785 1 7789 3 7787 5 0 1 7789 4 2 5723 6 0 1 7789 5 7787 3 0 0 0 1 7789 6 2 1115 3539 3519 0 0 1 7793 1 7790 1 7793 2 3 7788 1 7793 3 7790 3 0 1 7793 4 3 7668 2 0 1 7793 5 7790 3 0 0 0 1 7793 6 3 3922 2501 7568 1 0 1 7817 1 7814 1 7817 2 3 7811 1 7817 3 7814 6 0 1 7817 4 3 6121 16 0 1 7817 5 7814 3 0 0 0 1 7817 6 3 6437 7096 7295 2 0 1 7823 1 7818 1 7823 2 5 7822 1 7823 3 7818 5 0 1 7823 4 5 4777 3 0 1 7823 5 7818 2 0 0 0 1 7823 6 5 2438 356 4599 3 0 1 7829 1 7827 1 7829 2 2 7828 1 7829 3 7827 3 0 1 7829 4 2 4796 3 0 1 7829 5 7827 8 0 0 0 1 7829 6 2 7155 5906 401 1 0 1 7841 1 7829 1 7841 2 12 7840 1 7841 3 7829 1 0 1 7841 4 12 6793 13 0 1 7841 5 7829 10 0 0 0 1 7841 6 12 6877 710 7133 1 0 1 7853 1 7851 1 7853 2 2 7852 1 7853 3 7851 7 0 1 7853 4 2 5386 3 0 1 7853 5 7851 10 0 0 0 1 7853 6 2 2079 5068 7765 1 0 1 7867 1 7864 1 7867 2 3 7862 1 7867 3 7864 4 0 1 7867 4 3 5804 11 0 1 7867 5 7864 1 0 0 0 1 7867 6 3 5298 6607 6744 0 0 1 7873 1 7868 1 7873 2 5 7870 1 7873 3 7868 6 0 1 7873 4 5 6445 10 0 1 7873 5 7868 3 0 0 0 1 7873 6 5 4367 1891 7380 0 0 1 7877 1 7875 1 7877 2 2 7873 1 7877 3 7875 3 0 1 7877 4 2 6597 6 0 1 7877 5 7875 5 0 0 0 1 7877 6 2 4653 1395 7625 5 0 1 7879 1 7876 1 7879 2 3 7873 1 7879 3 7876 3 0 1 7879 4 3 6527 7 0 1 7879 5 7876 1 0 0 0 1 7879 6 3 6111 1548 4084 0 0 1 7883 1 7881 1 7883 2 2 7879 1 7883 3 7881 3 0 1 7883 4 2 6618 7 0 1 7883 5 7881 6 0 0 0 1 7883 6 2 3598 6912 4848 1 0 1 7901 1 7899 1 7901 2 2 7895 1 7901 3 7899 8 0 1 7901 4 2 6435 3 0 1 7901 5 7899 2 0 0 0 1 7901 6 2 6704 7881 7263 1 0 1 7907 1 7905 1 7907 2 2 7903 1 7907 3 7905 3 0 1 7907 4 2 7224 7 0 1 7907 5 7905 15 0 0 0 1 7907 6 2 5736 6031 6389 4 0 1 7919 1 7912 1 7919 2 7 7918 1 7919 3 7912 3 0 1 7919 4 7 7322 3 0 1 7919 5 7912 8 0 0 0 1 7919 6 7 4922 5917 3472 4 0 1 7927 1 7924 1 7927 2 3 7926 1 7927 3 7924 1 0 1 7927 4 3 6367 2 0 1 7927 5 7924 4 0 0 0 1 7927 6 3 1272 6856 6150 0 0 1 7933 1 7931 1 7933 2 2 7929 1 7933 3 7931 5 0 1 7933 4 2 7734 12 0 1 7933 5 7931 5 0 0 0 1 7933 6 2 7866 3854 2022 0 0 1 7937 1 7934 1 7937 2 3 7936 1 7937 3 7934 1 0 1 7937 4 3 5414 6 0 1 7937 5 7934 14 0 0 0 1 7937 6 3 3961 509 6755 2 0 1 7949 1 7947 1 7949 2 2 7944 1 7949 3 7947 3 0 1 7949 4 2 7294 18 0 1 7949 5 7947 6 0 0 0 1 7949 6 2 6177 7753 243 5 0 1 7951 1 7945 1 7951 2 6 7949 1 7951 3 7945 1 0 1 7951 4 6 6758 3 0 1 7951 5 7945 10 0 0 0 1 7951 6 6 2016 735 7698 3 0 1 7963 1 7958 1 7963 2 5 7962 1 7963 3 7958 1 0 1 7963 4 5 4368 5 0 1 7963 5 7958 5 0 0 0 1 7963 6 5 5444 659 6806 1 0 1 7993 1 7988 1 7993 2 5 7992 1 7993 3 7988 7 0 1 7993 4 5 4905 6 0 1 7993 5 7988 11 0 0 0 1 7993 6 5 2935 2235 7864 0 0 1 8009 1 8006 1 8009 2 3 8003 1 8009 3 8006 6 0 1 8009 4 3 7997 0 0 1 8009 5 8006 5 0 0 0 1 8009 6 3 3251 5503 6841 1 0 1 8011 1 7997 1 8011 2 14 8009 1 8011 3 7997 1 0 1 8011 4 14 7273 0 0 1 8011 5 7997 31 0 0 0 1 8011 6 14 6704 4929 7473 0 0 1 8017 1 8012 1 8017 2 5 8016 1 8017 3 8012 3 0 1 8017 4 5 5204 11 0 1 8017 5 8012 7 0 0 0 1 8017 6 5 3710 7946 7470 0 0 1 8039 1 8028 1 8039 2 11 8035 1 8039 3 8028 1 0 1 8039 4 11 7648 9 0 1 8039 5 8028 1 0 0 0 1 8039 6 11 7158 7277 2220 3 0 1 8053 1 8051 1 8053 2 2 8052 1 8053 3 8051 4 0 1 8053 4 2 8046 8 0 1 8053 5 8051 2 0 0 0 1 8053 6 2 898 1783 6375 0 0 1 8059 1 8056 1 8059 2 3 8058 1 8059 3 8056 6 0 1 8059 4 3 7932 2 0 1 8059 5 8056 1 0 0 0 1 8059 6 3 6629 5055 6373 0 0 1 8069 1 8067 1 8069 2 2 8068 1 8069 3 8067 5 0 1 8069 4 2 4135 3 0 1 8069 5 8067 2 0 0 0 1 8069 6 2 6072 7997 7974 1 0 1 8081 1 8078 1 8081 2 3 8080 1 8081 3 8078 3 0 1 8081 4 3 7439 4 0 1 8081 5 8078 6 0 0 0 1 8081 6 3 5498 5491 6981 2 0 1 8087 1 8082 1 8087 2 5 8086 1 8087 3 8082 1 0 1 8087 4 5 7414 4 0 1 8087 5 8082 1 0 0 0 1 8087 6 5 472 5447 1925 1 0 1 8089 1 8072 1 8089 2 17 8078 1 8089 3 8072 2 0 1 8089 4 17 5877 28 0 1 8089 5 8072 14 0 0 0 1 8089 6 17 7517 7863 819 0 0 1 8093 1 8091 1 8093 2 2 8089 1 8093 3 8091 3 0 1 8093 4 2 6711 7 0 1 8093 5 8091 20 0 0 0 1 8093 6 2 7359 2707 7561 2 0 1 8101 1 8095 1 8101 2 6 8100 1 8101 3 8095 1 0 1 8101 4 6 5576 7 0 1 8101 5 8095 3 0 0 0 1 8101 6 6 4610 3231 3842 0 0 1 8111 1 8100 1 8111 2 11 8110 1 8111 3 8100 4 0 1 8111 4 11 4175 3 0 1 8111 5 8100 1 0 0 0 1 8111 6 11 3313 5943 1374 1 0 1 8117 1 8115 1 8117 2 2 8109 1 8117 3 8115 10 0 1 8117 4 2 4332 13 0 1 8117 5 8115 12 0 0 0 1 8117 6 2 1507 1015 7142 1 0 1 8123 1 8121 1 8123 2 2 8122 1 8123 3 8121 4 0 1 8123 4 2 5348 4 0 1 8123 5 8121 4 0 0 0 1 8123 6 2 3854 5556 3044 2 0 1 8147 1 8145 1 8147 2 2 8146 1 8147 3 8145 2 0 1 8147 4 2 7196 13 0 1 8147 5 8145 8 0 0 0 1 8147 6 2 5596 5401 7685 1 0 1 8161 1 8154 1 8161 2 7 8154 1 8161 3 8154 1 0 1 8161 4 7 7029 0 0 1 8161 5 8154 15 0 0 0 1 8161 6 7 2036 1414 7254 0 0 1 8167 1 8164 1 8167 2 3 8165 1 8167 3 8164 1 0 1 8167 4 3 6636 6 0 1 8167 5 8164 10 0 0 0 1 8167 6 3 2265 7153 7585 0 0 1 8171 1 8169 1 8171 2 2 8167 1 8171 3 8169 2 0 1 8171 4 2 4824 8 0 1 8171 5 8169 17 0 0 0 1 8171 6 2 3525 6436 5270 1 0 1 8179 1 8177 1 8179 2 2 8178 1 8179 3 8177 4 0 1 8179 4 2 6095 2 0 1 8179 5 8177 15 0 0 0 1 8179 6 2 6127 4044 2735 0 0 1 8191 1 8174 1 8191 2 17 8189 1 8191 3 8174 5 0 1 8191 4 17 8183 3 0 1 8191 5 8174 4 0 0 0 1 8191 6 17 5644 5964 7746 0 0 1 8209 1 8202 1 8209 2 7 8202 1 8209 3 8202 3 0 1 8209 4 7 4481 0 0 1 8209 5 8202 12 0 0 0 1 8209 6 7 62 2959 4046 0 0 1 8219 1 8217 1 8219 2 2 8213 1 8219 3 8217 9 0 1 8219 4 2 4992 4 0 1 8219 5 8217 8 0 0 0 1 8219 6 2 5939 3375 1851 1 0 1 8221 1 8219 1 8221 2 2 8220 1 8221 3 8219 5 0 1 8221 4 2 7152 7 0 1 8221 5 8219 3 0 0 0 1 8221 6 2 6791 7026 7234 1 0 1 8231 1 8220 1 8231 2 11 8230 1 8231 3 8220 2 0 1 8231 4 11 7131 2 0 1 8231 5 8220 2 0 0 0 1 8231 6 11 3070 2212 4203 1 0 1 8233 1 8223 1 8233 2 10 8228 1 8233 3 8223 3 0 1 8233 4 10 6061 10 0 1 8233 5 8223 6 0 0 0 1 8233 6 10 4744 7612 6108 0 0 1 8237 1 8235 1 8237 2 2 8225 1 8237 3 8235 5 0 1 8237 4 2 4806 4 0 1 8237 5 8235 11 0 0 0 1 8237 6 2 6543 4317 5886 1 0 1 8243 1 8241 1 8243 2 2 8239 1 8243 3 8241 3 0 1 8243 4 2 5696 8 0 1 8243 5 8241 4 0 0 0 1 8243 6 2 4507 2514 2990 1 0 1 8263 1 8260 1 8263 2 3 8262 1 8263 3 8260 11 0 1 8263 4 3 7377 2 0 1 8263 5 8260 4 0 0 0 1 8263 6 3 454 2810 8004 0 0 1 8269 1 8267 1 8269 2 2 8265 1 8269 3 8267 4 0 1 8269 4 2 5697 6 0 1 8269 5 8267 2 0 0 0 1 8269 6 2 4559 6757 4287 0 0 1 8273 1 8270 1 8273 2 3 8266 1 8273 3 8270 1 0 1 8273 4 3 4860 2 0 1 8273 5 8270 3 0 0 0 1 8273 6 3 2399 6059 806 1 0 1 8287 1 8284 1 8287 2 3 8282 1 8287 3 8284 1 0 1 8287 4 3 4792 6 0 1 8287 5 8284 5 0 0 0 1 8287 6 3 1330 3839 5431 0 0 1 8291 1 8289 1 8291 2 2 8287 1 8291 3 8289 3 0 1 8291 4 2 6693 7 0 1 8291 5 8289 6 0 0 0 1 8291 6 2 1582 4825 2325 1 0 1 8293 1 8291 1 8293 2 2 8292 1 8293 3 8291 6 0 1 8293 4 2 8005 3 0 1 8293 5 8291 2 0 0 0 1 8293 6 2 6472 7110 7311 0 0 1 8297 1 8294 1 8297 2 3 8286 1 8297 3 8294 6 0 1 8297 4 3 7646 5 0 1 8297 5 8294 4 0 0 0 1 8297 6 3 6022 1160 4149 1 0 1 8311 1 8308 1 8311 2 3 8310 1 8311 3 8308 3 0 1 8311 4 3 5431 3 0 1 8311 5 8308 8 0 0 0 1 8311 6 3 7511 2038 1522 0 0 1 8317 1 8311 1 8317 2 6 8316 1 8317 3 8311 3 0 1 8317 4 6 7793 6 0 1 8317 5 8311 3 0 0 0 1 8317 6 6 2429 2524 6808 0 0 1 8329 1 8322 1 8329 2 7 8322 1 8329 3 8322 8 0 1 8329 4 7 6997 0 0 1 8329 5 8322 2 0 0 0 1 8329 6 7 7712 2699 2870 0 0 1 8353 1 8348 1 8353 2 5 8352 1 8353 3 8348 1 0 1 8353 4 5 7054 6 0 1 8353 5 8348 8 0 0 0 1 8353 6 5 6800 8204 4239 0 0 1 8363 1 8361 1 8363 2 2 8362 1 8363 3 8361 2 0 1 8363 4 2 8356 8 0 1 8363 5 8361 4 0 0 0 1 8363 6 2 3927 7299 6690 1 0 1 8369 1 8366 1 8369 2 3 8363 1 8369 3 8366 1 0 1 8369 4 3 8357 0 0 1 8369 5 8366 9 0 0 0 1 8369 6 3 5099 1511 5994 1 0 1 8377 1 8372 1 8377 2 5 8374 1 8377 3 8372 6 0 1 8377 4 5 6188 10 0 1 8377 5 8372 5 0 0 0 1 8377 6 5 2821 1440 6678 0 0 1 8387 1 8385 1 8387 2 2 8382 1 8387 3 8385 9 0 1 8387 4 2 4315 0 0 1 8387 5 8385 8 0 0 0 1 8387 6 2 1580 511 3244 2 0 1 8389 1 8383 1 8389 2 6 8388 1 8389 3 8383 2 0 1 8389 4 6 5414 11 0 1 8389 5 8383 4 0 0 0 1 8389 6 6 6479 3184 5219 0 0 1 8419 1 8416 1 8419 2 3 8414 1 8419 3 8416 5 0 1 8419 4 3 6238 3 0 1 8419 5 8416 8 0 0 0 1 8419 6 3 6064 6754 5573 0 0 1 8423 1 8418 1 8423 2 5 8421 1 8423 3 8418 6 0 1 8423 4 5 8411 11 0 1 8423 5 8418 8 0 0 0 1 8423 6 5 5929 1937 64 1 0 1 8429 1 8427 1 8429 2 2 8425 1 8429 3 8427 2 0 1 8429 4 2 8111 7 0 1 8429 5 8427 2 0 0 0 1 8429 6 2 2003 5123 5355 2 0 1 8431 1 8428 1 8431 2 3 8429 1 8431 3 8428 4 0 1 8431 4 3 4337 3 0 1 8431 5 8428 1 0 0 0 1 8431 6 3 7241 2827 8415 1 0 1 8443 1 8441 1 8443 2 2 8439 1 8443 3 8441 6 0 1 8443 4 2 4731 8 0 1 8443 5 8441 7 0 0 0 1 8443 6 2 8431 8425 8439 0 0 1 8447 1 8442 1 8447 2 5 8445 1 8447 3 8442 6 0 1 8447 4 5 4690 9 0 1 8447 5 8442 3 0 0 0 1 8447 6 5 8257 6076 6828 1 0 1 8461 1 8455 1 8461 2 6 8460 1 8461 3 8455 8 0 1 8461 4 6 7804 7 0 1 8461 5 8455 2 0 0 0 1 8461 6 6 2963 2257 4200 1 0 1 8467 1 8465 1 8467 2 2 8463 1 8467 3 8465 4 0 1 8467 4 2 5912 8 0 1 8467 5 8465 2 0 0 0 1 8467 6 2 2283 7061 7008 0 0 1 8501 1 8494 1 8501 2 7 8500 1 8501 3 8494 1 0 1 8501 4 7 6003 11 0 1 8501 5 8494 10 0 0 0 1 8501 6 7 7679 7644 1322 3 0 1 8513 1 8508 1 8513 2 5 8502 1 8513 3 8508 6 0 1 8513 4 5 5492 6 0 1 8513 5 8508 1 0 0 0 1 8513 6 5 1458 7531 85 1 0 1 8521 1 8508 1 8521 2 13 8518 1 8521 3 8508 1 0 1 8521 4 13 5088 25 0 1 8521 5 8508 1 0 0 0 1 8521 6 13 3817 5411 7988 0 0 1 8527 1 8522 1 8527 2 5 8526 1 8527 3 8522 1 0 1 8527 4 5 8207 5 0 1 8527 5 8522 1 0 0 0 1 8527 6 5 1927 2709 2231 2 0 1 8537 1 8534 1 8537 2 3 8531 1 8537 3 8534 1 0 1 8537 4 3 7792 1 0 1 8537 5 8534 22 0 0 0 1 8537 6 3 5831 2444 2380 1 0 1 8539 1 8537 1 8539 2 2 8538 1 8539 3 8537 4 0 1 8539 4 2 7075 2 0 1 8539 5 8537 2 0 0 0 1 8539 6 2 6655 6418 7175 0 0 1 8543 1 8538 1 8543 2 5 8541 1 8543 3 8538 1 0 1 8543 4 5 5021 5 0 1 8543 5 8538 5 0 0 0 1 8543 6 5 2782 5208 1478 2 0 1 8563 1 8561 1 8563 2 2 8559 1 8563 3 8561 5 0 1 8563 4 2 5843 8 0 1 8563 5 8561 4 0 0 0 1 8563 6 2 8102 7430 8481 0 0 1 8573 1 8571 1 8573 2 2 8569 1 8573 3 8571 2 0 1 8573 4 2 6305 1 0 1 8573 5 8571 3 0 0 0 1 8573 6 2 7706 6841 3192 1 0 1 8581 1 8575 1 8581 2 6 8577 1 8581 3 8575 6 0 1 8581 4 6 7245 10 0 1 8581 5 8575 2 0 0 0 1 8581 6 6 5084 7059 1532 1 0 1 8597 1 8595 1 8597 2 2 8593 1 8597 3 8595 3 0 1 8597 4 2 7922 6 0 1 8597 5 8595 4 0 0 0 1 8597 6 2 6709 5455 4088 2 0 1 8599 1 8596 1 8599 2 3 8598 1 8599 3 8596 5 0 1 8599 4 3 7681 3 0 1 8599 5 8596 8 0 0 0 1 8599 6 3 4637 4756 4240 0 0 1 8609 1 8606 1 8609 2 3 8608 1 8609 3 8606 7 0 1 8609 4 3 6308 7 0 1 8609 5 8606 11 0 0 0 1 8609 6 3 4751 1907 1867 2 0 1 8623 1 8620 1 8623 2 3 8622 1 8623 3 8620 10 0 1 8623 4 3 8007 5 0 1 8623 5 8620 1 0 0 0 1 8623 6 3 2263 4793 8507 0 0 1 8627 1 8625 1 8627 2 2 8626 1 8627 3 8625 2 0 1 8627 4 2 6369 2 0 1 8627 5 8625 7 0 0 0 1 8627 6 2 6559 3726 6628 1 0 1 8629 1 8623 1 8629 2 6 8621 1 8629 3 8623 8 0 1 8629 4 6 8257 0 0 1 8629 5 8623 6 0 0 0 1 8629 6 6 8607 8139 6917 2 0 1 8641 1 8624 1 8641 2 17 8634 1 8641 3 8624 3 0 1 8641 4 17 8622 26 0 1 8641 5 8624 8 0 0 0 1 8641 6 17 811 5137 8132 0 0 1 8647 1 8644 1 8647 2 3 8645 1 8647 3 8644 1 0 1 8647 4 3 8461 3 0 1 8647 5 8644 6 0 0 0 1 8647 6 3 5759 720 3543 0 0 1 8663 1 8658 1 8663 2 5 8662 1 8663 3 8658 3 0 1 8663 4 5 6897 5 0 1 8663 5 8658 5 0 0 0 1 8663 6 5 5105 6101 4990 2 0 1 8669 1 8667 1 8669 2 2 8665 1 8669 3 8667 3 0 1 8669 4 2 6162 1 0 1 8669 5 8667 3 0 0 0 1 8669 6 2 5286 1956 5119 1 0 1 8677 1 8675 1 8677 2 2 8673 1 8677 3 8675 6 0 1 8677 4 2 7175 6 0 1 8677 5 8675 5 0 0 0 1 8677 6 2 8665 8659 8673 0 0 1 8681 1 8666 1 8681 2 15 8680 1 8681 3 8666 3 0 1 8681 4 15 5574 4 0 1 8681 5 8666 4 0 0 0 1 8681 6 15 4442 6034 7487 2 0 1 8689 1 8676 1 8689 2 13 8686 1 8689 3 8676 9 0 1 8689 4 13 8553 29 0 1 8689 5 8676 1 0 0 0 1 8689 6 13 5398 120 8133 0 0 1 8693 1 8691 1 8693 2 2 8688 1 8693 3 8691 2 0 1 8693 4 2 5646 0 0 1 8693 5 8691 5 0 0 0 1 8693 6 2 8213 3798 8606 3 0 1 8699 1 8697 1 8699 2 2 8694 1 8699 3 8697 3 0 1 8699 4 2 6822 3 0 1 8699 5 8697 11 0 0 0 1 8699 6 2 3504 7003 4612 1 0 1 8707 1 8702 1 8707 2 5 8705 1 8707 3 8702 1 0 1 8707 4 5 8703 3 0 1 8707 5 8702 2 0 0 0 1 8707 6 5 3691 3786 6104 0 0 1 8713 1 8708 1 8713 2 5 8708 1 8713 3 8708 1 0 1 8713 4 5 8053 15 0 1 8713 5 8708 1 0 0 0 1 8713 6 5 5244 6551 7568 3 0 1 8719 1 8716 1 8719 2 3 8717 1 8719 3 8716 1 0 1 8719 4 3 7179 6 0 1 8719 5 8716 3 0 0 0 1 8719 6 3 8369 6247 8216 0 0 1 8731 1 8729 1 8731 2 2 8727 1 8731 3 8729 2 0 1 8731 4 2 6427 8 0 1 8731 5 8729 3 0 0 0 1 8731 6 2 6142 4660 815 3 0 1 8737 1 8732 1 8737 2 5 8732 1 8737 3 8732 5 0 1 8737 4 5 6826 34 0 1 8737 5 8732 5 0 0 0 1 8737 6 5 2847 8068 6560 0 0 1 8741 1 8739 1 8741 2 2 8737 1 8741 3 8739 3 0 1 8741 4 2 5400 1 0 1 8741 5 8739 7 0 0 0 1 8741 6 2 7582 7150 7172 1 0 1 8747 1 8745 1 8747 2 2 8743 1 8747 3 8745 3 0 1 8747 4 2 6301 8 0 1 8747 5 8745 8 0 0 0 1 8747 6 2 3019 1296 1216 1 0 1 8753 1 8750 1 8753 2 3 8744 1 8753 3 8750 4 0 1 8753 4 3 5995 6 0 1 8753 5 8750 4 0 0 0 1 8753 6 3 3660 1441 4276 2 0 1 8761 1 8738 1 8761 2 23 8758 1 8761 3 8738 10 0 1 8761 4 23 5114 20 0 1 8761 5 8738 8 0 0 0 1 8761 6 23 7319 3611 1537 1 0 1 8779 1 8768 1 8779 2 11 8778 1 8779 3 8768 3 0 1 8779 4 11 7274 2 0 1 8779 5 8768 1 0 0 0 1 8779 6 11 7050 2306 4786 1 0 1 8783 1 8778 1 8783 2 5 8781 1 8783 3 8778 6 0 1 8783 4 5 7117 10 0 1 8783 5 8778 23 0 0 0 1 8783 6 5 3955 5862 8316 1 0 1 8803 1 8801 1 8803 2 2 8799 1 8803 3 8801 6 0 1 8803 4 2 6724 8 0 1 8803 5 8801 2 0 0 0 1 8803 6 2 8791 8785 8799 0 0 1 8807 1 8802 1 8807 2 5 8805 1 8807 3 8802 5 0 1 8807 4 5 4665 10 0 1 8807 5 8802 2 0 0 0 1 8807 6 5 1200 2306 7401 2 0 1 8819 1 8817 1 8819 2 2 8818 1 8819 3 8817 3 0 1 8819 4 2 6655 2 0 1 8819 5 8817 5 0 0 0 1 8819 6 2 2915 3630 3811 2 0 1 8821 1 8819 1 8821 2 2 8817 1 8821 3 8819 2 0 1 8821 4 2 6971 10 0 1 8821 5 8819 3 0 0 0 1 8821 6 2 6300 1857 297 0 0 1 8831 1 8824 1 8831 2 7 8830 1 8831 3 8824 1 0 1 8831 4 7 8822 4 0 1 8831 5 8824 5 0 0 0 1 8831 6 7 3580 2624 6291 1 0 1 8837 1 8835 1 8837 2 2 8833 1 8837 3 8835 3 0 1 8837 4 2 7250 1 0 1 8837 5 8835 7 0 0 0 1 8837 6 2 6956 8689 2566 2 0 1 8839 1 8836 1 8839 2 3 8837 1 8839 3 8836 1 0 1 8839 4 3 4544 6 0 1 8839 5 8836 11 0 0 0 1 8839 6 3 2176 397 8457 0 0 1 8849 1 8846 1 8849 2 3 8843 1 8849 3 8846 5 0 1 8849 4 3 8837 0 0 1 8849 5 8846 8 0 0 0 1 8849 6 3 365 3317 2590 1 0 1 8861 1 8859 1 8861 2 2 8852 1 8861 3 8859 4 0 1 8861 4 2 4774 1 0 1 8861 5 8859 2 0 0 0 1 8861 6 2 6360 3414 6144 2 0 1 8863 1 8860 1 8863 2 3 8862 1 8863 3 8860 1 0 1 8863 4 3 8306 5 0 1 8863 5 8860 15 0 0 0 1 8863 6 3 6194 2869 6513 0 0 1 8867 1 8865 1 8867 2 2 8866 1 8867 3 8865 5 0 1 8867 4 2 5451 13 0 1 8867 5 8865 4 0 0 0 1 8867 6 2 6602 2630 2828 2 0 1 8887 1 8884 1 8887 2 3 8886 1 8887 3 8884 1 0 1 8887 4 3 7808 5 0 1 8887 5 8884 3 0 0 0 1 8887 6 3 3843 8137 8361 1 0 1 8893 1 8888 1 8893 2 5 8888 1 8893 3 8888 6 0 1 8893 4 5 6168 11 0 1 8893 5 8888 13 0 0 0 1 8893 6 5 2650 334 8386 0 0 1 8923 1 8921 1 8923 2 2 8922 1 8923 3 8921 2 0 1 8923 4 2 8144 12 0 1 8923 5 8921 2 0 0 0 1 8923 6 2 3743 1143 5020 2 0 1 8929 1 8918 1 8929 2 11 8924 1 8929 3 8918 2 0 1 8929 4 11 7151 27 0 1 8929 5 8918 1 0 0 0 1 8929 6 11 595 4416 6678 0 0 1 8933 1 8931 1 8933 2 2 8929 1 8933 3 8931 3 0 1 8933 4 2 5194 7 0 1 8933 5 8931 4 0 0 0 1 8933 6 2 4122 4036 7280 1 0 1 8941 1 8935 1 8941 2 6 8940 1 8941 3 8935 6 0 1 8941 4 6 6891 11 0 1 8941 5 8935 6 0 0 0 1 8941 6 6 1810 8744 7820 0 0 1 8951 1 8938 1 8951 2 13 8946 1 8951 3 8938 5 0 1 8951 4 13 5765 11 0 1 8951 5 8938 1 0 0 0 1 8951 6 13 8329 7274 6547 3 0 1 8963 1 8961 1 8963 2 2 8962 1 8963 3 8961 2 0 1 8963 4 2 4564 13 0 1 8963 5 8961 7 0 0 0 1 8963 6 2 4734 1878 3128 1 0 1 8969 1 8966 1 8969 2 3 8957 1 8969 3 8966 5 0 1 8969 4 3 8121 0 0 1 8969 5 8966 4 0 0 0 1 8969 6 3 7099 1084 5646 2 0 1 8971 1 8969 1 8971 2 2 8967 1 8971 3 8969 2 0 1 8971 4 2 8043 8 0 1 8971 5 8969 6 0 0 0 1 8971 6 2 4491 1899 493 0 0 1 8999 1 8992 1 8999 2 7 8997 1 8999 3 8992 9 0 1 8999 4 7 8544 4 0 1 8999 5 8992 3 0 0 0 1 8999 6 7 8803 8232 6050 5 0 1 9001 1 8994 1 9001 2 7 8998 1 9001 3 8994 3 0 1 9001 4 7 5064 16 0 1 9001 5 8994 4 0 0 0 1 9001 6 7 8167 7414 7543 0 0 1 9007 1 9004 1 9007 2 3 9005 1 9007 3 9004 5 0 1 9007 4 3 9003 4 0 1 9007 5 9004 6 0 0 0 1 9007 6 3 4954 800 6000 1 0 1 9011 1 9009 1 9011 2 2 9005 1 9011 3 9009 2 0 1 9011 4 2 8821 4 0 1 9011 5 9009 4 0 0 0 1 9011 6 2 649 2187 8646 1 0 1 9013 1 9008 1 9013 2 5 9008 1 9013 3 9008 2 0 1 9013 4 5 5925 7 0 1 9013 5 9008 19 0 0 0 1 9013 6 5 8822 5809 6555 0 0 1 9029 1 9027 1 9029 2 2 9028 1 9029 3 9027 3 0 1 9029 4 2 5776 4 0 1 9029 5 9027 4 0 0 0 1 9029 6 2 7194 1991 4979 2 0 1 9041 1 9038 1 9041 2 3 9040 1 9041 3 9038 3 0 1 9041 4 3 8772 4 0 1 9041 5 9038 9 0 0 0 1 9041 6 3 6171 2124 889 1 0 1 9043 1 9040 1 9043 2 3 9038 1 9043 3 9040 1 0 1 9043 4 3 7495 12 0 1 9043 5 9040 13 0 0 0 1 9043 6 3 1849 8353 8638 0 0 1 9049 1 9042 1 9049 2 7 9042 1 9049 3 9042 2 0 1 9049 4 7 5725 0 0 1 9049 5 9042 4 0 0 0 1 9049 6 7 4624 3105 2186 0 0 1 9059 1 9057 1 9059 2 2 9055 1 9059 3 9057 2 0 1 9059 4 2 4811 7 0 1 9059 5 9057 5 0 0 0 1 9059 6 2 1482 2453 1579 2 0 1 9067 1 9064 1 9067 2 3 9062 1 9067 3 9064 10 0 1 9067 4 3 6260 3 0 1 9067 5 9064 3 0 0 0 1 9067 6 3 6562 6836 6692 0 0 1 9091 1 9088 1 9091 2 3 9080 1 9091 3 9088 3 0 1 9091 4 3 7453 0 0 1 9091 5 9088 1 0 0 0 1 9091 6 3 5472 6337 1877 0 0 1 9103 1 9097 1 9103 2 6 9100 1 9103 3 9097 6 0 1 9103 4 6 5578 5 0 1 9103 5 9097 2 0 0 0 1 9103 6 6 1096 3322 4647 0 0 1 9109 1 9099 1 9109 2 10 9106 1 9109 3 9099 6 0 1 9109 4 10 4902 5 0 1 9109 5 9099 11 0 0 0 1 9109 6 10 3208 1962 6330 0 0 1 9127 1 9124 1 9127 2 3 9126 1 9127 3 9124 1 0 1 9127 4 3 5302 5 0 1 9127 5 9124 4 0 0 0 1 9127 6 3 702 4646 7426 0 0 1 9133 1 9127 1 9133 2 6 9131 1 9133 3 9127 3 0 1 9133 4 6 6574 8 0 1 9133 5 9127 12 0 0 0 1 9133 6 6 1196 3312 2556 0 0 1 9137 1 9134 1 9137 2 3 9136 1 9137 3 9134 4 0 1 9137 4 3 5911 4 0 1 9137 5 9134 1 0 0 0 1 9137 6 3 5560 3193 7286 1 0 1 9151 1 9148 1 9151 2 3 9150 1 9151 3 9148 3 0 1 9151 4 3 8204 2 0 1 9151 5 9148 6 0 0 0 1 9151 6 3 3429 6655 5977 0 0 1 9157 1 9151 1 9157 2 6 9155 1 9157 3 9151 3 0 1 9157 4 6 6299 8 0 1 9157 5 9151 6 0 0 0 1 9157 6 6 110 1682 5647 0 0 1 9161 1 9158 1 9161 2 3 9155 1 9161 3 9158 12 0 1 9161 4 3 9149 0 0 1 9161 5 9158 3 0 0 0 1 9161 6 3 6453 200 1330 2 0 1 9173 1 9171 1 9173 2 2 9172 1 9173 3 9171 2 0 1 9173 4 2 7906 3 0 1 9173 5 9171 5 0 0 0 1 9173 6 2 2784 3937 4880 2 0 1 9181 1 9179 1 9181 2 2 9177 1 9181 3 9179 6 0 1 9181 4 2 8076 10 0 1 9181 5 9179 2 0 0 0 1 9181 6 2 9169 9163 9177 0 0 1 9187 1 9184 1 9187 2 3 9186 1 9187 3 9184 9 0 1 9187 4 3 5702 2 0 1 9187 5 9184 1 0 0 0 1 9187 6 3 190 1967 7141 0 0 1 9199 1 9196 1 9199 2 3 9197 1 9199 3 9196 1 0 1 9199 4 3 7846 3 0 1 9199 5 9196 4 0 0 0 1 9199 6 3 5822 6629 9182 0 0 1 9203 1 9201 1 9203 2 2 9202 1 9203 3 9201 2 0 1 9203 4 2 7110 4 0 1 9203 5 9201 7 0 0 0 1 9203 6 2 5524 643 8945 1 0 1 9209 1 9206 1 9209 2 3 9208 1 9209 3 9206 7 0 1 9209 4 3 7273 4 0 1 9209 5 9206 7 0 0 0 1 9209 6 3 6289 1969 4074 1 0 1 9221 1 9219 1 9221 2 2 9216 1 9221 3 9219 7 0 1 9221 4 2 7422 15 0 1 9221 5 9219 9 0 0 0 1 9221 6 2 910 722 2441 2 0 1 9227 1 9225 1 9227 2 2 9223 1 9227 3 9225 3 0 1 9227 4 2 6443 7 0 1 9227 5 9225 2 0 0 0 1 9227 6 2 9082 3243 6820 1 0 1 9239 1 9220 1 9239 2 19 9234 1 9239 3 9220 7 0 1 9239 4 19 8312 7 0 1 9239 5 9220 12 0 0 0 1 9239 6 19 1407 6785 7285 2 0 1 9241 1 9228 1 9241 2 13 9240 1 9241 3 9228 4 0 1 9241 4 13 4914 14 0 1 9241 5 9228 4 0 0 0 1 9241 6 13 7794 4004 1012 0 0 1 9257 1 9254 1 9257 2 3 9256 1 9257 3 9254 1 0 1 9257 4 3 7434 7 0 1 9257 5 9254 3 0 0 0 1 9257 6 3 5278 4027 1045 2 0 1 9277 1 9272 1 9277 2 5 9272 1 9277 3 9272 5 0 1 9277 4 5 5440 11 0 1 9277 5 9272 8 0 0 0 1 9277 6 5 4880 1596 7970 0 0 1 9281 1 9278 1 9281 2 3 9275 1 9281 3 9278 5 0 1 9281 4 3 9269 0 0 1 9281 5 9278 1 0 0 0 1 9281 6 3 8133 1833 5545 1 0 1 9283 1 9281 1 9283 2 2 9279 1 9283 3 9281 6 0 1 9283 4 2 8339 8 0 1 9283 5 9281 3 0 0 0 1 9283 6 2 9271 9265 9279 0 0 1 9293 1 9291 1 9293 2 2 9289 1 9293 3 9291 3 0 1 9293 4 2 7365 6 0 1 9293 5 9291 12 0 0 0 1 9293 6 2 749 6168 4056 1 0 1 9311 1 9304 1 9311 2 7 9309 1 9311 3 9304 1 0 1 9311 4 7 6729 4 0 1 9311 5 9304 4 0 0 0 1 9311 6 7 4113 1876 1736 1 0 1 9319 1 9316 1 9319 2 3 9317 1 9319 3 9316 4 0 1 9319 4 3 9315 4 0 1 9319 5 9316 1 0 0 0 1 9319 6 3 6313 8883 8118 0 0 1 9323 1 9321 1 9323 2 2 9322 1 9323 3 9321 2 0 1 9323 4 2 9316 8 0 1 9323 5 9321 11 0 0 0 1 9323 6 2 6343 5860 726 2 0 1 9337 1 9332 1 9337 2 5 9336 1 9337 3 9332 3 0 1 9337 4 5 7142 8 0 1 9337 5 9332 17 0 0 0 1 9337 6 5 5575 6468 244 2 0 1 9341 1 9339 1 9341 2 2 9340 1 9341 3 9339 3 0 1 9341 4 2 6817 3 0 1 9341 5 9339 4 0 0 0 1 9341 6 2 2514 6633 7176 2 0 1 9343 1 9338 1 9343 2 5 9342 1 9343 3 9338 2 0 1 9343 4 5 6592 10 0 1 9343 5 9338 7 0 0 0 1 9343 6 5 2315 2343 6295 3 0 1 9349 1 9347 1 9349 2 2 9341 1 9349 3 9347 2 0 1 9349 4 2 5840 0 0 1 9349 5 9347 3 0 0 0 1 9349 6 2 8492 2492 7008 0 0 1 9371 1 9369 1 9371 2 2 9370 1 9371 3 9369 4 0 1 9371 4 2 5834 13 0 1 9371 5 9369 2 0 0 0 1 9371 6 2 6635 7764 3855 1 0 1 9377 1 9374 1 9377 2 3 9368 1 9377 3 9374 10 0 1 9377 4 3 5819 3 0 1 9377 5 9374 12 0 0 0 1 9377 6 3 3121 5127 2868 1 0 1 9391 1 9388 1 9391 2 3 9390 1 9391 3 9388 6 0 1 9391 4 3 6807 6 0 1 9391 5 9388 7 0 0 0 1 9391 6 3 1863 2392 5521 0 0 1 9397 1 9395 1 9397 2 2 9396 1 9397 3 9395 6 0 1 9397 4 2 7969 6 0 1 9397 5 9395 9 0 0 0 1 9397 6 2 5616 6531 5832 0 0 1 9403 1 9400 1 9403 2 3 9396 1 9403 3 9400 1 0 1 9403 4 3 9129 11 0 1 9403 5 9400 5 0 0 0 1 9403 6 3 5255 7055 4230 1 0 1 9413 1 9410 1 9413 2 3 9412 1 9413 3 9410 4 0 1 9413 4 3 5447 4 0 1 9413 5 9410 5 0 0 0 1 9413 6 3 8993 8167 4942 4 0 1 9419 1 9417 1 9419 2 2 9413 1 9419 3 9417 9 0 1 9419 4 2 6628 0 0 1 9419 5 9417 3 0 0 0 1 9419 6 2 7744 1647 8231 1 0 1 9421 1 9419 1 9421 2 2 9420 1 9421 3 9419 6 0 1 9421 4 2 8855 7 0 1 9421 5 9419 2 0 0 0 1 9421 6 2 4585 2484 1701 0 0 1 9431 1 9424 1 9431 2 7 9430 1 9431 3 9424 3 0 1 9431 4 7 6132 2 0 1 9431 5 9424 5 0 0 0 1 9431 6 7 2701 1680 8388 1 0 1 9433 1 9428 1 9433 2 5 9430 1 9433 3 9428 9 0 1 9433 4 5 9422 14 0 1 9433 5 9428 5 0 0 0 1 9433 6 5 8892 1778 9190 0 0 1 9437 1 9435 1 9437 2 2 9428 1 9437 3 9435 4 0 1 9437 4 2 6215 1 0 1 9437 5 9435 4 0 0 0 1 9437 6 2 2779 7855 3741 1 0 1 9439 1 9417 1 9439 2 22 9438 1 9439 3 9417 2 0 1 9439 4 22 8780 2 0 1 9439 5 9417 3 0 0 0 1 9439 6 22 8565 5999 6390 0 0 1 9461 1 9458 1 9461 2 3 9459 1 9461 3 9458 12 0 1 9461 4 3 7151 14 0 1 9461 5 9458 6 0 0 0 1 9461 6 3 1197 6380 4176 1 0 1 9463 1 9460 1 9463 2 3 9461 1 9463 3 9460 4 0 1 9463 4 3 9459 4 0 1 9463 5 9460 1 0 0 0 1 9463 6 3 5543 5930 5856 0 0 1 9467 1 9465 1 9467 2 2 9466 1 9467 3 9465 2 0 1 9467 4 2 6384 4 0 1 9467 5 9465 2 0 0 0 1 9467 6 2 1881 6205 5578 1 0 1 9473 1 9470 1 9473 2 3 9467 1 9473 3 9470 1 0 1 9473 4 3 5129 1 0 1 9473 5 9470 19 0 0 0 1 9473 6 3 1935 6654 995 2 0 1 9479 1 9472 1 9479 2 7 9472 1 9479 3 9472 2 0 1 9479 4 7 6365 8 0 1 9479 5 9472 2 0 0 0 1 9479 6 7 7469 8721 3242 3 0 1 9491 1 9489 1 9491 2 2 9476 1 9491 3 9489 5 0 1 9491 4 2 5083 4 0 1 9491 5 9489 6 0 0 0 1 9491 6 2 270 5031 8755 3 0 1 9497 1 9494 1 9497 2 3 9491 1 9497 3 9494 3 0 1 9497 4 3 6593 11 0 1 9497 5 9494 6 0 0 0 1 9497 6 3 6345 5362 863 1 0 1 9511 1 9508 1 9511 2 3 9510 1 9511 3 9508 4 0 1 9511 4 3 9373 3 0 1 9511 5 9508 6 0 0 0 1 9511 6 3 6658 4480 7514 0 0 1 9521 1 9518 1 9521 2 3 9520 1 9521 3 9518 3 0 1 9521 4 3 5073 7 0 1 9521 5 9518 3 0 0 0 1 9521 6 3 4999 8694 307 2 0 1 9533 1 9531 1 9533 2 2 9529 1 9533 3 9531 2 0 1 9533 4 2 5479 1 0 1 9533 5 9531 2 0 0 0 1 9533 6 2 2635 4771 6184 5 0 1 9539 1 9537 1 9539 2 2 9538 1 9539 3 9537 11 0 1 9539 4 2 9532 8 0 1 9539 5 9537 2 0 0 0 1 9539 6 2 4451 8475 9120 1 0 1 9547 1 9545 1 9547 2 2 9546 1 9547 3 9545 2 0 1 9547 4 2 4903 10 0 1 9547 5 9545 6 0 0 0 1 9547 6 2 9537 5553 3164 0 0 1 9551 1 9540 1 9551 2 11 9550 1 9551 3 9540 7 0 1 9551 4 11 8763 4 0 1 9551 5 9540 8 0 0 0 1 9551 6 11 4846 6942 2120 1 0 1 9587 1 9585 1 9587 2 2 9583 1 9587 3 9585 3 0 1 9587 4 2 7602 8 0 1 9587 5 9585 15 0 0 0 1 9587 6 2 3461 1202 8007 4 0 1 9601 1 9588 1 9601 2 13 9598 1 9601 3 9588 5 0 1 9601 4 13 6113 42 0 1 9601 5 9588 15 0 0 0 1 9601 6 13 8072 4399 5411 0 0 1 9613 1 9611 1 9613 2 2 9606 1 9613 3 9611 5 0 1 9613 4 2 6141 5 0 1 9613 5 9611 6 0 0 0 1 9613 6 2 3952 1517 6558 0 0 1 9619 1 9617 1 9619 2 2 9615 1 9619 3 9617 2 0 1 9619 4 2 7026 8 0 1 9619 5 9617 3 0 0 0 1 9619 6 2 373 4736 8835 0 0 1 9623 1 9618 1 9623 2 5 9621 1 9623 3 9618 1 0 1 9623 4 5 7793 8 0 1 9623 5 9618 18 0 0 0 1 9623 6 5 3984 8996 5702 2 0 1 9629 1 9627 1 9629 2 2 9621 1 9629 3 9627 2 0 1 9629 4 2 6790 0 0 1 9629 5 9627 13 0 0 0 1 9629 6 2 4940 5754 6591 1 0 1 9631 1 9628 1 9631 2 3 9629 1 9631 3 9628 7 0 1 9631 4 3 5229 6 0 1 9631 5 9628 7 0 0 0 1 9631 6 3 5073 5882 7033 0 0 1 9643 1 9641 1 9643 2 2 9639 1 9643 3 9641 6 0 1 9643 4 2 5310 8 0 1 9643 5 9641 4 0 0 0 1 9643 6 2 9631 9625 9639 0 0 1 9649 1 9642 1 9649 2 7 9642 1 9649 3 9642 2 0 1 9649 4 7 5002 0 0 1 9649 5 9642 11 0 0 0 1 9649 6 7 7129 3802 1048 0 0 1 9661 1 9659 1 9661 2 2 9657 1 9661 3 9659 2 0 1 9661 4 2 9105 6 0 1 9661 5 9659 6 0 0 0 1 9661 6 2 8970 4756 665 0 0 1 9677 1 9675 1 9677 2 2 9673 1 9677 3 9675 3 0 1 9677 4 2 8915 1 0 1 9677 5 9675 21 0 0 0 1 9677 6 2 747 3816 3455 2 0 1 9679 1 9676 1 9679 2 3 9678 1 9679 3 9676 7 0 1 9679 4 3 7499 2 0 1 9679 5 9676 8 0 0 0 1 9679 6 3 90 9445 7366 0 0 1 9689 1 9686 1 9689 2 3 9683 1 9689 3 9686 6 0 1 9689 4 3 9677 0 0 1 9689 5 9686 4 0 0 0 1 9689 6 3 223 5702 6648 1 0 1 9697 1 9687 1 9697 2 10 9692 1 9697 3 9687 5 0 1 9697 4 10 6346 10 0 1 9697 5 9687 24 0 0 0 1 9697 6 10 3349 7898 2350 0 0 1 9719 1 9702 1 9719 2 17 9712 1 9719 3 9702 1 0 1 9719 4 17 5263 8 0 1 9719 5 9702 3 0 0 0 1 9719 6 17 7452 2386 9440 3 0 1 9721 1 9714 1 9721 2 7 9718 1 9721 3 9714 5 0 1 9721 4 7 9702 22 0 1 9721 5 9714 1 0 0 0 1 9721 6 7 113 1306 5624 0 0 1 9733 1 9731 1 9733 2 2 9732 1 9733 3 9731 2 0 1 9733 4 2 9726 8 0 1 9733 5 9731 2 0 0 0 1 9733 6 2 8889 7453 2254 0 0 1 9739 1 9736 1 9739 2 3 9732 1 9739 3 9736 8 0 1 9739 4 3 8326 5 0 1 9739 5 9736 1 0 0 0 1 9739 6 3 9508 7496 2435 0 0 1 9743 1 9738 1 9743 2 5 9740 1 9743 3 9738 8 0 1 9743 4 5 5224 6 0 1 9743 5 9738 2 0 0 0 1 9743 6 5 6883 8750 5105 1 0 1 9749 1 9747 1 9749 2 2 9748 1 9749 3 9747 5 0 1 9749 4 2 5546 4 0 1 9749 5 9747 6 0 0 0 1 9749 6 2 7694 5721 3734 2 0 1 9767 1 9762 1 9767 2 5 9765 1 9767 3 9762 2 0 1 9767 4 5 9763 3 0 1 9767 5 9762 3 0 0 0 1 9767 6 5 2381 5959 3257 3 0 1 9769 1 9756 1 9769 2 13 9768 1 9769 3 9756 9 0 1 9769 4 13 6230 14 0 1 9769 5 9756 1 0 0 0 1 9769 6 13 6921 632 8704 0 0 1 9781 1 9775 1 9781 2 6 9777 1 9781 3 9775 4 0 1 9781 4 6 5001 2 0 1 9781 5 9775 6 0 0 0 1 9781 6 6 9149 9684 2229 0 0 1 9787 1 9784 1 9787 2 3 9786 1 9787 3 9784 4 0 1 9787 4 3 6629 2 0 1 9787 5 9784 4 0 0 0 1 9787 6 3 5127 4555 9505 0 0 1 9791 1 9780 1 9791 2 11 9790 1 9791 3 9780 1 0 1 9791 4 11 6086 2 0 1 9791 5 9780 2 0 0 0 1 9791 6 11 2437 3419 6324 2 0 1 9803 1 9801 1 9803 2 2 9802 1 9803 3 9801 2 0 1 9803 4 2 7808 2 0 1 9803 5 9801 3 0 0 0 1 9803 6 2 1791 6435 2148 1 0 1 9811 1 9808 1 9811 2 3 9810 1 9811 3 9808 1 0 1 9811 4 3 6930 6 0 1 9811 5 9808 13 0 0 0 1 9811 6 3 7526 2384 5050 0 0 1 9817 1 9812 1 9817 2 5 9816 1 9817 3 9812 1 0 1 9817 4 5 5210 6 0 1 9817 5 9812 1 0 0 0 1 9817 6 5 1895 215 6969 0 0 1 9829 1 9819 1 9829 2 10 9825 1 9829 3 9819 11 0 1 9829 4 10 5988 2 0 1 9829 5 9819 3 0 0 0 1 9829 6 10 2581 8245 8531 0 0 1 9833 1 9830 1 9833 2 3 9824 1 9833 3 9830 6 0 1 9833 4 3 6035 12 0 1 9833 5 9830 5 0 0 0 1 9833 6 3 3223 2059 6117 1 0 1 9839 1 9832 1 9839 2 7 9838 1 9839 3 9832 1 0 1 9839 4 7 5413 2 0 1 9839 5 9832 1 0 0 0 1 9839 6 7 8207 1934 3887 1 0 1 9851 1 9849 1 9851 2 2 9845 1 9851 3 9849 2 0 1 9851 4 2 5951 4 0 1 9851 5 9849 7 0 0 0 1 9851 6 2 6021 1251 5705 2 0 1 9857 1 9852 1 9857 2 5 9856 1 9857 3 9852 5 0 1 9857 4 5 9114 4 0 1 9857 5 9852 10 0 0 0 1 9857 6 5 4495 7184 7053 2 0 1 9859 1 9857 1 9859 2 2 9855 1 9859 3 9857 4 0 1 9859 4 2 9231 1 0 1 9859 5 9857 3 0 0 0 1 9859 6 2 2796 4250 5028 0 0 1 9871 1 9868 1 9871 2 3 9869 1 9871 3 9868 3 0 1 9871 4 3 6493 3 0 1 9871 5 9868 3 0 0 0 1 9871 6 3 7230 2345 4177 1 0 1 9883 1 9881 1 9883 2 2 9882 1 9883 3 9881 2 0 1 9883 4 2 5028 11 0 1 9883 5 9881 12 0 0 0 1 9883 6 2 8787 9638 9399 0 0 1 9887 1 9882 1 9887 2 5 9882 1 9887 3 9882 1 0 1 9887 4 5 7319 6 0 1 9887 5 9882 3 0 0 0 1 9887 6 5 8678 2032 6861 1 0 1 9901 1 9899 1 9901 2 2 9900 1 9901 3 9899 4 0 1 9901 4 2 9894 8 0 1 9901 5 9899 2 0 0 0 1 9901 6 2 1748 4483 8692 1 0 1 9907 1 9905 1 9907 2 2 9903 1 9907 3 9905 4 0 1 9907 4 2 6151 8 0 1 9907 5 9905 9 0 0 0 1 9907 6 2 5230 3284 7577 0 0 1 9923 1 9921 1 9923 2 2 9918 1 9923 3 9921 4 0 1 9923 4 2 9317 0 0 1 9923 5 9921 6 0 0 0 1 9923 6 2 2269 2624 6629 1 0 1 9929 1 9926 1 9929 2 3 9928 1 9929 3 9926 1 0 1 9929 4 3 8041 4 0 1 9929 5 9926 3 0 0 0 1 9929 6 3 2171 5942 8347 1 0 1 9931 1 9921 1 9931 2 10 9928 1 9931 3 9921 4 0 1 9931 4 10 9545 4 0 1 9931 5 9921 2 0 0 0 1 9931 6 10 2316 8350 5581 2 0 1 9941 1 9939 1 9941 2 2 9937 1 9941 3 9939 3 0 1 9941 4 2 8321 7 0 1 9941 5 9939 2 0 0 0 1 9941 6 2 1291 7931 1408 2 0 1 9949 1 9947 1 9949 2 2 9945 1 9949 3 9947 4 0 1 9949 4 2 9170 10 0 1 9949 5 9947 5 0 0 0 1 9949 6 2 1443 1156 6970 0 0 1 9967 1 9964 1 9967 2 3 9965 1 9967 3 9964 3 0 1 9967 4 3 9963 4 0 1 9967 5 9964 4 0 0 0 1 9967 6 3 6881 7254 9681 0 0 1 9973 1 9962 1 9973 2 11 9969 1 9973 3 9962 1 0 1 9973 4 11 7687 2 0 1 9973 5 9962 8 0 0 0 1 9973 6 11 3928 2985 9944 0 0 1 10007 1 10002 1 10007 2 5 10005 1 10007 3 10002 3 0 1 10007 4 5 9995 11 0 1 10007 5 10002 3 0 0 0 1 10007 6 5 7978 7220 7070 1 0 1 10009 1 9998 1 10009 2 11 10005 1 10009 3 9998 1 0 1 10009 4 11 9995 11 0 1 10009 5 9998 1 0 0 0 1 10009 6 11 8706 3520 9952 1 0 1 10037 1 10035 1 10037 2 2 10033 1 10037 3 10035 2 0 1 10037 4 2 7099 1 0 1 10037 5 10035 3 0 0 0 1 10037 6 2 102 8872 6761 1 0 1 10039 1 10036 1 10039 2 3 10038 1 10039 3 10036 1 0 1 10039 4 3 6587 2 0 1 10039 5 10036 3 0 0 0 1 10039 6 3 4408 9268 8821 3 0 1 10061 1 10058 1 10061 2 3 10059 1 10061 3 10058 4 0 1 10061 4 3 10057 4 0 1 10061 5 10058 9 0 0 0 1 10061 6 3 8516 7568 6258 2 0 1 10067 1 10065 1 10067 2 2 10063 1 10067 3 10065 3 0 1 10067 4 2 7032 14 0 1 10067 5 10065 3 0 0 0 1 10067 6 2 9132 2222 7159 1 0 1 10069 1 10067 1 10069 2 2 10065 1 10069 3 10067 4 0 1 10069 4 2 8451 6 0 1 10069 5 10067 4 0 0 0 1 10069 6 2 2432 8214 5305 0 0 1 10079 1 10068 1 10079 2 11 10076 1 10079 3 10068 2 0 1 10079 4 11 5337 12 0 1 10079 5 10068 3 0 0 0 1 10079 6 11 9540 4152 9065 5 0 1 10091 1 10089 1 10091 2 2 10087 1 10091 3 10089 3 0 1 10091 4 2 6538 8 0 1 10091 5 10089 8 0 0 0 1 10091 6 2 7118 9253 3773 1 0 1 10093 1 10091 1 10093 2 2 10092 1 10093 3 10091 2 0 1 10093 4 2 5918 3 0 1 10093 5 10091 2 0 0 0 1 10093 6 2 6200 562 4293 0 0 1 10099 1 10097 1 10099 2 2 10095 1 10099 3 10097 6 0 1 10099 4 2 9440 1 0 1 10099 5 10097 5 0 0 0 1 10099 6 2 355 883 6474 0 0 1 10103 1 10098 1 10103 2 5 10102 1 10103 3 10098 8 0 1 10103 4 5 6950 4 0 1 10103 5 10098 1 0 0 0 1 10103 6 5 8645 8394 7728 1 0 1 10111 1 10099 1 10111 2 12 10109 1 10111 3 10099 5 0 1 10111 4 12 8381 3 0 1 10111 5 10099 4 0 0 0 1 10111 6 12 91 4329 5293 1 0 1 10133 1 10131 1 10133 2 2 10129 1 10133 3 10131 3 0 1 10133 4 2 5713 7 0 1 10133 5 10131 2 0 0 0 1 10133 6 2 9574 3849 8838 1 0 1 10139 1 10137 1 10139 2 2 10138 1 10139 3 10137 5 0 1 10139 4 2 10132 8 0 1 10139 5 10137 4 0 0 0 1 10139 6 2 1353 1688 2822 1 0 1 10141 1 10139 1 10141 2 2 10140 1 10141 3 10139 5 0 1 10141 4 2 8225 3 0 1 10141 5 10139 5 0 0 0 1 10141 6 2 4279 4575 8246 0 0 1 10151 1 10144 1 10151 2 7 10149 1 10151 3 10144 1 0 1 10151 4 7 7169 4 0 1 10151 5 10144 17 0 0 0 1 10151 6 7 502 5985 7872 1 0 1 10159 1 10156 1 10159 2 3 10157 1 10159 3 10156 1 0 1 10159 4 3 9468 3 0 1 10159 5 10156 4 0 0 0 1 10159 6 3 9446 9225 438 0 0 1 10163 1 10161 1 10163 2 2 10159 1 10163 3 10161 2 0 1 10163 4 2 8097 17 0 1 10163 5 10161 5 0 0 0 1 10163 6 2 2747 2058 9888 1 0 1 10169 1 10166 1 10169 2 3 10163 1 10169 3 10166 1 0 1 10169 4 3 10157 0 0 1 10169 5 10166 9 0 0 0 1 10169 6 3 9807 1773 6295 5 0 1 10177 1 10170 1 10177 2 7 10174 1 10177 3 10170 1 0 1 10177 4 7 10034 8 0 1 10177 5 10170 9 0 0 0 1 10177 6 7 8952 8195 10064 0 0 1 10181 1 10179 1 10181 2 2 10180 1 10181 3 10179 9 0 1 10181 4 2 6033 3 0 1 10181 5 10179 7 0 0 0 1 10181 6 2 3594 8153 7912 1 0 1 10193 1 10190 1 10193 2 3 10192 1 10193 3 10190 7 0 1 10193 4 3 8097 4 0 1 10193 5 10190 1 0 0 0 1 10193 6 3 3862 8561 9167 1 0 1 10211 1 10205 1 10211 2 6 10210 1 10211 3 10205 1 0 1 10211 4 6 8236 2 0 1 10211 5 10205 7 0 0 0 1 10211 6 6 7499 8739 8209 1 0 1 10223 1 10218 1 10223 2 5 10221 1 10223 3 10218 1 0 1 10223 4 5 9079 14 0 1 10223 5 10218 12 0 0 0 1 10223 6 5 7202 5227 9800 1 0 1 10243 1 10236 1 10243 2 7 10241 1 10243 3 10236 2 0 1 10243 4 7 9513 13 0 1 10243 5 10236 7 0 0 0 1 10243 6 7 5937 6838 8205 0 0 1 10247 1 10242 1 10247 2 5 10244 1 10247 3 10242 5 0 1 10247 4 5 5485 6 0 1 10247 5 10242 2 0 0 0 1 10247 6 5 5326 8735 6340 1 0 1 10253 1 10251 1 10253 2 2 10252 1 10253 3 10251 8 0 1 10253 4 2 8614 6 0 1 10253 5 10251 11 0 0 0 1 10253 6 2 2012 2852 5703 1 0 1 10259 1 10257 1 10259 2 2 10249 1 10259 3 10257 5 0 1 10259 4 2 8416 0 0 1 10259 5 10257 5 0 0 0 1 10259 6 2 1727 5263 7235 1 0 1 10267 1 10265 1 10267 2 2 10263 1 10267 3 10265 2 0 1 10267 4 2 8737 1 0 1 10267 5 10265 17 0 0 0 1 10267 6 2 3657 3099 4244 0 0 1 10271 1 10264 1 10271 2 7 10270 1 10271 3 10264 1 0 1 10271 4 7 6272 3 0 1 10271 5 10264 1 0 0 0 1 10271 6 7 9500 1943 3784 1 0 1 10273 1 10263 1 10273 2 10 10268 1 10273 3 10263 5 0 1 10273 4 10 9542 16 0 1 10273 5 10263 4 0 0 0 1 10273 6 10 2243 6345 3002 1 0 1 10289 1 10286 1 10289 2 3 10283 1 10289 3 10286 1 0 1 10289 4 3 10277 0 0 1 10289 5 10286 4 0 0 0 1 10289 6 3 8887 8083 9311 1 0 1 10301 1 10299 1 10301 2 2 10293 1 10301 3 10299 2 0 1 10301 4 2 9322 0 0 1 10301 5 10299 7 0 0 0 1 10301 6 2 1126 316 2802 2 0 1 10303 1 10300 1 10303 2 3 10302 1 10303 3 10300 4 0 1 10303 4 3 9982 2 0 1 10303 5 10300 6 0 0 0 1 10303 6 3 119 6862 2036 9 0 1 10313 1 10310 1 10313 2 3 10312 1 10313 3 10310 5 0 1 10313 4 3 5430 4 0 1 10313 5 10310 12 0 0 0 1 10313 6 3 3920 3425 5885 1 0 1 10321 1 10314 1 10321 2 7 10314 1 10321 3 10314 8 0 1 10321 4 7 5844 0 0 1 10321 5 10314 9 0 0 0 1 10321 6 7 8505 8845 7362 0 0 1 10331 1 10329 1 10331 2 2 10330 1 10331 3 10329 3 0 1 10331 4 2 8493 2 0 1 10331 5 10329 2 0 0 0 1 10331 6 2 3409 9355 5321 1 0 1 10333 1 10328 1 10333 2 5 10328 1 10333 3 10328 3 0 1 10333 4 5 6295 11 0 1 10333 5 10328 7 0 0 0 1 10333 6 5 5943 6139 5383 0 0 1 10337 1 10334 1 10337 2 3 10336 1 10337 3 10334 3 0 1 10337 4 3 9346 7 0 1 10337 5 10334 10 0 0 0 1 10337 6 3 9593 5351 1518 1 0 1 10343 1 10338 1 10343 2 5 10341 1 10343 3 10338 5 0 1 10343 4 5 10339 3 0 1 10343 5 10338 5 0 0 0 1 10343 6 5 4855 709 8804 2 0 1 10357 1 10355 1 10357 2 2 10353 1 10357 3 10355 4 0 1 10357 4 2 9464 9 0 1 10357 5 10355 29 0 0 0 1 10357 6 2 7218 4223 6369 1 0 1 10369 1 10356 1 10369 2 13 10358 1 10369 3 10356 4 0 1 10369 4 13 5914 0 0 1 10369 5 10356 14 0 0 0 1 10369 6 13 9237 7072 9774 5 0 1 10391 1 10372 1 10391 2 19 10389 1 10391 3 10372 1 0 1 10391 4 19 8160 3 0 1 10391 5 10372 6 0 0 0 1 10391 6 19 8612 5888 4117 2 0 1 10399 1 10393 1 10399 2 6 10397 1 10399 3 10393 1 0 1 10399 4 6 10004 4 0 1 10399 5 10393 4 0 0 0 1 10399 6 6 3057 5189 6359 1 0 1 10427 1 10425 1 10427 2 2 10423 1 10427 3 10425 3 0 1 10427 4 2 6390 8 0 1 10427 5 10425 4 0 0 0 1 10427 6 2 2327 2364 2585 3 0 1 10429 1 10422 1 10429 2 7 10423 1 10429 3 10422 8 0 1 10429 4 7 6339 8 0 1 10429 5 10422 5 0 0 0 1 10429 6 7 702 1521 2882 0 0 1 10433 1 10430 1 10433 2 3 10428 1 10433 3 10430 1 0 1 10433 4 3 9291 2 0 1 10433 5 10430 11 0 0 0 1 10433 6 3 5541 9400 2175 1 0 1 10453 1 10448 1 10453 2 5 10452 1 10453 3 10448 3 0 1 10453 4 5 8607 3 0 1 10453 5 10448 11 0 0 0 1 10453 6 5 9188 8836 20 2 0 1 10457 1 10454 1 10457 2 3 10456 1 10457 3 10454 3 0 1 10457 4 3 5413 6 0 1 10457 5 10454 4 0 0 0 1 10457 6 3 3710 9475 2194 2 0 1 10459 1 10457 1 10459 2 2 10455 1 10459 3 10457 2 0 1 10459 4 2 5399 8 0 1 10459 5 10457 5 0 0 0 1 10459 6 2 5965 1050 1150 0 0 1 10463 1 10458 1 10463 2 5 10461 1 10463 3 10458 2 0 1 10463 4 5 7139 5 0 1 10463 5 10458 9 0 0 0 1 10463 6 5 2150 9054 10455 1 0 1 10477 1 10475 1 10477 2 2 10476 1 10477 3 10475 2 0 1 10477 4 2 9846 6 0 1 10477 5 10475 5 0 0 0 1 10477 6 2 5188 9854 6644 0 0 1 10487 1 10482 1 10487 2 5 10486 1 10487 3 10482 1 0 1 10487 4 5 5442 5 0 1 10487 5 10482 5 0 0 0 1 10487 6 5 10225 1681 7999 1 0 1 10499 1 10497 1 10499 2 2 10495 1 10499 3 10497 3 0 1 10499 4 2 7152 7 0 1 10499 5 10497 12 0 0 0 1 10499 6 2 6824 8169 10136 1 0 1 10501 1 10499 1 10501 2 2 10497 1 10501 3 10499 2 0 1 10501 4 2 5365 6 0 1 10501 5 10499 11 0 0 0 1 10501 6 2 806 246 10118 0 0 1 10513 1 10506 1 10513 2 7 10506 1 10513 3 10506 1 0 1 10513 4 7 8031 21 0 1 10513 5 10506 3 0 0 0 1 10513 6 7 4862 7613 5528 0 0 1 10529 1 10526 1 10529 2 3 10520 1 10529 3 10526 5 0 1 10529 4 3 9453 15 0 1 10529 5 10526 5 0 0 0 1 10529 6 3 9960 3590 9477 3 0 1 10531 1 10528 1 10531 2 3 10524 1 10531 3 10528 3 0 1 10531 4 3 9291 5 0 1 10531 5 10528 13 0 0 0 1 10531 6 3 4037 4785 8414 1 0 1 10559 1 10536 1 10559 2 23 10558 1 10559 3 10536 10 0 1 10559 4 23 10135 4 0 1 10559 5 10536 2 0 0 0 1 10559 6 23 4513 1327 8562 1 0 1 10567 1 10561 1 10567 2 6 10566 1 10567 3 10561 2 0 1 10567 4 6 8731 2 0 1 10567 5 10561 6 0 0 0 1 10567 6 6 2127 2150 5867 0 0 1 10589 1 10587 1 10589 2 2 10588 1 10589 3 10587 3 0 1 10589 4 2 5746 3 0 1 10589 5 10587 18 0 0 0 1 10589 6 2 6284 3375 5122 1 0 1 10597 1 10592 1 10597 2 5 10596 1 10597 3 10592 11 0 1 10597 4 5 8893 3 0 1 10597 5 10592 2 0 0 0 1 10597 6 5 8342 5064 9389 0 0 1 10601 1 10598 1 10601 2 3 10596 1 10601 3 10598 7 0 1 10601 4 3 5797 2 0 1 10601 5 10598 3 0 0 0 1 10601 6 3 1548 5573 8384 8 0 1 10607 1 10602 1 10607 2 5 10599 1 10607 3 10602 5 0 1 10607 4 5 10428 3 0 1 10607 5 10602 3 0 0 0 1 10607 6 5 3761 10137 9577 1 0 1 10613 1 10611 1 10613 2 2 10608 1 10613 3 10611 8 0 1 10613 4 2 7629 8 0 1 10613 5 10611 6 0 0 0 1 10613 6 2 5300 6621 6918 2 0 1 10627 1 10622 1 10627 2 5 10625 1 10627 3 10622 1 0 1 10627 4 5 10619 6 0 1 10627 5 10622 2 0 0 0 1 10627 6 5 2103 2607 6675 0 0 1 10631 1 10620 1 10631 2 11 10629 1 10631 3 10620 1 0 1 10631 4 11 7438 5 0 1 10631 5 10620 1 0 0 0 1 10631 6 11 2265 3246 2360 2 0 1 10639 1 10633 1 10639 2 6 10635 1 10639 3 10633 3 0 1 10639 4 6 6229 5 0 1 10639 5 10633 3 0 0 0 1 10639 6 6 7741 10588 5732 2 0 1 10651 1 10644 1 10651 2 7 10649 1 10651 3 10644 2 0 1 10651 4 7 8034 6 0 1 10651 5 10644 8 0 0 0 1 10651 6 7 8343 5328 6888 0 0 1 10657 1 10650 1 10657 2 7 10650 1 10657 3 10650 3 0 1 10657 4 7 8173 14 0 1 10657 5 10650 3 0 0 0 1 10657 6 7 6442 4670 9286 0 0 1 10663 1 10660 1 10663 2 3 10657 1 10663 3 10660 1 0 1 10663 4 3 10651 0 0 1 10663 5 10660 3 0 0 0 1 10663 6 3 2853 8493 7534 0 0 1 10667 1 10665 1 10667 2 2 10666 1 10667 3 10665 3 0 1 10667 4 2 9077 4 0 1 10667 5 10665 16 0 0 0 1 10667 6 2 9831 1922 2875 1 0 1 10687 1 10682 1 10687 2 5 10685 1 10687 3 10682 7 0 1 10687 4 5 10683 3 0 1 10687 5 10682 5 0 0 0 1 10687 6 5 8608 2242 1554 4 0 1 10691 1 10689 1 10691 2 2 10685 1 10691 3 10689 12 0 1 10691 4 2 8483 0 0 1 10691 5 10689 21 0 0 0 1 10691 6 2 4913 8402 879 2 0 1 10709 1 10707 1 10709 2 2 10708 1 10709 3 10707 5 0 1 10709 4 2 6531 3 0 1 10709 5 10707 4 0 0 0 1 10709 6 2 2824 7462 9497 2 0 1 10711 1 10708 1 10711 2 3 10710 1 10711 3 10708 9 0 1 10711 4 3 7232 2 0 1 10711 5 10708 1 0 0 0 1 10711 6 3 9464 216 6034 0 0 1 10723 1 10721 1 10723 2 2 10722 1 10723 3 10721 2 0 1 10723 4 2 10716 8 0 1 10723 5 10721 6 0 0 0 1 10723 6 2 8107 9992 10099 0 0 1 10729 1 10722 1 10729 2 7 10722 1 10729 3 10722 7 0 1 10729 4 7 8196 0 0 1 10729 5 10722 5 0 0 0 1 10729 6 7 9079 3233 3512 1 0 1 10733 1 10731 1 10733 2 2 10729 1 10733 3 10731 3 0 1 10733 4 2 5821 9 0 1 10733 5 10731 2 0 0 0 1 10733 6 2 9859 3470 7843 2 0 1 10739 1 10733 1 10739 2 6 10738 1 10739 3 10733 2 0 1 10739 4 6 6930 5 0 1 10739 5 10733 4 0 0 0 1 10739 6 6 10428 8594 10506 1 0 1 10753 1 10742 1 10753 2 11 10752 1 10753 3 10742 2 0 1 10753 4 11 9268 21 0 1 10753 5 10742 1 0 0 0 1 10753 6 11 8853 456 6717 0 0 1 10771 1 10768 1 10771 2 3 10770 1 10771 3 10768 4 0 1 10771 4 3 10157 2 0 1 10771 5 10768 4 0 0 0 1 10771 6 3 4964 4159 3365 0 0 1 10781 1 10771 1 10781 2 10 10780 1 10781 3 10771 4 0 1 10781 4 10 7606 11 0 1 10781 5 10771 11 0 0 0 1 10781 6 10 8080 7494 10445 2 0 1 10789 1 10787 1 10789 2 2 10782 1 10789 3 10787 2 0 1 10789 4 2 7877 17 0 1 10789 5 10787 12 0 0 0 1 10789 6 2 8124 4627 10087 0 0 1 10799 1 10780 1 10799 2 19 10797 1 10799 3 10780 2 0 1 10799 4 19 9456 5 0 1 10799 5 10780 2 0 0 0 1 10799 6 19 8481 4614 8994 10 0 1 10831 1 10824 1 10831 2 7 10822 1 10831 3 10824 5 0 1 10831 4 7 10215 2 0 1 10831 5 10824 10 0 0 0 1 10831 6 7 6435 9453 10520 0 0 1 10837 1 10835 1 10837 2 2 10833 1 10837 3 10835 6 0 1 10837 4 2 10360 10 0 1 10837 5 10835 7 0 0 0 1 10837 6 2 10825 10819 10833 0 0 1 10847 1 10842 1 10847 2 5 10845 1 10847 3 10842 5 0 1 10847 4 5 6619 10 0 1 10847 5 10842 7 0 0 0 1 10847 6 5 5616 1870 8460 2 0 1 10853 1 10851 1 10853 2 2 10852 1 10853 3 10851 2 0 1 10853 4 2 10846 8 0 1 10853 5 10851 3 0 0 0 1 10853 6 2 4861 2671 8870 1 0 1 10859 1 10857 1 10859 2 2 10853 1 10859 3 10857 2 0 1 10859 4 2 6366 0 0 1 10859 5 10857 5 0 0 0 1 10859 6 2 1506 6878 10660 1 0 1 10861 1 10859 1 10861 2 2 10857 1 10861 3 10859 2 0 1 10861 4 2 10395 12 0 1 10861 5 10859 9 0 0 0 1 10861 6 2 7967 1894 9957 0 0 1 10867 1 10865 1 10867 2 2 10866 1 10867 3 10865 2 0 1 10867 4 2 10860 8 0 1 10867 5 10865 6 0 0 0 1 10867 6 2 7094 7525 5213 0 0 1 10883 1 10881 1 10883 2 2 10882 1 10883 3 10881 3 0 1 10883 4 2 8117 2 0 1 10883 5 10881 2 0 0 0 1 10883 6 2 6775 5586 8864 2 0 1 10889 1 10886 1 10889 2 3 10884 1 10889 3 10886 1 0 1 10889 4 3 6640 2 0 1 10889 5 10886 7 0 0 0 1 10889 6 3 7550 68 2058 2 0 1 10891 1 10889 1 10891 2 2 10890 1 10891 3 10889 6 0 1 10891 4 2 6688 2 0 1 10891 5 10889 16 0 0 0 1 10891 6 2 6672 8404 2556 0 0 1 10903 1 10900 1 10903 2 3 10902 1 10903 3 10900 1 0 1 10903 4 3 7497 5 0 1 10903 5 10900 5 0 0 0 1 10903 6 3 3939 7090 1946 0 0 1 10909 1 10907 1 10909 2 2 10908 1 10909 3 10907 6 0 1 10909 4 2 9660 3 0 1 10909 5 10907 27 0 0 0 1 10909 6 2 4559 6806 6471 0 0 1 10937 1 10934 1 10937 2 3 10931 1 10937 3 10934 4 0 1 10937 4 3 10641 1 0 1 10937 5 10934 11 0 0 0 1 10937 6 3 9042 5447 8395 1 0 1 10939 1 10936 1 10939 2 3 10934 1 10939 3 10936 1 0 1 10939 4 3 10791 3 0 1 10939 5 10936 8 0 0 0 1 10939 6 3 6782 6456 6392 0 0 1 10949 1 10947 1 10949 2 2 10945 1 10949 3 10947 3 0 1 10949 4 2 9086 12 0 1 10949 5 10947 2 0 0 0 1 10949 6 2 4707 4207 10455 1 0 1 10957 1 10952 1 10957 2 5 10956 1 10957 3 10952 1 0 1 10957 4 5 6612 7 0 1 10957 5 10952 1 0 0 0 1 10957 6 5 2344 954 10070 3 0 1 10973 1 10971 1 10973 2 2 10969 1 10973 3 10971 3 0 1 10973 4 2 7937 7 0 1 10973 5 10971 4 0 0 0 1 10973 6 2 1660 7027 5553 1 0 1 10979 1 10977 1 10979 2 2 10974 1 10979 3 10977 4 0 1 10979 4 2 10209 3 0 1 10979 5 10977 8 0 0 0 1 10979 6 2 1555 2504 2716 1 0 1 10987 1 10985 1 10987 2 2 10983 1 10987 3 10985 6 0 1 10987 4 2 8862 8 0 1 10987 5 10985 5 0 0 0 1 10987 6 2 10975 10969 10983 0 0 1 10993 1 10986 1 10993 2 7 10986 1 10993 3 10986 10 0 1 10993 4 7 9709 21 0 1 10993 5 10986 1 0 0 0 1 10993 6 7 4015 6869 8311 0 0 1 11003 1 11001 1 11003 2 2 11002 1 11003 3 11001 4 0 1 11003 4 2 10996 8 0 1 11027 1 11025 1 11027 2 2 11023 1 11027 3 11025 3 0 1 11027 4 2 10607 8 0 1 11047 1 11044 1 11047 2 3 11045 1 11047 3 11044 4 0 1 11047 4 3 9701 3 0 1 11057 1 11054 1 11057 2 3 11056 1 11057 3 11054 1 0 1 11057 4 3 10481 7 0 1 11059 1 11049 1 11059 2 10 11049 1 11059 3 11049 8 0 1 11059 4 10 5760 0 0 1 11069 1 11067 1 11069 2 2 11061 1 11069 3 11067 12 0 1 11069 4 2 6982 0 0 1 11071 1 11068 1 11071 2 3 11069 1 11071 3 11068 6 0 1 11071 4 3 7980 3 0 1 11083 1 11081 1 11083 2 2 11079 1 11083 3 11081 6 0 1 11083 4 2 10536 8 0 1 11087 1 11082 1 11087 2 5 11086 1 11087 3 11082 5 0 1 11087 4 5 10473 3 0 1 11093 1 11091 1 11093 2 2 11092 1 11093 3 11091 2 0 1 11093 4 2 7869 6 0 1 11113 1 11100 1 11113 2 13 11112 1 11113 3 11100 4 0 1 11113 4 13 7710 14 0 1 11117 1 11114 1 11117 2 3 11116 1 11117 3 11114 1 0 1 11117 4 3 7991 4 0 1 11119 1 11116 1 11119 2 3 11117 1 11119 3 11116 1 0 1 11119 4 3 10561 6 0 1 11131 1 11129 1 11131 2 2 11127 1 11131 3 11129 4 0 1 11131 4 2 9391 8 0 1 11149 1 11139 1 11149 2 10 11148 1 11149 3 11139 2 0 1 11149 4 10 5896 7 0 1 11159 1 11152 1 11159 2 7 11157 1 11159 3 11152 11 0 1 11159 4 7 10793 4 0 1 11161 1 11154 1 11161 2 7 11158 1 11161 3 11154 1 0 1 11161 4 7 9994 16 0 1 11171 1 11169 1 11171 2 2 11170 1 11171 3 11169 3 0 1 11171 4 2 7302 4 0 1 11173 1 11168 1 11173 2 5 11170 1 11173 3 11168 1 0 1 11173 4 5 9051 18 0 1 11177 1 11174 1 11177 2 3 11171 1 11177 3 11174 4 0 1 11177 4 3 6647 9 0 1 11197 1 11195 1 11197 2 2 11193 1 11197 3 11195 6 0 1 11197 4 2 6642 6 0 1 11213 1 11211 1 11213 2 2 11209 1 11213 3 11211 2 0 1 11213 4 2 9249 1 0 1 11239 1 11236 1 11239 2 3 11238 1 11239 3 11236 1 0 1 11239 4 3 6673 2 0 1 11243 1 11238 1 11243 2 5 11238 1 11243 3 11238 7 0 1 11243 4 5 5897 3 0 1 11251 1 11238 1 11251 2 13 11250 1 11251 3 11238 2 0 1 11251 4 13 5766 2 0 1 11257 1 11247 1 11257 2 10 11252 1 11257 3 11247 4 0 1 11257 4 10 9783 10 0 1 11261 1 11259 1 11261 2 2 11260 1 11261 3 11259 3 0 1 11261 4 2 10474 3 0 1 11273 1 11270 1 11273 2 3 11268 1 11273 3 11270 3 0 1 11273 4 3 9079 0 0 1 11279 1 11272 1 11279 2 7 11278 1 11279 3 11272 7 0 1 11279 4 7 7469 2 0 1 11287 1 11284 1 11287 2 3 11285 1 11287 3 11284 1 0 1 11287 4 3 6223 6 0 1 11299 1 11296 1 11299 2 3 11298 1 11299 3 11296 1 0 1 11299 4 3 6832 6 0 1 11311 1 11308 1 11311 2 3 11309 1 11311 3 11308 1 0 1 11311 4 3 11307 4 0 1 11317 1 11315 1 11317 2 2 11316 1 11317 3 11315 2 0 1 11317 4 2 11310 8 0 1 11321 1 11318 1 11321 2 3 11320 1 11321 3 11318 5 0 1 11321 4 3 5880 7 0 1 11329 1 11322 1 11329 2 7 11317 1 11329 3 11322 3 0 1 11329 4 7 8324 5 0 1 11351 1 11344 1 11351 2 7 11350 1 11351 3 11344 11 0 1 11351 4 7 8130 2 0 1 11353 1 11346 1 11353 2 7 11350 1 11353 3 11346 3 0 1 11353 4 7 11202 8 0 1 11369 1 11366 1 11369 2 3 11354 1 11369 3 11366 3 0 1 11369 4 3 10844 2 0 1 11383 1 11378 1 11383 2 5 11382 1 11383 3 11378 2 0 1 11383 4 5 9168 9 0 1 11393 1 11390 1 11393 2 3 11392 1 11393 3 11390 3 0 1 11393 4 3 7035 4 0 1 11399 1 11388 1 11399 2 11 11397 1 11399 3 11388 1 0 1 11399 4 11 9253 5 0 1 11411 1 11404 1 11411 2 7 11405 1 11411 3 11404 4 0 1 11411 4 7 11226 7 0 1 11423 1 11418 1 11423 2 5 11421 1 11423 3 11418 2 0 1 11423 4 5 11419 3 0 1 11437 1 11435 1 11437 2 2 11436 1 11437 3 11435 2 0 1 11437 4 2 7118 3 0 1 11443 1 11441 1 11443 2 2 11442 1 11443 3 11441 2 0 1 11443 4 2 8699 7 0 1 11447 1 11442 1 11447 2 5 11445 1 11447 3 11442 1 0 1 11447 4 5 7158 14 0 1 11467 1 11462 1 11467 2 5 11466 1 11467 3 11462 2 0 1 11467 4 5 9143 2 0 1 11471 1 11460 1 11471 2 11 11470 1 11471 3 11460 1 0 1 11471 4 11 6789 2 0 1 11483 1 11481 1 11483 2 2 11476 1 11483 3 11481 2 0 1 11483 4 2 7121 14 0 1 11489 1 11486 1 11489 2 3 11483 1 11489 3 11486 5 0 1 11489 4 3 11477 0 0 1 11491 1 11488 1 11491 2 3 11481 1 11491 3 11488 3 0 1 11491 4 3 8779 2 0 1 11497 1 11490 1 11497 2 7 11494 1 11497 3 11490 7 0 1 11497 4 7 9646 8 0 1 11503 1 11500 1 11503 2 3 11502 1 11503 3 11500 4 0 1 11503 4 3 7225 2 0 1 11519 1 11512 1 11519 2 7 11518 1 11519 3 11512 3 0 1 11519 4 7 7599 3 0 1 11527 1 11522 1 11527 2 5 11526 1 11527 3 11522 5 0 1 11527 4 5 8088 2 0 1 11549 1 11547 1 11549 2 2 11544 1 11549 3 11547 3 0 1 11549 4 2 11363 8 0 1 11551 1 11544 1 11551 2 7 11542 1 11551 3 11544 4 0 1 11551 4 7 6094 2 0 1 11579 1 11577 1 11579 2 2 11566 1 11579 3 11577 2 0 1 11579 4 2 8159 3 0 1 11587 1 11585 1 11587 2 2 11583 1 11587 3 11585 6 0 1 11587 4 2 10873 8 0 1 11593 1 11588 1 11593 2 5 11592 1 11593 3 11588 2 0 1 11593 4 5 9337 12 0 1 11597 1 11594 1 11597 2 3 11587 1 11597 3 11594 4 0 1 11597 4 3 9996 7 0 1 11617 1 11607 1 11617 2 10 11616 1 11617 3 11607 4 0 1 11617 4 10 6340 21 0 1 11621 1 11619 1 11621 2 2 11617 1 11621 3 11619 3 0 1 11621 4 2 10543 6 0 1 11633 1 11630 1 11633 2 3 11632 1 11633 3 11630 4 0 1 11633 4 3 8552 4 0 1 11657 1 11654 1 11657 2 3 11656 1 11657 3 11654 6 0 1 11657 4 3 6727 6 0 1 11677 1 11675 1 11677 2 2 11673 1 11677 3 11675 4 0 1 11677 4 2 10358 18 0 1 11681 1 11678 1 11681 2 3 11673 1 11681 3 11678 1 0 1 11681 4 3 8444 2 0 1 11689 1 11682 1 11689 2 7 11682 1 11689 3 11682 2 0 1 11689 4 7 7401 0 0 1 11699 1 11697 1 11699 2 2 11695 1 11699 3 11697 4 0 1 11699 4 2 5943 8 0 1 11701 1 11695 1 11701 2 6 11700 1 11701 3 11695 2 0 1 11701 4 6 6465 12 0 1 11717 1 11715 1 11717 2 2 11716 1 11717 3 11715 7 0 1 11717 4 2 9431 3 0 1 11719 1 11713 1 11719 2 6 11717 1 11719 3 11713 2 0 1 11719 4 6 10615 4 0 1 11731 1 11728 1 11731 2 3 11726 1 11731 3 11728 6 0 1 11731 4 3 7601 3 0 1 11743 1 11740 1 11743 2 3 11742 1 11743 3 11740 3 0 1 11743 4 3 11732 12 0 1 11777 1 11774 1 11777 2 3 11768 1 11777 3 11774 1 0 1 11777 4 3 8084 2 0 1 11779 1 11777 1 11779 2 2 11778 1 11779 3 11777 5 0 1 11779 4 2 11591 2 0 1 11783 1 11778 1 11783 2 5 11782 1 11783 3 11778 7 0 1 11783 4 5 10624 2 0 1 11789 1 11787 1 11789 2 2 11785 1 11789 3 11787 2 0 1 11789 4 2 9784 7 0 1 11801 1 11798 1 11801 2 3 11795 1 11801 3 11798 4 0 1 11801 4 3 11789 0 0 1 11807 1 11802 1 11807 2 5 11802 1 11807 3 11802 2 0 1 11807 4 5 11346 6 0 1 11813 1 11811 1 11813 2 2 11809 1 11813 3 11811 5 0 1 11813 4 2 6237 9 0 1 11821 1 11819 1 11821 2 2 11820 1 11821 3 11819 6 0 1 11821 4 2 7766 3 0 1 11827 1 11825 1 11827 2 2 11823 1 11827 3 11825 4 0 1 11827 4 2 8917 8 0 1 11831 1 11824 1 11831 2 7 11829 1 11831 3 11824 1 0 1 11831 4 7 11523 11 0 1 11833 1 11828 1 11833 2 5 11832 1 11833 3 11828 3 0 1 11833 4 5 9164 6 0 1 11839 1 11836 1 11839 2 3 11837 1 11839 3 11836 3 0 1 11839 4 3 9176 3 0 1 11863 1 11860 1 11863 2 3 11861 1 11863 3 11860 4 0 1 11863 4 3 11859 4 0 1 11867 1 11865 1 11867 2 2 11863 1 11867 3 11865 3 0 1 11867 4 2 7791 7 0 1 11887 1 11884 1 11887 2 3 11886 1 11887 3 11884 1 0 1 11887 4 3 10400 18 0 1 11897 1 11894 1 11897 2 3 11896 1 11897 3 11894 1 0 1 11897 4 3 8766 4 0 1 11903 1 11898 1 11903 2 5 11901 1 11903 3 11898 2 0 1 11903 4 5 11899 3 0 1 11909 1 11907 1 11909 2 2 11893 1 11909 3 11907 5 0 1 11909 4 2 7289 2 0 1 11923 1 11918 1 11923 2 5 11922 1 11923 3 11918 1 0 1 11923 4 5 6692 5 0 1 11927 1 11922 1 11927 2 5 11919 1 11927 3 11922 3 0 1 11927 4 5 7777 10 0 1 11933 1 11931 1 11933 2 2 11932 1 11933 3 11931 2 0 1 11933 4 2 7489 4 0 1 11939 1 11937 1 11939 2 2 11934 1 11939 3 11937 9 0 1 11939 4 2 11206 3 0 1 11941 1 11931 1 11941 2 10 11940 1 11941 3 11931 3 0 1 11941 4 10 6541 3 0 1 11953 1 11948 1 11953 2 5 11952 1 11953 3 11948 3 0 1 11953 4 5 8562 6 0 1 11959 1 11956 1 11959 2 3 11958 1 11959 3 11956 4 0 1 11959 4 3 6303 2 0 1 11969 1 11966 1 11969 2 3 11962 1 11969 3 11966 10 0 1 11969 4 3 8176 4 0 1 11971 1 11961 1 11971 2 10 11970 1 11971 3 11961 2 0 1 11971 4 10 8429 5 0 1 11981 1 11979 1 11981 2 2 11973 1 11981 3 11979 2 0 1 11981 4 2 7574 0 0 1 11987 1 11985 1 11987 2 2 11980 1 11987 3 11985 2 0 1 11987 4 2 10954 1 0 1 12007 1 11994 1 12007 2 13 12006 1 12007 3 11994 5 0 1 12007 4 13 10837 3 0 1 12011 1 12009 1 12011 2 2 12007 1 12011 3 12009 3 0 1 12011 4 2 9302 9 0 1 12037 1 12032 1 12037 2 5 12036 1 12037 3 12032 1 0 1 12037 4 5 7802 6 0 1 12041 1 12038 1 12041 2 3 12040 1 12041 3 12038 6 0 1 12041 4 3 8855 4 0 1 12043 1 12041 1 12043 2 2 12042 1 12043 3 12041 2 0 1 12043 4 2 9243 2 0 1 12049 1 12036 1 12049 2 13 12040 1 12049 3 12036 4 0 1 12049 4 13 8499 35 0 1 12071 1 12060 1 12071 2 11 12068 1 12071 3 12060 4 0 1 12071 4 11 10269 6 0 1 12073 1 12066 1 12073 2 7 12070 1 12073 3 12066 2 0 1 12073 4 7 8681 8 0 1 12097 1 12092 1 12097 2 5 12096 1 12097 3 12092 3 0 1 12097 4 5 6345 12 0 1 12101 1 12098 1 12101 2 3 12090 1 12101 3 12098 4 0 1 12101 4 3 9744 1 0 1 12107 1 12105 1 12107 2 2 12102 1 12107 3 12105 4 0 1 12107 4 2 11759 3 0 1 12109 1 12103 1 12109 2 6 12108 1 12109 3 12103 8 0 1 12109 4 6 8914 7 0 1 12113 1 12110 1 12113 2 3 12106 1 12113 3 12110 4 0 1 12113 4 3 6426 0 0 1 12119 1 12112 1 12119 2 7 12118 1 12119 3 12112 1 0 1 12119 4 7 8857 7 0 1 12143 1 12133 1 12143 2 10 12142 1 12143 3 12133 10 0 1 12143 4 10 10228 2 0 1 12149 1 12147 1 12149 2 2 12144 1 12149 3 12147 5 0 1 12149 4 2 10662 2 0 1 12157 1 12155 1 12157 2 2 12156 1 12157 3 12155 2 0 1 12157 4 2 9056 3 0 1 12161 1 12158 1 12161 2 3 12153 1 12161 3 12158 3 0 1 12161 4 3 6434 2 0 1 12163 1 12158 1 12163 2 5 12162 1 12163 3 12158 2 0 1 12163 4 5 8225 2 0 1 12197 1 12195 1 12197 2 2 12196 1 12197 3 12195 11 0 1 12197 4 2 7573 6 0 1 12203 1 12201 1 12203 2 2 12199 1 12203 3 12201 3 0 1 12203 4 2 6197 8 0 1 12211 1 12209 1 12211 2 2 12210 1 12211 3 12209 5 0 1 12211 4 2 7980 6 0 1 12227 1 12225 1 12227 2 2 12226 1 12227 3 12225 2 0 1 12227 4 2 6696 2 0 1 12239 1 12226 1 12239 2 13 12238 1 12239 3 12226 3 0 1 12239 4 13 11522 2 0 1 12241 1 12234 1 12241 2 7 12234 1 12241 3 12234 5 0 1 12241 4 7 7895 14 0 1 12251 1 12249 1 12251 2 2 12246 1 12251 3 12249 2 0 1 12251 4 2 6778 3 0 1 12253 1 12251 1 12253 2 2 12252 1 12253 3 12251 2 0 1 12253 4 2 7895 3 0 1 12263 1 12258 1 12263 2 5 12262 1 12263 3 12258 1 0 1 12263 4 5 8857 3 0 1 12269 1 12267 1 12269 2 2 12268 1 12269 3 12267 5 0 1 12269 4 2 6657 4 0 1 12277 1 12275 1 12277 2 2 12276 1 12277 3 12275 2 0 1 12277 4 2 6367 6 0 1 12281 1 12278 1 12281 2 3 12264 1 12281 3 12278 1 0 1 12281 4 3 9966 0 0 1 12289 1 12278 1 12289 2 11 12288 1 12289 3 12278 1 0 1 12289 4 11 10637 23 0 1 12301 1 12299 1 12301 2 2 12297 1 12301 3 12299 5 0 1 12301 4 2 11309 6 0 1 12323 1 12321 1 12323 2 2 12322 1 12323 3 12321 3 0 1 12323 4 2 7335 2 0 1 12329 1 12326 1 12329 2 3 12324 1 12329 3 12326 6 0 1 12329 4 3 8762 8 0 1 12343 1 12336 1 12343 2 7 12340 1 12343 3 12336 3 0 1 12343 4 7 11091 0 0 1 12347 1 12345 1 12347 2 2 12346 1 12347 3 12345 2 0 1 12347 4 2 10924 4 0 1 12373 1 12371 1 12373 2 2 12369 1 12373 3 12371 4 0 1 12373 4 2 11774 6 0 1 12377 1 12371 1 12377 2 6 12366 1 12377 3 12371 3 0 1 12377 4 6 9835 1 0 1 12379 1 12377 1 12379 2 2 12378 1 12379 3 12377 5 0 1 12379 4 2 12372 8 0 1 12391 1 12365 1 12391 2 26 12390 1 12391 3 12365 1 0 1 12391 4 26 10137 3 0 1 12401 1 12398 1 12401 2 3 12395 1 12401 3 12398 6 0 1 12401 4 3 12389 0 0 1 12409 1 12402 1 12409 2 7 12406 1 12409 3 12402 4 0 1 12409 4 7 9146 16 0 1 12413 1 12411 1 12413 2 2 12409 1 12413 3 12411 8 0 1 12413 4 2 6331 6 0 1 12421 1 12414 1 12421 2 7 12419 1 12421 3 12414 5 0 1 12421 4 7 11329 4 0 1 12433 1 12420 1 12433 2 13 12432 1 12433 3 12420 3 0 1 12433 4 13 7663 11 0 1 12437 1 12435 1 12437 2 2 12436 1 12437 3 12435 3 0 1 12437 4 2 10551 3 0 1 12451 1 12448 1 12451 2 3 12450 1 12451 3 12448 1 0 1 12451 4 3 11286 7 0 1 12457 1 12447 1 12457 2 10 12454 1 12457 3 12447 2 0 1 12457 4 10 10267 8 0 1 12473 1 12470 1 12473 2 3 12467 1 12473 3 12470 3 0 1 12473 4 3 10319 16 0 1 12479 1 12456 1 12479 2 23 12466 1 12479 3 12456 3 0 1 12479 4 23 8509 14 0 1 12487 1 12484 1 12487 2 3 12486 1 12487 3 12484 10 0 1 12487 4 3 6883 2 0 1 12491 1 12489 1 12491 2 2 12487 1 12491 3 12489 3 0 1 12491 4 2 10160 7 0 1 12497 1 12494 1 12497 2 3 12491 1 12497 3 12494 4 0 1 12497 4 3 8631 25 0 1 12503 1 12498 1 12503 2 5 12498 1 12503 3 12498 2 0 1 12503 4 5 10642 7 0 1 12511 1 12508 1 12511 2 3 12509 1 12511 3 12508 5 0 1 12511 4 3 8133 6 0 1 12517 1 12511 1 12517 2 6 12516 1 12517 3 12511 1 0 1 12517 4 6 10850 6 0 1 12527 1 12522 1 12527 2 5 12519 1 12527 3 12522 5 0 1 12527 4 5 10348 1 0 1 12539 1 12537 1 12539 2 2 12535 1 12539 3 12537 3 0 1 12539 4 2 8483 8 0 1 12541 1 12527 1 12541 2 14 12538 1 12541 3 12527 2 0 1 12541 4 14 12187 1 0 1 12547 1 12545 1 12547 2 2 12546 1 12547 3 12545 2 0 1 12547 4 2 11040 7 0 1 12553 1 12548 1 12553 2 5 12552 1 12553 3 12548 5 0 1 12553 4 5 9804 6 0 1 12569 1 12566 1 12569 2 3 12563 1 12569 3 12566 3 0 1 12569 4 3 12557 0 0 1 12577 1 12567 1 12577 2 10 12576 1 12577 3 12567 4 0 1 12577 4 10 10786 15 0 1 12583 1 12578 1 12583 2 5 12581 1 12583 3 12578 1 0 1 12583 4 5 7861 15 0 1 12589 1 12587 1 12589 2 2 12588 1 12589 3 12587 4 0 1 12589 4 2 12582 8 0 1 12601 1 12590 1 12601 2 11 12600 1 12601 3 12590 3 0 1 12601 4 11 8297 23 0 1 12611 1 12609 1 12611 2 2 12607 1 12611 3 12609 2 0 1 12611 4 2 8240 7 0 1 12613 1 12611 1 12613 2 2 12612 1 12613 3 12611 6 0 1 12613 4 2 6509 3 0 1 12619 1 12617 1 12619 2 2 12618 1 12619 3 12617 5 0 1 12619 4 2 9097 2 0 1 12637 1 12635 1 12637 2 2 12633 1 12637 3 12635 4 0 1 12637 4 2 9579 6 0 1 12641 1 12638 1 12641 2 3 12636 1 12641 3 12638 3 0 1 12641 4 3 11325 2 0 1 12647 1 12642 1 12647 2 5 12645 1 12647 3 12642 1 0 1 12647 4 5 10998 8 0 1 12653 1 12651 1 12653 2 2 12649 1 12653 3 12651 3 0 1 12653 4 2 7719 6 0 1 12659 1 12657 1 12659 2 2 12655 1 12659 3 12657 3 0 1 12659 4 2 9226 9 0 1 12671 1 12657 1 12671 2 14 12666 1 12671 3 12657 6 0 1 12671 4 14 8174 8 0 1 12689 1 12686 1 12689 2 3 12663 1 12689 3 12686 1 0 1 12689 4 3 10300 11 0 1 12697 1 12690 1 12697 2 7 12690 1 12697 3 12690 11 0 1 12697 4 7 7201 14 0 1 12703 1 12700 1 12703 2 3 12701 1 12703 3 12700 4 0 1 12703 4 3 12695 10 0 1 12713 1 12710 1 12713 2 3 12712 1 12713 3 12710 5 0 1 12713 4 3 11614 7 0 1 12721 1 12708 1 12721 2 13 12720 1 12721 3 12708 5 0 1 12721 4 13 11757 14 0 1 12739 1 12737 1 12739 2 2 12738 1 12739 3 12737 6 0 1 12739 4 2 7197 6 0 1 12743 1 12738 1 12743 2 5 12742 1 12743 3 12738 3 0 1 12743 4 5 9400 3 0 1 12757 1 12755 1 12757 2 2 12756 1 12757 3 12755 2 0 1 12757 4 2 10778 7 0 1 12763 1 12761 1 12763 2 2 12759 1 12763 3 12761 4 0 1 12763 4 2 12176 8 0 1 12781 1 12779 1 12781 2 2 12780 1 12781 3 12779 4 0 1 12781 4 2 7134 3 0 1 12791 1 12784 1 12791 2 7 12790 1 12791 3 12784 13 0 1 12791 4 7 12538 3 0 1 12799 1 12786 1 12799 2 13 12796 1 12799 3 12786 7 0 1 12799 4 13 9776 4 0 1 12809 1 12806 1 12809 2 3 12803 1 12809 3 12806 8 0 1 12809 4 3 12797 0 0 1 12821 1 12819 1 12821 2 2 12817 1 12821 3 12819 7 0 1 12821 4 2 8064 6 0 1 12823 1 12820 1 12823 2 3 12821 1 12823 3 12820 5 0 1 12823 4 3 12819 4 0 1 12829 1 12827 1 12829 2 2 12828 1 12829 3 12827 6 0 1 12829 4 2 12822 8 0 1 12841 1 12820 1 12841 2 21 12837 1 12841 3 12820 1 0 1 12841 4 21 12285 18 0 1 12853 1 12848 1 12853 2 5 12848 1 12853 3 12848 1 0 1 12853 4 5 10364 10 0 1 12889 1 12876 1 12889 2 13 12876 1 12889 3 12876 1 0 1 12889 4 13 12850 0 0 1 12893 1 12890 1 12893 2 3 12891 1 12893 3 12890 1 0 1 12893 4 3 12889 4 0 1 12899 1 12897 1 12899 2 2 12895 1 12899 3 12897 3 0 1 12899 4 2 11522 7 0 1 12907 1 12905 1 12907 2 2 12906 1 12907 3 12905 2 0 1 12907 4 2 10806 2 0 1 12911 1 12888 1 12911 2 23 12909 1 12911 3 12888 3 0 1 12911 4 23 11184 3 0 1 12917 1 12915 1 12917 2 2 12913 1 12917 3 12915 3 0 1 12917 4 2 10722 6 0 1 12919 1 12913 1 12919 2 6 12917 1 12919 3 12913 3 0 1 12919 4 6 12237 4 0 1 12923 1 12921 1 12923 2 2 12919 1 12923 3 12921 5 0 1 12923 4 2 9816 8 0 1 12941 1 12939 1 12941 2 2 12937 1 12941 3 12939 3 0 1 12941 4 2 6943 1 0 1 12953 1 12950 1 12953 2 3 12952 1 12953 3 12950 3 0 1 12953 4 3 6783 4 0 1 12959 1 12952 1 12959 2 7 12958 1 12959 3 12952 1 0 1 12959 4 7 12476 2 0 1 12967 1 12964 1 12967 2 3 12965 1 12967 3 12964 8 0 1 12967 4 3 12959 10 0 1 12973 1 12959 1 12973 2 14 12972 1 12973 3 12959 1 0 1 12973 4 14 8938 3 0 1 12979 1 12977 1 12979 2 2 12975 1 12979 3 12977 2 0 1 12979 4 2 12782 20 0 1 12983 1 12978 1 12983 2 5 12978 1 12983 3 12978 8 0 1 12983 4 5 8709 6 0 1 13001 1 12998 1 13001 2 3 12992 1 13001 3 12998 1 0 1 13001 4 3 8473 6 0 1 13003 1 12998 1 13003 2 5 13001 1 13003 3 12998 9 0 1 13003 4 5 12995 6 0 1 13007 1 13002 1 13007 2 5 13005 1 13007 3 13002 2 0 1 13007 4 5 13003 3 0 1 13009 1 13002 1 13009 2 7 13006 1 13009 3 13002 2 0 1 13009 4 7 11645 14 0 1 13033 1 13028 1 13033 2 5 13028 1 13033 3 13028 5 0 1 13033 4 5 8087 10 0 1 13037 1 13035 1 13037 2 2 13036 1 13037 3 13035 2 0 1 13037 4 2 10273 3 0 1 13043 1 13041 1 13043 2 2 13037 1 13043 3 13041 4 0 1 13043 4 2 10220 4 0 1 13049 1 13046 1 13049 2 3 13043 1 13049 3 13046 6 0 1 13049 4 3 13037 0 0 1 13063 1 13058 1 13063 2 5 13062 1 13063 3 13058 1 0 1 13063 4 5 6753 5 0 1 13093 1 13087 1 13093 2 6 13091 1 13093 3 13087 2 0 1 13093 4 6 12260 0 0 1 13099 1 13096 1 13099 2 3 13094 1 13099 3 13096 1 0 1 13099 4 3 9131 3 0 1 13103 1 13098 1 13103 2 5 13100 1 13103 3 13098 2 0 1 13103 4 5 12631 6 0 1 13109 1 13107 1 13109 2 2 13108 1 13109 3 13107 4 0 1 13109 4 2 10967 3 0 1 13121 1 13114 1 13121 2 7 13120 1 13121 3 13114 1 0 1 13121 4 7 13112 4 0 1 13127 1 13122 1 13127 2 5 13125 1 13127 3 13122 6 0 1 13127 4 5 11607 5 0 1 13147 1 13145 1 13147 2 2 13143 1 13147 3 13145 5 0 1 13147 4 2 10388 8 0 1 13151 1 13138 1 13151 2 13 13149 1 13151 3 13138 2 0 1 13151 4 13 8034 3 0 1 13159 1 13156 1 13159 2 3 13157 1 13159 3 13156 1 0 1 13159 4 3 7702 6 0 1 13163 1 13161 1 13163 2 2 13162 1 13163 3 13161 2 0 1 13163 4 2 10042 4 0 1 13171 1 13160 1 13171 2 11 13155 1 13171 3 13160 3 0 1 13171 4 11 9001 1 0 1 13177 1 13172 1 13177 2 5 13176 1 13177 3 13172 1 0 1 13177 4 5 12852 12 0 1 13183 1 13180 1 13183 2 3 13181 1 13183 3 13180 3 0 1 13183 4 3 9259 6 0 1 13187 1 13185 1 13187 2 2 13186 1 13187 3 13185 2 0 1 13187 4 2 11476 2 0 1 13217 1 13214 1 13217 2 3 13216 1 13217 3 13214 6 0 1 13217 4 3 8353 7 0 1 13219 1 13216 1 13219 2 3 13218 1 13219 3 13216 1 0 1 13219 4 3 9064 2 0 1 13229 1 13227 1 13229 2 2 13228 1 13229 3 13227 3 0 1 13229 4 2 12376 3 0 1 13241 1 13238 1 13241 2 3 13235 1 13241 3 13238 3 0 1 13241 4 3 13229 0 0 1 13249 1 13242 1 13249 2 7 13242 1 13249 3 13242 2 0 1 13249 4 7 9771 0 0 1 13259 1 13253 1 13259 2 6 13258 1 13259 3 13253 2 0 1 13259 4 6 7318 2 0 1 13267 1 13264 1 13267 2 3 13262 1 13267 3 13264 4 0 1 13267 4 3 12885 6 0 1 13291 1 13289 1 13291 2 2 13290 1 13291 3 13289 4 0 1 13291 4 2 9534 2 0 1 13297 1 13292 1 13297 2 5 13292 1 13297 3 13292 1 0 1 13297 4 5 10985 15 0 1 13309 1 13303 1 13309 2 6 13308 1 13309 3 13303 9 0 1 13309 4 6 10048 11 0 1 13313 1 13310 1 13313 2 3 13307 1 13313 3 13310 5 0 1 13313 4 3 10149 26 0 1 13327 1 13324 1 13327 2 3 13326 1 13327 3 13324 1 0 1 13327 4 3 12644 5 0 1 13331 1 13329 1 13331 2 2 13330 1 13331 3 13329 3 0 1 13331 4 2 13324 8 0 1 13337 1 13334 1 13337 2 3 13331 1 13337 3 13334 6 0 1 13337 4 3 11563 25 0 1 13339 1 13337 1 13339 2 2 13335 1 13339 3 13337 4 0 1 13339 4 2 11379 8 0 1 13367 1 13362 1 13367 2 5 13365 1 13367 3 13362 7 0 1 13367 4 5 10774 5 0 1 13381 1 13371 1 13381 2 10 13377 1 13381 3 13371 4 0 1 13381 4 10 13369 10 0 1 13397 1 13395 1 13397 2 2 13387 1 13397 3 13395 2 0 1 13397 4 2 8569 23 0 1 13399 1 13396 1 13399 2 3 13397 1 13399 3 13396 9 0 1 13399 4 3 13395 4 0 1 13411 1 13409 1 13411 2 2 13410 1 13411 3 13409 6 0 1 13411 4 2 12560 2 0 1 13417 1 13412 1 13417 2 5 13416 1 13417 3 13412 7 0 1 13417 4 5 9896 8 0 1 13421 1 13411 1 13421 2 10 13412 1 13421 3 13411 6 0 1 13421 4 10 11263 12 0 1 13441 1 13430 1 13441 2 11 13436 1 13441 3 13430 2 0 1 13441 4 11 13422 24 0 1 13451 1 13449 1 13451 2 2 13447 1 13451 3 13449 3 0 1 13451 4 2 13123 7 0 1 13457 1 13454 1 13457 2 3 13451 1 13457 3 13454 5 0 1 13457 4 3 13055 1 0 1 13463 1 13458 1 13463 2 5 13461 1 13463 3 13458 2 0 1 13463 4 5 7855 8 0 1 13469 1 13467 1 13469 2 2 13465 1 13469 3 13467 2 0 1 13469 4 2 12001 6 0 1 13477 1 13475 1 13477 2 2 13473 1 13477 3 13475 6 0 1 13477 4 2 8310 10 0 1 13487 1 13482 1 13487 2 5 13485 1 13487 3 13482 9 0 1 13487 4 5 13483 3 0 1 13499 1 13493 1 13499 2 6 13498 1 13499 3 13493 1 0 1 13499 4 6 11673 2 0 1 13513 1 13508 1 13513 2 5 13508 1 13513 3 13508 1 0 1 13513 4 5 12909 12 0 1 13523 1 13521 1 13523 2 2 13522 1 13523 3 13521 3 0 1 13523 4 2 10269 2 0 1 13537 1 13530 1 13537 2 7 13530 1 13537 3 13530 7 0 1 13537 4 7 13336 17 0 1 13553 1 13550 1 13553 2 3 13548 1 13553 3 13550 4 0 1 13553 4 3 9255 0 0 1 13567 1 13564 1 13567 2 3 13565 1 13567 3 13564 17 0 1 13567 4 3 10098 6 0 1 13577 1 13574 1 13577 2 3 13572 1 13577 3 13574 9 0 1 13577 4 3 11270 0 0 1 13591 1 13588 1 13591 2 3 13590 1 13591 3 13588 4 0 1 13591 4 3 7954 2 0 1 13597 1 13592 1 13597 2 5 13592 1 13597 3 13592 2 0 1 13597 4 5 8962 12 0 1 13613 1 13611 1 13613 2 2 13612 1 13613 3 13611 2 0 1 13613 4 2 9342 4 0 1 13619 1 13617 1 13619 2 2 13612 1 13619 3 13617 7 0 1 13619 4 2 12678 1 0 1 13627 1 13625 1 13627 2 2 13626 1 13627 3 13625 6 0 1 13627 4 2 13620 8 0 1 13633 1 13628 1 13633 2 5 13632 1 13633 3 13628 10 0 1 13633 4 5 8948 6 0 1 13649 1 13646 1 13649 2 3 13643 1 13649 3 13646 5 0 1 13649 4 3 13637 0 0 1 13669 1 13663 1 13669 2 6 13668 1 13669 3 13663 2 0 1 13669 4 6 8034 7 0 1 13679 1 13672 1 13679 2 7 13677 1 13679 3 13672 1 0 1 13679 4 7 12320 11 0 1 13681 1 13659 1 13681 2 22 13679 1 13681 3 13659 5 0 1 13681 4 22 12837 13 0 1 13687 1 13684 1 13687 2 3 13685 1 13687 3 13684 5 0 1 13687 4 3 13219 6 0 1 13691 1 13689 1 13691 2 2 13684 1 13691 3 13689 4 0 1 13691 4 2 7555 1 0 1 13693 1 13687 1 13693 2 6 13691 1 13693 3 13687 3 0 1 13693 4 6 12123 10 0 1 13697 1 13694 1 13697 2 3 13692 1 13697 3 13694 3 0 1 13697 4 3 12739 0 0 1 13709 1 13707 1 13709 2 2 13705 1 13709 3 13707 3 0 1 13709 4 2 10841 1 0 1 13711 1 13705 1 13711 2 6 13709 1 13711 3 13705 3 0 1 13711 4 6 10891 3 0 1 13721 1 13718 1 13721 2 3 13716 1 13721 3 13718 1 0 1 13721 4 3 13459 2 0 1 13723 1 13721 1 13723 2 2 13722 1 13723 3 13721 2 0 1 13723 4 2 13716 8 0 1 13729 1 13706 1 13729 2 23 13724 1 13729 3 13706 7 0 1 13729 4 23 9923 28 0 1 13751 1 13740 1 13751 2 11 13750 1 13751 3 13740 1 0 1 13751 4 11 12072 3 0 1 13757 1 13755 1 13757 2 2 13753 1 13757 3 13755 3 0 1 13757 4 2 12979 7 0 1 13759 1 13753 1 13759 2 6 13758 1 13759 3 13753 2 0 1 13759 4 6 11518 3 0 1 13763 1 13761 1 13763 2 2 13758 1 13763 3 13761 4 0 1 13763 4 2 8176 0 0 1 13781 1 13774 1 13781 2 7 13780 1 13781 3 13774 1 0 1 13781 4 7 12092 3 0 1 13789 1 13782 1 13789 2 7 13787 1 13789 3 13782 3 0 1 13789 4 7 12012 4 0 1 13799 1 13792 1 13799 2 7 13798 1 13799 3 13792 1 0 1 13799 4 7 13200 2 0 1 13807 1 13802 1 13807 2 5 13806 1 13807 3 13802 7 0 1 13807 4 5 7160 12 0 1 13829 1 13827 1 13829 2 2 13822 1 13829 3 13827 4 0 1 13829 4 2 13104 4 0 1 13831 1 13825 1 13831 2 6 13829 1 13831 3 13825 3 0 1 13831 4 6 7411 3 0 1 13841 1 13835 1 13841 2 6 13835 1 13841 3 13835 4 0 1 13841 4 6 9725 0 0 1 13859 1 13857 1 13859 2 2 13849 1 13859 3 13857 3 0 1 13859 4 2 8838 0 0 1 13873 1 13868 1 13873 2 5 13872 1 13873 3 13868 5 0 1 13873 4 5 12572 6 0 1 13877 1 13875 1 13877 2 2 13873 1 13877 3 13875 3 0 1 13877 4 2 12699 6 0 1 13879 1 13873 1 13879 2 6 13878 1 13879 3 13873 1 0 1 13879 4 6 7827 2 0 1 13883 1 13881 1 13883 2 2 13878 1 13883 3 13881 3 0 1 13883 4 2 8704 0 0 1 13901 1 13899 1 13901 2 2 13900 1 13901 3 13899 3 0 1 13901 4 2 10722 3 0 1 13903 1 13900 1 13903 2 3 13902 1 13903 3 13900 5 0 1 13903 4 3 9020 5 0 1 13907 1 13905 1 13907 2 2 13906 1 13907 3 13905 2 0 1 13907 4 2 12303 4 0 1 13913 1 13910 1 13913 2 3 13907 1 13913 3 13910 1 0 1 13913 4 3 9536 9 0 1 13921 1 13914 1 13921 2 7 13918 1 13921 3 13914 2 0 1 13921 4 7 10679 14 0 1 13931 1 13929 1 13931 2 2 13927 1 13931 3 13929 3 0 1 13931 4 2 12622 8 0 1 13933 1 13931 1 13933 2 2 13932 1 13933 3 13931 2 0 1 13933 4 2 12695 3 0 1 13963 1 13960 1 13963 2 3 13956 1 13963 3 13960 1 0 1 13963 4 3 9166 2 0 1 13967 1 13962 1 13967 2 5 13964 1 13967 3 13962 1 0 1 13967 4 5 13388 6 0 1 13997 1 13995 1 13997 2 2 13993 1 13997 3 13995 3 0 1 13997 4 2 9119 6 0 1 13999 1 13996 1 13999 2 3 13998 1 13999 3 13996 5 0 1 13999 4 3 13497 3 0 1 14009 1 14006 1 14009 2 3 14002 1 14009 3 14006 6 0 1 14009 4 3 7563 1 0 1 14011 1 14009 1 14011 2 2 14007 1 14011 3 14009 4 0 1 14011 4 2 13601 8 0 1 14029 1 14023 1 14029 2 6 14028 1 14029 3 14023 1 0 1 14029 4 6 10970 7 0 1 14033 1 14030 1 14033 2 3 14032 1 14033 3 14030 3 0 1 14033 4 3 13187 4 0 1 14051 1 14049 1 14051 2 2 14047 1 14051 3 14049 2 0 1 14051 4 2 7128 8 0 1 14057 1 14054 1 14057 2 3 14051 1 14057 3 14054 1 0 1 14057 4 3 11112 12 0 1 14071 1 14064 1 14071 2 7 14062 1 14071 3 14064 2 0 1 14071 4 7 13232 2 0 1 14081 1 14078 1 14081 2 3 14076 1 14081 3 14078 1 0 1 14081 4 3 9476 2 0 1 14083 1 14080 1 14083 2 3 14076 1 14083 3 14080 1 0 1 14083 4 3 8351 2 0 1 14087 1 14082 1 14087 2 5 14085 1 14087 3 14082 5 0 1 14087 4 5 10003 5 0 1 14107 1 14105 1 14107 2 2 14103 1 14107 3 14105 6 0 1 14107 4 2 8711 8 0 1 14143 1 14140 1 14143 2 3 14142 1 14143 3 14140 1 0 1 14143 4 3 8452 2 0 1 14149 1 14143 1 14149 2 6 14145 1 14149 3 14143 1 0 1 14149 4 6 12231 2 0 1 14153 1 14150 1 14153 2 3 14152 1 14153 3 14150 4 0 1 14153 4 3 9492 7 0 1 14159 1 14146 1 14159 2 13 14142 1 14159 3 14146 2 0 1 14159 4 13 7929 4 0 1 14173 1 14171 1 14173 2 2 14172 1 14173 3 14171 2 0 1 14173 4 2 7332 6 0 1 14177 1 14174 1 14177 2 3 14172 1 14177 3 14174 1 0 1 14177 4 3 13112 0 0 1 14197 1 14186 1 14197 2 11 14196 1 14197 3 14186 1 0 1 14197 4 11 13990 7 0 1 14207 1 14202 1 14207 2 5 14206 1 14207 3 14202 3 0 1 14207 4 5 10123 3 0 1 14221 1 14219 1 14221 2 2 14217 1 14221 3 14219 2 0 1 14221 4 2 10322 10 0 1 14243 1 14241 1 14243 2 2 14239 1 14243 3 14241 2 0 1 14243 4 2 11177 7 0 1 14249 1 14246 1 14249 2 3 14240 1 14249 3 14246 5 0 1 14249 4 3 8020 3 0 1 14251 1 14248 1 14251 2 3 14244 1 14251 3 14248 1 0 1 14251 4 3 7517 5 0 1 14281 1 14262 1 14281 2 19 14268 1 14281 3 14262 4 0 1 14281 4 19 12888 32 0 1 14293 1 14287 1 14293 2 6 14292 1 14293 3 14287 1 0 1 14293 4 6 9296 7 0 1 14303 1 14298 1 14303 2 5 14302 1 14303 3 14298 1 0 1 14303 4 5 13408 4 0 1 14321 1 14318 1 14321 2 3 14320 1 14321 3 14318 1 0 1 14321 4 3 12410 7 0 1 14323 1 14318 1 14323 2 5 14321 1 14323 3 14318 1 0 1 14323 4 5 14315 6 0 1 14327 1 14322 1 14327 2 5 14319 1 14327 3 14322 1 0 1 14327 4 5 13083 3 0 1 14341 1 14339 1 14341 2 2 14340 1 14341 3 14339 4 0 1 14341 4 2 13520 3 0 1 14347 1 14344 1 14347 2 3 14342 1 14347 3 14344 7 0 1 14347 4 3 12043 3 0 1 14369 1 14366 1 14369 2 3 14363 1 14369 3 14366 1 0 1 14369 4 3 14357 0 0 1 14387 1 14385 1 14387 2 2 14383 1 14387 3 14385 3 0 1 14387 4 2 11871 7 0 1 14389 1 14387 1 14389 2 2 14384 1 14389 3 14387 2 0 1 14389 4 2 12161 18 0 1 14401 1 14390 1 14401 2 11 14400 1 14401 3 14390 2 0 1 14401 4 11 9977 20 0 1 14407 1 14388 1 14407 2 19 14405 1 14407 3 14388 1 0 1 14407 4 19 13007 11 0 1 14411 1 14409 1 14411 2 2 14406 1 14411 3 14409 4 0 1 14411 4 2 9697 3 0 1 14419 1 14417 1 14419 2 2 14418 1 14419 3 14417 4 0 1 14419 4 2 8774 6 0 1 14423 1 14418 1 14423 2 5 14422 1 14423 3 14418 1 0 1 14423 4 5 9831 3 0 1 14431 1 14428 1 14431 2 3 14430 1 14431 3 14428 3 0 1 14431 4 3 11655 3 0 1 14437 1 14432 1 14437 2 5 14432 1 14437 3 14432 3 0 1 14437 4 5 9262 7 0 1 14447 1 14442 1 14447 2 5 14442 1 14447 3 14442 6 0 1 14447 4 5 9069 7 0 1 14449 1 14427 1 14449 2 22 14443 1 14449 3 14427 1 0 1 14449 4 22 13340 39 0 1 14461 1 14459 1 14461 2 2 14460 1 14461 3 14459 4 0 1 14461 4 2 7365 3 0 1 14479 1 14476 1 14479 2 3 14477 1 14479 3 14476 1 0 1 14479 4 3 14475 4 0 1 14489 1 14486 1 14489 2 3 14484 1 14489 3 14486 3 0 1 14489 4 3 11364 2 0 1 14503 1 14500 1 14503 2 3 14501 1 14503 3 14500 15 0 1 14503 4 3 14495 10 0 1 14519 1 14506 1 14519 2 13 14516 1 14519 3 14506 1 0 1 14519 4 13 10077 4 0 1 14533 1 14531 1 14533 2 2 14526 1 14533 3 14531 4 0 1 14533 4 2 12880 2 0 1 14537 1 14534 1 14537 2 3 14536 1 14537 3 14534 5 0 1 14537 4 3 11076 4 0 1 14543 1 14538 1 14543 2 5 14542 1 14543 3 14538 2 0 1 14543 4 5 8060 2 0 1 14549 1 14547 1 14549 2 2 14536 1 14549 3 14547 4 0 1 14549 4 2 13678 0 0 1 14551 1 14548 1 14551 2 3 14549 1 14551 3 14548 1 0 1 14551 4 3 13724 6 0 1 14557 1 14555 1 14557 2 2 14553 1 14557 3 14555 4 0 1 14557 4 2 14122 6 0 1 14561 1 14555 1 14561 2 6 14558 1 14561 3 14555 2 0 1 14561 4 6 13475 0 0 1 14563 1 14560 1 14563 2 3 14562 1 14563 3 14560 1 0 1 14563 4 3 10162 2 0 1 14591 1 14580 1 14591 2 11 14588 1 14591 3 14580 2 0 1 14591 4 11 14295 5 0 1 14593 1 14588 1 14593 2 5 14590 1 14593 3 14588 7 0 1 14593 4 5 14582 14 0 1 14621 1 14619 1 14621 2 2 14615 1 14621 3 14619 7 0 1 14621 4 2 11075 4 0 1 14627 1 14625 1 14627 2 2 14623 1 14627 3 14625 3 0 1 14627 4 2 7514 7 0 1 14629 1 14627 1 14629 2 2 14623 1 14629 3 14627 5 0 1 14629 4 2 8495 0 0 1 14633 1 14630 1 14633 2 3 14627 1 14633 3 14630 1 0 1 14633 4 3 9488 9 0 1 14639 1 14628 1 14639 2 11 14633 1 14639 3 14628 1 0 1 14639 4 11 14397 7 0 1 14653 1 14651 1 14653 2 2 14649 1 14653 3 14651 7 0 1 14653 4 2 9191 12 0 1 14657 1 14654 1 14657 2 3 14652 1 14657 3 14654 3 0 1 14657 4 3 12260 0 0 1 14669 1 14667 1 14669 2 2 14657 1 14669 3 14667 2 0 1 14669 4 2 11437 1 0 1 14683 1 14680 1 14683 2 3 14678 1 14683 3 14680 5 0 1 14683 4 3 14412 3 0 1 14699 1 14697 1 14699 2 2 14698 1 14699 3 14697 3 0 1 14699 4 2 11988 4 0 1 14713 1 14708 1 14713 2 5 14710 1 14713 3 14708 5 0 1 14713 4 5 14702 14 0 1 14717 1 14715 1 14717 2 2 14713 1 14717 3 14715 2 0 1 14717 4 2 9721 6 0 1 14723 1 14721 1 14723 2 2 14719 1 14723 3 14721 3 0 1 14723 4 2 13815 7 0 1 14731 1 14721 1 14731 2 10 14730 1 14731 3 14721 3 0 1 14731 4 10 13058 2 0 1 14737 1 14727 1 14737 2 10 14736 1 14737 3 14727 7 0 1 14737 4 10 10198 6 0 1 14741 1 14739 1 14741 2 2 14740 1 14741 3 14739 3 0 1 14741 4 2 11603 9 0 1 14747 1 14745 1 14747 2 2 14740 1 14747 3 14745 2 0 1 14747 4 2 10091 1 0 1 14753 1 14750 1 14753 2 3 14752 1 14753 3 14750 3 0 1 14753 4 3 14315 6 0 1 14759 1 14742 1 14759 2 17 14757 1 14759 3 14742 5 0 1 14759 4 17 14751 3 0 1 14767 1 14764 1 14767 2 3 14765 1 14767 3 14764 8 0 1 14767 4 3 11676 6 0 1 14771 1 14769 1 14771 2 2 14765 1 14771 3 14769 2 0 1 14771 4 2 14427 0 0 1 14779 1 14776 1 14779 2 3 14778 1 14779 3 14776 8 0 1 14779 4 3 9676 2 0 1 14783 1 14778 1 14783 2 5 14774 1 14783 3 14778 5 0 1 14783 4 5 12067 10 0 1 14797 1 14795 1 14797 2 2 14796 1 14797 3 14795 6 0 1 14797 4 2 11646 3 0 1 14813 1 14811 1 14813 2 2 14809 1 14813 3 14811 3 0 1 14813 4 2 13288 6 0 1 14821 1 14819 1 14821 2 2 14817 1 14821 3 14819 4 0 1 14821 4 2 10680 6 0 1 14827 1 14825 1 14827 2 2 14823 1 14827 3 14825 6 0 1 14827 4 2 8938 8 0 1 14831 1 14820 1 14831 2 11 14830 1 14831 3 14820 1 0 1 14831 4 11 14142 4 0 1 14843 1 14841 1 14843 2 2 14839 1 14843 3 14841 3 0 1 14843 4 2 14210 13 0 1 14851 1 14849 1 14851 2 2 14847 1 14851 3 14849 5 0 1 14851 4 2 14640 8 0 1 14867 1 14865 1 14867 2 2 14866 1 14867 3 14865 2 0 1 14867 4 2 11809 4 0 1 14869 1 14867 1 14869 2 2 14865 1 14869 3 14867 2 0 1 14869 4 2 12464 6 0 1 14879 1 14872 1 14879 2 7 14878 1 14879 3 14872 2 0 1 14879 4 7 7908 2 0 1 14887 1 14884 1 14887 2 3 14885 1 14887 3 14884 1 0 1 14887 4 3 13556 3 0 1 14891 1 14889 1 14891 2 2 14887 1 14891 3 14889 2 0 1 14891 4 2 9122 7 0 1 14897 1 14894 1 14897 2 3 14891 1 14897 3 14894 1 0 1 14897 4 3 11419 1 0 1 14923 1 14921 1 14923 2 2 14922 1 14923 3 14921 5 0 1 14923 4 2 9081 10 0 1 14929 1 14922 1 14929 2 7 14926 1 14929 3 14922 1 0 1 14929 4 7 9447 16 0 1 14939 1 14937 1 14939 2 2 14935 1 14939 3 14937 3 0 1 14939 4 2 12854 7 0 1 14947 1 14945 1 14947 2 2 14943 1 14947 3 14945 6 0 1 14947 4 2 12696 8 0 1 14951 1 14932 1 14951 2 19 14950 1 14951 3 14932 1 0 1 14951 4 19 9679 2 0 1 14957 1 14955 1 14957 2 2 14956 1 14957 3 14955 2 0 1 14957 4 2 14950 8 0 1 14969 1 14966 1 14969 2 3 14964 1 14969 3 14966 3 0 1 14969 4 3 13196 2 0 1 14983 1 14980 1 14983 2 3 14981 1 14983 3 14980 6 0 1 14983 4 3 14979 4 0 1 15013 1 15011 1 15013 2 2 15012 1 15013 3 15011 2 0 1 15013 4 2 11191 6 0 1 15017 1 15014 1 15017 2 3 15016 1 15017 3 15014 4 0 1 15017 4 3 11978 7 0 1 15031 1 15028 1 15031 2 3 15029 1 15031 3 15028 3 0 1 15031 4 3 8554 3 0 1 15053 1 15051 1 15053 2 2 15047 1 15053 3 15051 8 0 1 15053 4 2 14277 4 0 1 15061 1 15059 1 15061 2 2 15057 1 15061 3 15059 5 0 1 15061 4 2 9468 10 0 1 15073 1 15068 1 15073 2 5 15068 1 15073 3 15068 3 0 1 15073 4 5 13101 15 0 1 15077 1 15075 1 15077 2 2 15076 1 15077 3 15075 3 0 1 15077 4 2 10509 9 0 1 15083 1 15081 1 15083 2 2 15075 1 15083 3 15081 2 0 1 15083 4 2 7810 0 0 1 15091 1 15089 1 15091 2 2 15087 1 15091 3 15089 6 0 1 15091 4 2 7652 1 0 1 15101 1 15099 1 15101 2 2 15093 1 15101 3 15099 7 0 1 15101 4 2 14609 0 0 1 15107 1 15105 1 15107 2 2 15101 1 15107 3 15105 8 0 1 15107 4 2 12520 0 0 1 15121 1 15110 1 15121 2 11 15120 1 15121 3 15110 3 0 1 15121 4 11 11091 23 0 1 15131 1 15129 1 15131 2 2 15127 1 15131 3 15129 3 0 1 15131 4 2 14639 8 0 1 15137 1 15134 1 15137 2 3 15132 1 15137 3 15134 1 0 1 15137 4 3 12044 0 0 1 15139 1 15137 1 15139 2 2 15138 1 15139 3 15137 4 0 1 15139 4 2 10952 2 0 1 15149 1 15147 1 15149 2 2 15145 1 15149 3 15147 2 0 1 15149 4 2 13568 7 0 1 15161 1 15158 1 15161 2 3 15155 1 15161 3 15158 7 0 1 15161 4 3 15149 0 0 1 15173 1 15171 1 15173 2 2 15169 1 15173 3 15171 3 0 1 15173 4 2 9189 7 0 1 15187 1 15185 1 15187 2 2 15183 1 15187 3 15185 4 0 1 15187 4 2 12918 8 0 1 15193 1 15188 1 15193 2 5 15192 1 15193 3 15188 8 0 1 15193 4 5 9152 6 0 1 15199 1 15193 1 15199 2 6 15197 1 15199 3 15193 6 0 1 15199 4 6 14595 4 0 1 15217 1 15207 1 15217 2 10 15216 1 15217 3 15207 2 0 1 15217 4 10 8075 21 0 1 15227 1 15225 1 15227 2 2 15223 1 15227 3 15225 3 0 1 15227 4 2 13122 8 0 1 15233 1 15230 1 15233 2 3 15227 1 15233 3 15230 5 0 1 15233 4 3 14724 1 0 1 15241 1 15230 1 15241 2 11 15240 1 15241 3 15230 2 0 1 15241 4 11 12892 14 0 1 15259 1 15257 1 15259 2 2 15258 1 15259 3 15257 5 0 1 15259 4 2 9510 2 0 1 15263 1 15258 1 15263 2 5 15261 1 15263 3 15258 6 0 1 15263 4 5 9395 8 0 1 15269 1 15267 1 15269 2 2 15262 1 15269 3 15267 5 0 1 15269 4 2 14071 9 0 1 15271 1 15260 1 15271 2 11 15269 1 15271 3 15260 5 0 1 15271 4 11 10687 6 0 1 15277 1 15271 1 15277 2 6 15276 1 15277 3 15271 1 0 1 15277 4 6 10990 7 0 1 15287 1 15282 1 15287 2 5 15285 1 15287 3 15282 1 0 1 15287 4 5 10761 8 0 1 15289 1 15278 1 15289 2 11 15284 1 15289 3 15278 1 0 1 15289 4 11 13890 16 0 1 15299 1 15297 1 15299 2 2 15295 1 15299 3 15297 3 0 1 15299 4 2 12536 8 0 1 15307 1 15304 1 15307 2 3 15306 1 15307 3 15304 1 0 1 15307 4 3 14957 5 0 1 15313 1 15308 1 15313 2 5 15312 1 15313 3 15308 3 0 1 15313 4 5 15294 20 0 1 15319 1 15316 1 15319 2 3 15313 1 15319 3 15316 11 0 1 15319 4 3 13897 7 0 1 15329 1 15326 1 15329 2 3 15328 1 15329 3 15326 1 0 1 15329 4 3 9817 7 0 1 15331 1 15329 1 15331 2 2 15327 1 15331 3 15329 2 0 1 15331 4 2 8141 8 0 1 15349 1 15347 1 15349 2 2 15348 1 15349 3 15347 6 0 1 15349 4 2 10522 22 0 1 15359 1 15348 1 15359 2 11 15357 1 15359 3 15348 1 0 1 15359 4 11 11082 6 0 1 15361 1 15354 1 15361 2 7 15354 1 15361 3 15354 2 0 1 15361 4 7 8585 0 0 1 15373 1 15371 1 15373 2 2 15369 1 15373 3 15371 5 0 1 15373 4 2 11244 6 0 1 15377 1 15374 1 15377 2 3 15372 1 15377 3 15374 8 0 1 15377 4 3 13302 0 0 1 15383 1 15378 1 15383 2 5 15382 1 15383 3 15378 2 0 1 15383 4 5 7799 2 0 1 15391 1 15379 1 15391 2 12 15390 1 15391 3 15379 6 0 1 15391 4 12 8544 10 0 1 15401 1 15395 1 15401 2 6 15398 1 15401 3 15395 11 0 1 15401 4 6 13736 6 0 1 15413 1 15411 1 15413 2 2 15412 1 15413 3 15411 2 0 1 15413 4 2 9182 3 0 1 15427 1 15425 1 15427 2 2 15426 1 15427 3 15425 5 0 1 15427 4 2 12801 2 0 1 15439 1 15436 1 15439 2 3 15438 1 15439 3 15436 8 0 1 15439 4 3 8299 3 0 1 15443 1 15441 1 15443 2 2 15438 1 15443 3 15441 3 0 1 15443 4 2 13921 3 0 1 15451 1 15448 1 15451 2 3 15450 1 15451 3 15448 4 0 1 15451 4 3 8718 6 0 1 15461 1 15459 1 15461 2 2 15460 1 15461 3 15459 3 0 1 15461 4 2 15132 3 0 1 15467 1 15462 1 15467 2 5 15462 1 15467 3 15462 5 0 1 15467 4 5 13985 3 0 1 15473 1 15470 1 15473 2 3 15472 1 15473 3 15470 1 0 1 15473 4 3 9553 6 0 1 15493 1 15488 1 15493 2 5 15492 1 15493 3 15488 1 0 1 15493 4 5 13989 3 0 1 15497 1 15494 1 15497 2 3 15491 1 15497 3 15494 11 0 1 15497 4 3 15145 9 0 1 15511 1 15508 1 15511 2 3 15509 1 15511 3 15508 10 0 1 15511 4 3 15507 4 0 1 15527 1 15522 1 15527 2 5 15524 1 15527 3 15522 3 0 1 15527 4 5 12618 9 0 1 15541 1 15535 1 15541 2 6 15537 1 15541 3 15535 1 0 1 15541 4 6 13485 2 0 1 15551 1 15544 1 15551 2 7 15550 1 15551 3 15544 5 0 1 15551 4 7 8500 3 0 1 15559 1 15556 1 15559 2 3 15557 1 15559 3 15556 6 0 1 15559 4 3 12175 6 0 1 15569 1 15566 1 15569 2 3 15564 1 15569 3 15566 1 0 1 15569 4 3 9214 2 0 1 15581 1 15579 1 15581 2 2 15580 1 15581 3 15579 3 0 1 15581 4 2 15574 8 0 1 15583 1 15578 1 15583 2 5 15582 1 15583 3 15578 7 0 1 15583 4 5 12039 3 0 1 15601 1 15578 1 15601 2 23 15600 1 15601 3 15578 2 0 1 15601 4 23 9357 8 0 1 15607 1 15604 1 15607 2 3 15605 1 15607 3 15604 1 0 1 15607 4 3 10488 3 0 1 15619 1 15612 1 15619 2 7 15617 1 15619 3 15612 3 0 1 15619 4 7 15119 6 0 1 15629 1 15627 1 15629 2 2 15624 1 15629 3 15627 3 0 1 15629 4 2 13192 8 0 1 15641 1 15638 1 15641 2 3 15636 1 15641 3 15638 3 0 1 15641 4 3 10034 2 0 1 15643 1 15638 1 15643 2 5 15641 1 15643 3 15638 2 0 1 15643 4 5 10262 0 0 1 15647 1 15642 1 15647 2 5 15646 1 15647 3 15642 12 0 1 15647 4 5 10656 4 0 1 15649 1 15638 1 15649 2 11 15644 1 15649 3 15638 3 0 1 15649 4 11 13785 27 0 1 15661 1 15659 1 15661 2 2 15657 1 15661 3 15659 2 0 1 15661 4 2 10274 12 0 1 15667 1 15665 1 15667 2 2 15663 1 15667 3 15665 6 0 1 15667 4 2 8825 8 0 1 15671 1 15658 1 15671 2 13 15669 1 15671 3 15658 3 0 1 15671 4 13 11603 3 0 1 15679 1 15668 1 15679 2 11 15678 1 15679 3 15668 3 0 1 15679 4 11 14897 2 0 1 15683 1 15681 1 15683 2 2 15682 1 15683 3 15681 3 0 1 15683 4 2 14689 2 0 1 15727 1 15724 1 15727 2 3 15726 1 15727 3 15724 5 0 1 15727 4 3 13197 2 0 1 15731 1 15729 1 15731 2 2 15726 1 15731 3 15729 2 0 1 15731 4 2 10581 3 0 1 15733 1 15727 1 15733 2 6 15731 1 15733 3 15727 3 0 1 15733 4 6 13802 4 0 1 15737 1 15734 1 15737 2 3 15736 1 15737 3 15734 3 0 1 15737 4 3 12626 7 0 1 15739 1 15737 1 15739 2 2 15738 1 15739 3 15737 6 0 1 15739 4 2 12090 2 0 1 15749 1 15747 1 15749 2 2 15744 1 15749 3 15747 7 0 1 15749 4 2 13579 8 0 1 15761 1 15758 1 15761 2 3 15756 1 15761 3 15758 1 0 1 15761 4 3 8021 2 0 1 15767 1 15762 1 15767 2 5 15765 1 15767 3 15762 6 0 1 15767 4 5 15763 3 0 1 15773 1 15771 1 15773 2 2 15765 1 15773 3 15771 4 0 1 15773 4 2 11997 19 0 1 15787 1 15785 1 15787 2 2 15783 1 15787 3 15785 6 0 1 15787 4 2 8715 8 0 1 15791 1 15762 1 15791 2 29 15789 1 15791 3 15762 1 0 1 15791 4 29 13692 3 0 1 15797 1 15795 1 15797 2 2 15796 1 15797 3 15795 2 0 1 15797 4 2 11364 4 0 1 15803 1 15801 1 15803 2 2 15799 1 15803 3 15801 3 0 1 15803 4 2 13330 8 0 1 15809 1 15806 1 15809 2 3 15793 1 15809 3 15806 5 0 1 15809 4 3 11417 5 0 1 15817 1 15812 1 15817 2 5 15814 1 15817 3 15812 1 0 1 15817 4 5 15806 14 0 1 15823 1 15820 1 15823 2 3 15821 1 15823 3 15820 1 0 1 15823 4 3 11784 3 0 1 15859 1 15857 1 15859 2 2 15855 1 15859 3 15857 2 0 1 15859 4 2 14606 8 0 1 15877 1 15872 1 15877 2 5 15876 1 15877 3 15872 1 0 1 15877 4 5 12548 6 0 1 15881 1 15878 1 15881 2 3 15880 1 15881 3 15878 3 0 1 15881 4 3 14374 7 0 1 15887 1 15882 1 15887 2 5 15885 1 15887 3 15882 2 0 1 15887 4 5 12622 5 0 1 15889 1 15868 1 15889 2 21 15885 1 15889 3 15868 3 0 1 15889 4 21 8661 18 0 1 15901 1 15891 1 15901 2 10 15900 1 15901 3 15891 2 0 1 15901 4 10 8178 3 0 1 15907 1 15905 1 15907 2 2 15906 1 15907 3 15905 2 0 1 15907 4 2 14352 24 0 1 15913 1 15908 1 15913 2 5 15912 1 15913 3 15908 2 0 1 15913 4 5 10875 12 0 1 15919 1 15913 1 15919 2 6 15915 1 15919 3 15913 1 0 1 15919 4 6 15915 6 0 1 15923 1 15921 1 15923 2 2 15922 1 15923 3 15921 2 0 1 15923 4 2 11080 11 0 1 15937 1 15930 1 15937 2 7 15934 1 15937 3 15930 1 0 1 15937 4 7 9049 8 0 1 15959 1 15948 1 15959 2 11 15957 1 15959 3 15948 1 0 1 15959 4 11 12406 8 0 1 15971 1 15969 1 15971 2 2 15967 1 15971 3 15969 2 0 1 15971 4 2 13906 8 0 1 15973 1 15966 1 15973 2 7 15971 1 15973 3 15966 4 0 1 15973 4 7 15535 9 0 1 15991 1 15979 1 15991 2 12 15990 1 15991 3 15979 6 0 1 15991 4 12 15501 6 0 1 16001 1 15998 1 16001 2 3 16000 1 16001 3 15998 3 0 1 16001 4 3 11518 4 0 1 16007 1 16002 1 16007 2 5 16005 1 16007 3 16002 5 0 1 16007 4 5 10910 5 0 1 16033 1 16028 1 16033 2 5 16030 1 16033 3 16028 1 0 1 16033 4 5 10823 24 0 1 16057 1 16050 1 16057 2 7 16054 1 16057 3 16050 4 0 1 16057 4 7 8370 14 0 1 16061 1 16049 1 16061 2 12 16057 1 16061 3 16049 5 0 1 16061 4 12 12651 2 0 1 16063 1 16058 1 16063 2 5 16062 1 16063 3 16058 1 0 1 16063 4 5 10575 2 0 1 16067 1 16065 1 16067 2 2 16061 1 16067 3 16065 4 0 1 16067 4 2 10096 0 0 1 16069 1 16067 1 16069 2 2 16062 1 16069 3 16067 2 0 1 16069 4 2 15200 9 0 1 16073 1 16070 1 16073 2 3 16072 1 16073 3 16070 3 0 1 16073 4 3 11304 7 0 1 16087 1 16082 1 16087 2 5 16086 1 16087 3 16082 11 0 1 16087 4 5 14210 5 0 1 16091 1 16085 1 16091 2 6 16090 1 16091 3 16085 3 0 1 16091 4 6 15496 2 0 1 16097 1 16094 1 16097 2 3 16091 1 16097 3 16094 8 0 1 16097 4 3 13585 1 0 1 16103 1 16098 1 16103 2 5 16102 1 16103 3 16098 2 0 1 16103 4 5 8601 2 0 1 16111 1 16104 1 16111 2 7 16100 1 16111 3 16104 1 0 1 16111 4 7 11905 5 0 1 16127 1 16122 1 16127 2 5 16126 1 16127 3 16122 5 0 1 16127 4 5 9406 7 0 1 16139 1 16137 1 16139 2 2 16134 1 16139 3 16137 2 0 1 16139 4 2 13098 3 0 1 16141 1 16135 1 16141 2 6 16137 1 16141 3 16135 4 0 1 16141 4 6 12611 10 0 1 16183 1 16180 1 16183 2 3 16181 1 16183 3 16180 1 0 1 16183 4 3 13542 3 0 1 16187 1 16185 1 16187 2 2 16186 1 16187 3 16185 2 0 1 16187 4 2 14687 2 0 1 16189 1 16187 1 16189 2 2 16188 1 16189 3 16187 6 0 1 16189 4 2 12027 3 0 1 16193 1 16188 1 16193 2 5 16186 1 16193 3 16188 2 0 1 16193 4 5 11495 2 0 1 16217 1 16214 1 16217 2 3 16209 1 16217 3 16214 3 0 1 16217 4 3 9176 2 0 1 16223 1 16218 1 16223 2 5 16221 1 16223 3 16218 1 0 1 16223 4 5 16211 11 0 1 16229 1 16227 1 16229 2 2 16225 1 16229 3 16227 3 0 1 16229 4 2 10412 1 0 1 16231 1 16228 1 16231 2 3 16230 1 16231 3 16228 4 0 1 16231 4 3 11282 3 0 1 16249 1 16232 1 16249 2 17 16246 1 16249 3 16232 6 0 1 16249 4 17 9288 20 0 1 16253 1 16251 1 16253 2 2 16252 1 16253 3 16251 5 0 1 16253 4 2 11667 3 0 1 16267 1 16264 1 16267 2 3 16254 1 16267 3 16264 6 0 1 16267 4 3 9631 2 0 1 16273 1 16266 1 16273 2 7 16266 1 16273 3 16266 1 0 1 16273 4 7 9328 14 0 1 16301 1 16299 1 16301 2 2 16300 1 16301 3 16299 3 0 1 16301 4 2 9533 3 0 1 16319 1 16312 1 16319 2 7 16318 1 16319 3 16312 3 0 1 16319 4 7 14283 11 0 1 16333 1 16331 1 16333 2 2 16329 1 16333 3 16331 6 0 1 16333 4 2 13777 12 0 1 16339 1 16337 1 16339 2 2 16335 1 16339 3 16337 5 0 1 16339 4 2 9888 8 0 1 16349 1 16347 1 16349 2 2 16345 1 16349 3 16347 3 0 1 16349 4 2 15888 6 0 1 16361 1 16358 1 16361 2 3 16353 1 16361 3 16358 7 0 1 16361 4 3 15626 2 0 1 16363 1 16361 1 16363 2 2 16359 1 16363 3 16361 4 0 1 16363 4 2 13047 14 0 1 16369 1 16362 1 16369 2 7 16366 1 16369 3 16362 4 0 1 16369 4 7 11519 16 0 1 16381 1 16379 1 16381 2 2 16377 1 16381 3 16379 4 0 1 16381 4 2 15657 6 0 1 16411 1 16408 1 16411 2 3 16410 1 16411 3 16408 1 0 1 16411 4 3 8375 2 0 1 16417 1 16407 1 16417 2 10 16416 1 16417 3 16407 4 0 1 16417 4 10 13893 21 0 1 16421 1 16419 1 16421 2 2 16411 1 16421 3 16419 8 0 1 16421 4 2 11652 7 0 1 16427 1 16425 1 16427 2 2 16423 1 16427 3 16425 3 0 1 16427 4 2 15023 7 0 1 16433 1 16430 1 16433 2 3 16423 1 16433 3 16430 11 0 1 16433 4 3 14284 4 0 1 16447 1 16444 1 16447 2 3 16446 1 16447 3 16444 5 0 1 16447 4 3 13423 5 0 1 16451 1 16444 1 16451 2 7 16445 1 16451 3 16444 3 0 1 16451 4 7 16447 4 0 1 16453 1 16451 1 16453 2 2 16452 1 16453 3 16451 2 0 1 16453 4 2 15443 3 0 1 16477 1 16475 1 16477 2 2 16476 1 16477 3 16475 2 0 1 16477 4 2 16470 8 0 1 16481 1 16475 1 16481 2 6 16471 1 16481 3 16475 7 0 1 16481 4 6 13531 3 0 1 16487 1 16482 1 16487 2 5 16486 1 16487 3 16482 1 0 1 16487 4 5 14263 5 0 1 16493 1 16491 1 16493 2 2 16489 1 16493 3 16491 3 0 1 16493 4 2 8748 6 0 1 16519 1 16516 1 16519 2 3 16517 1 16519 3 16516 6 0 1 16519 4 3 12886 3 0 1 16529 1 16526 1 16529 2 3 16528 1 16529 3 16526 10 0 1 16529 4 3 16347 7 0 1 16547 1 16545 1 16547 2 2 16546 1 16547 3 16545 2 0 1 16547 4 2 10767 2 0 1 16553 1 16550 1 16553 2 3 16547 1 16553 3 16550 1 0 1 16553 4 3 12969 9 0 1 16561 1 16554 1 16561 2 7 16558 1 16561 3 16554 1 0 1 16561 4 7 9382 14 0 1 16567 1 16564 1 16567 2 3 16565 1 16567 3 16564 4 0 1 16567 4 3 10444 3 0 1 16573 1 16571 1 16573 2 2 16569 1 16573 3 16571 7 0 1 16573 4 2 9569 12 0 1 16603 1 16601 1 16603 2 2 16602 1 16603 3 16601 6 0 1 16603 4 2 15788 16 0 1 16607 1 16602 1 16607 2 5 16605 1 16607 3 16602 1 0 1 16607 4 5 15925 10 0 1 16619 1 16617 1 16619 2 2 16615 1 16619 3 16617 2 0 1 16619 4 2 15056 7 0 1 16631 1 16612 1 16631 2 19 16630 1 16631 3 16612 1 0 1 16631 4 19 10223 8 0 1 16633 1 16618 1 16633 2 15 16632 1 16633 3 16618 4 0 1 16633 4 15 9934 14 0 1 16649 1 16646 1 16649 2 3 16643 1 16649 3 16646 6 0 1 16649 4 3 16637 0 0 1 16651 1 16649 1 16651 2 2 16650 1 16651 3 16649 4 0 1 16651 4 2 11256 12 0 1 16657 1 16652 1 16657 2 5 16656 1 16657 3 16652 13 0 1 16657 4 5 13959 6 0 1 16661 1 16651 1 16661 2 10 16656 1 16661 3 16651 7 0 1 16661 4 10 12016 7 0 1 16673 1 16670 1 16673 2 3 16672 1 16673 3 16670 1 0 1 16673 4 3 8824 7 0 1 16691 1 16685 1 16691 2 6 16689 1 16691 3 16685 1 0 1 16691 4 6 16681 7 0 1 16693 1 16691 1 16693 2 2 16692 1 16693 3 16691 6 0 1 16693 4 2 8491 3 0 1 16699 1 16696 1 16699 2 3 16694 1 16699 3 16696 10 0 1 16699 4 3 16410 3 0 1 16703 1 16698 1 16703 2 5 16702 1 16703 3 16698 8 0 1 16703 4 5 8813 2 0 1 16729 1 16716 1 16729 2 13 16726 1 16729 3 16716 2 0 1 16729 4 13 12734 16 0 1 16741 1 16735 1 16741 2 6 16740 1 16741 3 16735 1 0 1 16741 4 6 8876 11 0 1 16747 1 16745 1 16747 2 2 16746 1 16747 3 16745 2 0 1 16747 4 2 16430 2 0 1 16759 1 16756 1 16759 2 3 16754 1 16759 3 16756 4 0 1 16759 4 3 13520 6 0 1 16763 1 16761 1 16763 2 2 16759 1 16763 3 16761 2 0 1 16763 4 2 13241 21 0 1 16787 1 16785 1 16787 2 2 16783 1 16787 3 16785 3 0 1 16787 4 2 10145 13 0 1 16811 1 16804 1 16811 2 7 16810 1 16811 3 16804 2 0 1 16811 4 7 14794 2 0 1 16823 1 16818 1 16823 2 5 16821 1 16823 3 16818 3 0 1 16823 4 5 11944 8 0 1 16829 1 16827 1 16829 2 2 16825 1 16829 3 16827 2 0 1 16829 4 2 13058 12 0 1 16831 1 16825 1 16831 2 6 16829 1 16831 3 16825 3 0 1 16831 4 6 14569 3 0 1 16843 1 16841 1 16843 2 2 16839 1 16843 3 16841 6 0 1 16843 4 2 11857 13 0 1 16871 1 16854 1 16871 2 17 16869 1 16871 3 16854 2 0 1 16871 4 17 16863 3 0 1 16879 1 16876 1 16879 2 3 16877 1 16879 3 16876 4 0 1 16879 4 3 9540 6 0 1 16883 1 16881 1 16883 2 2 16875 1 16883 3 16881 15 0 1 16883 4 2 8556 0 0 1 16889 1 16886 1 16889 2 3 16882 1 16889 3 16886 7 0 1 16889 4 3 15970 4 0 1 16901 1 16899 1 16901 2 2 16900 1 16901 3 16899 3 0 1 16901 4 2 16894 8 0 1 16903 1 16900 1 16903 2 3 16902 1 16903 3 16900 3 0 1 16903 4 3 12591 5 0 1 16921 1 16904 1 16921 2 17 16918 1 16921 3 16904 3 0 1 16921 4 17 16162 16 0 1 16927 1 16921 1 16927 2 6 16926 1 16927 3 16921 1 0 1 16927 4 6 9845 2 0 1 16931 1 16929 1 16931 2 2 16930 1 16931 3 16929 3 0 1 16931 4 2 13481 2 0 1 16937 1 16934 1 16937 2 3 16936 1 16937 3 16934 1 0 1 16937 4 3 9810 7 0 1 16943 1 16938 1 16943 2 5 16942 1 16943 3 16938 7 0 1 16943 4 5 9020 7 0 1 16963 1 16961 1 16963 2 2 16959 1 16963 3 16961 5 0 1 16963 4 2 14815 8 0 1 16979 1 16977 1 16979 2 2 16973 1 16979 3 16977 2 0 1 16979 4 2 10100 0 0 1 16981 1 16979 1 16981 2 2 16980 1 16981 3 16979 6 0 1 16981 4 2 13100 3 0 1 16987 1 16984 1 16987 2 3 16976 1 16987 3 16984 1 0 1 16987 4 3 13805 3 0 1 16993 1 16983 1 16993 2 10 16992 1 16993 3 16983 5 0 1 16993 4 10 15879 14 0 1 17011 1 17009 1 17011 2 2 17007 1 17011 3 17009 2 0 1 17011 4 2 13795 8 0 1 17021 1 17019 1 17021 2 2 17013 1 17021 3 17019 8 0 1 17021 4 2 13081 0 0 1 17027 1 17025 1 17027 2 2 17026 1 17027 3 17025 2 0 1 17027 4 2 14040 4 0 1 17029 1 17019 1 17029 2 10 17025 1 17029 3 17019 6 0 1 17029 4 10 17017 10 0 1 17033 1 17030 1 17033 2 3 17027 1 17033 3 17030 5 0 1 17033 4 3 14449 1 0 1 17041 1 17034 1 17041 2 7 17034 1 17041 3 17034 1 0 1 17041 4 7 16291 0 0 1 17047 1 17044 1 17047 2 3 17046 1 17047 3 17044 1 0 1 17047 4 3 11227 2 0 1 17053 1 17051 1 17053 2 2 17049 1 17053 3 17051 4 0 1 17053 4 2 14289 10 0 1 17077 1 17075 1 17077 2 2 17073 1 17077 3 17075 6 0 1 17077 4 2 8890 36 0 1 17093 1 17091 1 17093 2 2 17089 1 17093 3 17091 2 0 1 17093 4 2 12893 1 0 1 17099 1 17097 1 17099 2 2 17098 1 17099 3 17097 3 0 1 17099 4 2 13487 2 0 1 17107 1 17104 1 17107 2 3 17106 1 17107 3 17104 5 0 1 17107 4 3 16922 2 0 1 17117 1 17114 1 17117 2 3 17115 1 17117 3 17114 4 0 1 17117 4 3 14382 14 0 1 17123 1 17121 1 17123 2 2 17119 1 17123 3 17121 3 0 1 17123 4 2 14197 7 0 1 17137 1 17132 1 17137 2 5 17136 1 17137 3 17132 1 0 1 17137 4 5 11563 6 0 1 17159 1 17152 1 17159 2 7 17158 1 17159 3 17152 1 0 1 17159 4 7 16866 3 0 1 17167 1 17164 1 17167 2 3 17166 1 17167 3 17164 11 0 1 17167 4 3 10995 2 0 1 17183 1 17178 1 17183 2 5 17178 1 17183 3 17178 1 0 1 17183 4 5 11186 7 0 1 17189 1 17187 1 17189 2 2 17177 1 17189 3 17187 4 0 1 17189 4 2 8834 1 0 1 17191 1 17188 1 17191 2 3 17189 1 17191 3 17188 4 0 1 17191 4 3 11345 3 0 1 17203 1 17201 1 17203 2 2 17199 1 17203 3 17201 5 0 1 17203 4 2 16333 8 0 1 17207 1 17202 1 17207 2 5 17205 1 17207 3 17202 3 0 1 17207 4 5 17203 3 0 1 17209 1 17195 1 17209 2 14 17202 1 17209 3 17195 5 0 1 17209 4 14 8751 0 0 1 17231 1 17218 1 17231 2 13 17227 1 17231 3 17218 3 0 1 17231 4 13 9900 6 0 1 17239 1 17233 1 17239 2 6 17237 1 17239 3 17233 3 0 1 17239 4 6 9995 3 0 1 17257 1 17252 1 17257 2 5 17252 1 17257 3 17252 1 0 1 17257 4 5 12127 10 0 1 17291 1 17285 1 17291 2 6 17288 1 17291 3 17285 1 0 1 17291 4 6 9115 1 0 1 17293 1 17286 1 17293 2 7 17291 1 17293 3 17286 3 0 1 17293 4 7 13974 7 0 1 17299 1 17297 1 17299 2 2 17295 1 17299 3 17297 6 0 1 17299 4 2 16555 8 0 1 17317 1 17315 1 17317 2 2 17316 1 17317 3 17315 2 0 1 17317 4 2 14695 6 0 1 17321 1 17318 1 17321 2 3 17316 1 17321 3 17318 6 0 1 17321 4 3 11113 2 0 1 17327 1 17322 1 17327 2 5 17324 1 17327 3 17322 2 0 1 17327 4 5 12024 11 0 1 17333 1 17331 1 17333 2 2 17329 1 17333 3 17331 3 0 1 17333 4 2 15647 6 0 1 17341 1 17335 1 17341 2 6 17340 1 17341 3 17335 4 0 1 17341 4 6 16573 11 0 1 17351 1 17340 1 17351 2 11 17350 1 17351 3 17340 2 0 1 17351 4 11 8850 3 0 1 17359 1 17356 1 17359 2 3 17357 1 17359 3 17356 3 0 1 17359 4 3 14524 3 0 1 17377 1 17370 1 17377 2 7 17370 1 17377 3 17370 2 0 1 17377 4 7 13357 17 0 1 17383 1 17378 1 17383 2 5 17381 1 17383 3 17378 6 0 1 17383 4 5 17379 3 0 1 17387 1 17385 1 17387 2 2 17380 1 17387 3 17385 4 0 1 17387 4 2 11427 8 0 1 17389 1 17387 1 17389 2 2 17385 1 17389 3 17387 6 0 1 17389 4 2 14053 12 0 1 17393 1 17390 1 17393 2 3 17387 1 17393 3 17390 5 0 1 17393 4 3 15367 9 0 1 17401 1 17390 1 17401 2 11 17400 1 17401 3 17390 2 0 1 17401 4 11 8849 8 0 1 17417 1 17414 1 17417 2 3 17408 1 17417 3 17414 5 0 1 17417 4 3 12851 6 0 1 17419 1 17416 1 17419 2 3 17418 1 17419 3 17416 3 0 1 17419 4 3 14679 2 0 1 17431 1 17428 1 17431 2 3 17430 1 17431 3 17428 1 0 1 17431 4 3 16720 3 0 1 17443 1 17441 1 17443 2 2 17439 1 17443 3 17441 6 0 1 17443 4 2 9848 1 0 1 17449 1 17435 1 17449 2 14 17444 1 17449 3 17435 4 0 1 17449 4 14 15512 19 0 1 17467 1 17464 1 17467 2 3 17466 1 17467 3 17464 12 0 1 17467 4 3 13632 2 0 1 17471 1 17460 1 17471 2 11 17468 1 17471 3 17460 2 0 1 17471 4 11 9740 5 0 1 17477 1 17475 1 17477 2 2 17476 1 17477 3 17475 3 0 1 17477 4 2 10983 6 0 1 17483 1 17481 1 17483 2 2 17478 1 17483 3 17481 5 0 1 17483 4 2 16596 3 0 1 17489 1 17486 1 17489 2 3 17480 1 17489 3 17486 4 0 1 17489 4 3 12697 6 0 1 17491 1 17488 1 17491 2 3 17486 1 17491 3 17488 4 0 1 17491 4 3 11158 3 0 1 17497 1 17492 1 17497 2 5 17494 1 17497 3 17492 2 0 1 17497 4 5 11505 23 0 1 17509 1 17507 1 17509 2 2 17505 1 17509 3 17507 2 0 1 17509 4 2 14794 12 0 1 17519 1 17506 1 17519 2 13 17517 1 17519 3 17506 2 0 1 17519 4 13 16641 3 0 1 17539 1 17536 1 17539 2 3 17531 1 17539 3 17536 5 0 1 17539 4 3 12655 0 0 1 17551 1 17548 1 17551 2 3 17550 1 17551 3 17548 3 0 1 17551 4 3 10092 2 0 1 17569 1 17558 1 17569 2 11 17564 1 17569 3 17558 3 0 1 17569 4 11 11572 19 0 1 17573 1 17571 1 17573 2 2 17569 1 17573 3 17571 3 0 1 17573 4 2 15339 1 0 1 17579 1 17577 1 17579 2 2 17575 1 17579 3 17577 4 0 1 17579 4 2 12349 7 0 1 17581 1 17571 1 17581 2 10 17580 1 17581 3 17571 13 0 1 17581 4 10 14731 3 0 1 17597 1 17595 1 17597 2 2 17596 1 17597 3 17595 2 0 1 17597 4 2 13272 3 0 1 17599 1 17593 1 17599 2 6 17597 1 17599 3 17593 1 0 1 17599 4 6 11910 10 0 1 17609 1 17606 1 17609 2 3 17603 1 17609 3 17606 1 0 1 17609 4 3 17597 0 0 1 17623 1 17620 1 17623 2 3 17621 1 17623 3 17620 1 0 1 17623 4 3 10124 3 0 1 17627 1 17625 1 17627 2 2 17621 1 17627 3 17625 4 0 1 17627 4 2 9640 4 0 1 17657 1 17654 1 17657 2 3 17648 1 17657 3 17654 5 0 1 17657 4 3 16553 2 0 1 17659 1 17656 1 17659 2 3 17643 1 17659 3 17656 1 0 1 17659 4 3 9493 3 0 1 17669 1 17667 1 17669 2 2 17665 1 17669 3 17667 3 0 1 17669 4 2 13132 6 0 1 17681 1 17678 1 17681 2 3 17675 1 17681 3 17678 1 0 1 17681 4 3 17669 0 0 1 17683 1 17678 1 17683 2 5 17682 1 17683 3 17678 7 0 1 17683 4 5 10266 5 0 1 17707 1 17704 1 17707 2 3 17706 1 17707 3 17704 9 0 1 17707 4 3 9502 2 0 1 17713 1 17706 1 17713 2 7 17706 1 17713 3 17706 1 0 1 17713 4 7 10800 12 0 1 17729 1 17726 1 17729 2 3 17723 1 17729 3 17726 14 0 1 17729 4 3 17717 0 0 1 17737 1 17730 1 17737 2 7 17730 1 17737 3 17730 4 0 1 17737 4 7 12831 20 0 1 17747 1 17745 1 17747 2 2 17743 1 17747 3 17745 3 0 1 17747 4 2 10694 8 0 1 17749 1 17747 1 17749 2 2 17740 1 17749 3 17747 2 0 1 17749 4 2 13430 15 0 1 17761 1 17742 1 17761 2 19 17748 1 17761 3 17742 1 0 1 17761 4 19 14869 32 0 1 17783 1 17778 1 17783 2 5 17778 1 17783 3 17778 5 0 1 17783 4 5 9981 6 0 1 17789 1 17787 1 17789 2 2 17784 1 17789 3 17787 3 0 1 17789 4 2 10357 18 0 1 17791 1 17788 1 17791 2 3 17789 1 17791 3 17788 4 0 1 17791 4 3 12096 6 0 1 17807 1 17802 1 17807 2 5 17802 1 17807 3 17802 1 0 1 17807 4 5 17454 13 0 1 17827 1 17825 1 17827 2 2 17826 1 17827 3 17825 2 0 1 17827 4 2 11229 11 0 1 17837 1 17835 1 17837 2 2 17833 1 17837 3 17835 3 0 1 17837 4 2 14362 7 0 1 17839 1 17833 1 17839 2 6 17837 1 17839 3 17833 3 0 1 17839 4 6 17396 3 0 1 17851 1 17849 1 17851 2 2 17847 1 17851 3 17849 2 0 1 17851 4 2 13825 8 0 1 17863 1 17857 1 17863 2 6 17862 1 17863 3 17857 1 0 1 17863 4 6 16183 3 0 1 17881 1 17874 1 17881 2 7 17878 1 17881 3 17874 1 0 1 17881 4 7 9480 29 0 1 17891 1 17889 1 17891 2 2 17887 1 17891 3 17889 3 0 1 17891 4 2 12191 11 0 1 17903 1 17898 1 17903 2 5 17898 1 17903 3 17898 13 0 1 17903 4 5 17549 6 0 1 17909 1 17907 1 17909 2 2 17903 1 17909 3 17907 3 0 1 17909 4 2 12859 3 0 1 17911 1 17908 1 17911 2 3 17909 1 17911 3 17908 3 0 1 17911 4 3 9990 3 0 1 17921 1 17918 1 17921 2 3 17914 1 17921 3 17918 8 0 1 17921 4 3 15904 1 0 1 17923 1 17921 1 17923 2 2 17922 1 17923 3 17921 2 0 1 17923 4 2 12671 2 0 1 17929 1 17918 1 17929 2 11 17915 1 17929 3 17918 3 0 1 17929 4 11 15684 1 0 1 17939 1 17937 1 17939 2 2 17932 1 17939 3 17937 5 0 1 17939 4 2 9366 1 0 1 17957 1 17955 1 17957 2 2 17952 1 17957 3 17955 5 0 1 17957 4 2 16029 0 0 1 17959 1 17953 1 17959 2 6 17957 1 17959 3 17953 14 0 1 17959 4 6 15994 4 0 1 17971 1 17968 1 17971 2 3 17970 1 17971 3 17968 7 0 1 17971 4 3 10615 6 0 1 17977 1 17972 1 17977 2 5 17976 1 17977 3 17972 16 0 1 17977 4 5 11843 6 0 1 17981 1 17979 1 17981 2 2 17980 1 17981 3 17979 12 0 1 17981 4 2 14248 3 0 1 17987 1 17982 1 17987 2 5 17984 1 17987 3 17982 2 0 1 17987 4 5 14070 1 0 1 17989 1 17987 1 17989 2 2 17988 1 17989 3 17987 6 0 1 17989 4 2 14690 9 0 1 18013 1 18011 1 18013 2 2 18009 1 18013 3 18011 6 0 1 18013 4 2 15982 6 0 1 18041 1 18038 1 18041 2 3 18035 1 18041 3 18038 4 0 1 18041 4 3 18029 0 0 1 18043 1 18041 1 18043 2 2 18039 1 18043 3 18041 4 0 1 18043 4 2 13772 8 0 1 18047 1 18042 1 18047 2 5 18044 1 18047 3 18042 6 0 1 18047 4 5 11073 4 0 1 18049 1 18036 1 18049 2 13 18048 1 18049 3 18036 3 0 1 18049 4 13 15234 15 0 1 18059 1 18057 1 18059 2 2 18054 1 18059 3 18057 10 0 1 18059 4 2 11939 3 0 1 18061 1 18055 1 18061 2 6 18057 1 18061 3 18055 1 0 1 18061 4 6 9650 2 0 1 18077 1 18075 1 18077 2 2 18071 1 18077 3 18075 5 0 1 18077 4 2 12604 1 0 1 18089 1 18086 1 18089 2 3 18084 1 18089 3 18086 3 0 1 18089 4 3 9195 2 0 1 18097 1 18092 1 18097 2 5 18094 1 18097 3 18092 3 0 1 18097 4 5 14769 23 0 1 18119 1 18102 1 18119 2 17 18117 1 18119 3 18102 2 0 1 18119 4 17 18111 3 0 1 18121 1 18098 1 18121 2 23 18120 1 18121 3 18098 3 0 1 18121 4 23 17654 8 0 1 18127 1 18124 1 18127 2 3 18126 1 18127 3 18124 6 0 1 18127 4 3 18116 12 0 1 18131 1 18124 1 18131 2 7 18127 1 18131 3 18124 2 0 1 18131 4 7 12288 2 0 1 18133 1 18128 1 18133 2 5 18128 1 18133 3 18128 6 0 1 18133 4 5 13395 7 0 1 18143 1 18138 1 18143 2 5 18135 1 18143 3 18138 5 0 1 18143 4 5 15942 3 0 1 18149 1 18147 1 18149 2 2 18148 1 18149 3 18147 3 0 1 18149 4 2 16538 3 0 1 18169 1 18158 1 18169 2 11 18154 1 18169 3 18158 3 0 1 18169 4 11 17818 37 0 1 18181 1 18179 1 18181 2 2 18177 1 18181 3 18179 6 0 1 18181 4 2 9768 12 0 1 18191 1 18162 1 18191 2 29 18190 1 18191 3 18162 6 0 1 18191 4 29 15236 4 0 1 18199 1 18188 1 18199 2 11 18197 1 18199 3 18188 3 0 1 18199 4 11 13365 3 0 1 18211 1 18204 1 18211 2 7 18205 1 18211 3 18204 1 0 1 18211 4 7 11326 7 0 1 18217 1 18210 1 18217 2 7 18214 1 18217 3 18210 3 0 1 18217 4 7 11839 20 0 1 18223 1 18220 1 18223 2 3 18222 1 18223 3 18220 4 0 1 18223 4 3 16672 16 0 1 18229 1 18227 1 18229 2 2 18225 1 18229 3 18227 4 0 1 18229 4 2 17959 6 0 1 18233 1 18230 1 18233 2 3 18232 1 18233 3 18230 1 0 1 18233 4 3 9739 6 0 1 18251 1 18249 1 18251 2 2 18246 1 18251 3 18249 2 0 1 18251 4 2 11575 3 0 1 18253 1 18248 1 18253 2 5 18252 1 18253 3 18248 17 0 1 18253 4 5 11906 3 0 1 18257 1 18252 1 18257 2 5 18249 1 18257 3 18252 2 0 1 18257 4 5 16485 13 0 1 18269 1 18267 1 18269 2 2 18265 1 18269 3 18267 3 0 1 18269 4 2 9937 1 0 1 18287 1 18282 1 18287 2 5 18282 1 18287 3 18282 1 0 1 18287 4 5 13947 7 0 1 18289 1 18276 1 18289 2 13 18280 1 18289 3 18276 3 0 1 18289 4 13 9706 16 0 1 18301 1 18295 1 18301 2 6 18297 1 18301 3 18295 1 0 1 18301 4 6 18297 6 0 1 18307 1 18296 1 18307 2 11 18306 1 18307 3 18296 7 0 1 18307 4 11 16831 2 0 1 18311 1 18298 1 18311 2 13 18307 1 18311 3 18298 2 0 1 18311 4 13 14877 6 0 1 18313 1 18303 1 18313 2 10 18310 1 18313 3 18303 3 0 1 18313 4 10 17080 13 0 1 18329 1 18326 1 18329 2 3 18323 1 18329 3 18326 4 0 1 18329 4 3 18317 0 0 1 18341 1 18338 1 18341 2 3 18336 1 18341 3 18338 3 0 1 18341 4 3 14231 2 0 1 18353 1 18350 1 18353 2 3 18341 1 18353 3 18350 6 0 1 18353 4 3 16535 0 0 1 18367 1 18364 1 18367 2 3 18366 1 18367 3 18364 1 0 1 18367 4 3 9844 5 0 1 18371 1 18360 1 18371 2 11 18368 1 18371 3 18360 4 0 1 18371 4 11 16148 1 0 1 18379 1 18376 1 18379 2 3 18368 1 18379 3 18376 1 0 1 18379 4 3 16019 4 0 1 18397 1 18391 1 18397 2 6 18396 1 18397 3 18391 2 0 1 18397 4 6 12477 6 0 1 18401 1 18398 1 18401 2 3 18396 1 18401 3 18398 3 0 1 18401 4 3 12715 2 0 1 18413 1 18411 1 18413 2 2 18409 1 18413 3 18411 3 0 1 18413 4 2 13627 1 0 1 18427 1 18425 1 18427 2 2 18426 1 18427 3 18425 6 0 1 18427 4 2 9861 7 0 1 18433 1 18428 1 18433 2 5 18432 1 18433 3 18428 5 0 1 18433 4 5 15443 6 0 1 18439 1 18436 1 18439 2 3 18437 1 18439 3 18436 5 0 1 18439 4 3 18435 4 0 1 18443 1 18441 1 18443 2 2 18442 1 18443 3 18441 2 0 1 18443 4 2 14970 2 0 1 18451 1 18448 1 18451 2 3 18440 1 18451 3 18448 3 0 1 18451 4 3 17314 0 0 1 18457 1 18452 1 18457 2 5 18456 1 18457 3 18452 2 0 1 18457 4 5 10609 6 0 1 18461 1 18459 1 18461 2 2 18453 1 18461 3 18459 7 0 1 18461 4 2 17838 0 0 1 18481 1 18468 1 18481 2 13 18478 1 18481 3 18468 4 0 1 18481 4 13 15261 16 0 1 18493 1 18491 1 18493 2 2 18492 1 18493 3 18491 4 0 1 18493 4 2 11729 3 0 1 18503 1 18498 1 18503 2 5 18501 1 18503 3 18498 5 0 1 18503 4 5 14477 5 0 1 18517 1 18511 1 18517 2 6 18515 1 18517 3 18511 4 0 1 18517 4 6 12181 4 0 1 18521 1 18518 1 18521 2 3 18515 1 18521 3 18518 6 0 1 18521 4 3 18509 0 0 1 18523 1 18520 1 18523 2 3 18522 1 18523 3 18520 6 0 1 18523 4 3 13398 2 0 1 18539 1 18533 1 18539 2 6 18537 1 18539 3 18533 4 0 1 18539 4 6 15012 5 0 1 18541 1 18535 1 18541 2 6 18537 1 18541 3 18535 2 0 1 18541 4 6 10978 2 0 1 18553 1 18548 1 18553 2 5 18550 1 18553 3 18548 7 0 1 18553 4 5 9961 10 0 1 18583 1 18580 1 18583 2 3 18581 1 18583 3 18580 4 0 1 18583 4 3 18575 10 0 1 18587 1 18585 1 18587 2 2 18583 1 18587 3 18585 3 0 1 18587 4 2 13034 7 0 1 18593 1 18590 1 18593 2 3 18587 1 18593 3 18590 12 0 1 18593 4 3 16589 9 0 1 18617 1 18614 1 18617 2 3 18610 1 18617 3 18614 6 0 1 18617 4 3 12761 1 0 1 18637 1 18635 1 18637 2 2 18636 1 18637 3 18635 2 0 1 18637 4 2 18630 8 0 1 18661 1 18651 1 18661 2 10 18660 1 18661 3 18651 2 0 1 18661 4 10 13839 3 0 1 18671 1 18664 1 18671 2 7 18670 1 18671 3 18664 1 0 1 18671 4 7 10586 3 0 1 18679 1 18673 1 18679 2 6 18677 1 18679 3 18673 3 0 1 18679 4 6 17207 3 0 1 18691 1 18688 1 18691 2 3 18690 1 18691 3 18688 3 0 1 18691 4 3 16159 2 0 1 18701 1 18699 1 18701 2 2 18693 1 18701 3 18699 2 0 1 18701 4 2 10844 0 0 1 18713 1 18710 1 18713 2 3 18712 1 18713 3 18710 10 0 1 18713 4 3 17106 6 0 1 18719 1 18712 1 18719 2 7 18717 1 18719 3 18712 2 0 1 18719 4 7 11067 5 0 1 18731 1 18729 1 18731 2 2 18727 1 18731 3 18729 3 0 1 18731 4 2 18494 7 0 1 18743 1 18738 1 18743 2 5 18738 1 18743 3 18738 1 0 1 18743 4 5 16527 7 0 1 18749 1 18747 1 18749 2 2 18742 1 18749 3 18747 5 0 1 18749 4 2 17743 17 0 1 18757 1 18755 1 18757 2 2 18753 1 18757 3 18755 6 0 1 18757 4 2 10613 6 0 1 18773 1 18771 1 18773 2 2 18768 1 18773 3 18771 3 0 1 18773 4 2 10974 12 0 1 18787 1 18785 1 18787 2 2 18786 1 18787 3 18785 2 0 1 18787 4 2 16032 12 0 1 18793 1 18788 1 18793 2 5 18792 1 18793 3 18788 13 0 1 18793 4 5 14561 6 0 1 18797 1 18794 1 18797 2 3 18795 1 18797 3 18794 1 0 1 18797 4 3 18793 4 0 1 18803 1 18798 1 18803 2 5 18802 1 18803 3 18798 2 0 1 18803 4 5 16948 5 0 1 18839 1 18832 1 18839 2 7 18838 1 18839 3 18832 1 0 1 18839 4 7 14835 2 0 1 18859 1 18857 1 18859 2 2 18855 1 18859 3 18857 2 0 1 18859 4 2 10191 8 0 1 18869 1 18867 1 18869 2 2 18861 1 18869 3 18867 2 0 1 18869 4 2 15316 0 0 1 18899 1 18897 1 18899 2 2 18895 1 18899 3 18897 3 0 1 18899 4 2 15825 7 0 1 18911 1 18897 1 18911 2 14 18905 1 18911 3 18897 7 0 1 18911 4 14 17681 7 0 1 18913 1 18906 1 18913 2 7 18910 1 18913 3 18906 1 0 1 18913 4 7 10361 10 0 1 18917 1 18915 1 18917 2 2 18916 1 18917 3 18915 2 0 1 18917 4 2 16591 3 0 1 18919 1 18916 1 18919 2 3 18918 1 18919 3 18916 3 0 1 18919 4 3 16302 2 0 1 18947 1 18945 1 18947 2 2 18946 1 18947 3 18945 2 0 1 18947 4 2 15044 4 0 1 18959 1 18946 1 18959 2 13 18958 1 18959 3 18946 3 0 1 18959 4 13 11516 2 0 1 18973 1 18971 1 18973 2 2 18972 1 18973 3 18971 4 0 1 18973 4 2 15546 7 0 1 18979 1 18977 1 18979 2 2 18975 1 18979 3 18977 2 0 1 18979 4 2 10202 8 0 1 19001 1 18998 1 19001 2 3 18995 1 19001 3 18998 3 0 1 19001 4 3 18989 0 0 1 19009 1 18986 1 19009 2 23 19006 1 19009 3 18986 1 0 1 19009 4 23 15317 20 0 1 19013 1 19011 1 19013 2 2 19008 1 19013 3 19011 5 0 1 19013 4 2 10213 2 0 1 19031 1 19020 1 19031 2 11 19029 1 19031 3 19020 2 0 1 19031 4 11 16760 3 0 1 19037 1 19035 1 19037 2 2 19033 1 19037 3 19035 3 0 1 19037 4 2 16206 6 0 1 19051 1 19049 1 19051 2 2 19047 1 19051 3 19049 2 0 1 19051 4 2 18812 8 0 1 19069 1 19067 1 19069 2 2 19064 1 19069 3 19067 2 0 1 19069 4 2 10991 7 0 1 19073 1 19070 1 19073 2 3 19068 1 19073 3 19070 3 0 1 19073 4 3 15571 0 0 1 19079 1 19072 1 19079 2 7 19077 1 19079 3 19072 5 0 1 19079 4 7 10494 4 0 1 19081 1 19064 1 19081 2 17 19080 1 19081 3 19064 3 0 1 19081 4 17 18602 8 0 1 19087 1 19068 1 19087 2 19 19085 1 19087 3 19068 1 0 1 19087 4 19 15189 18 0 1 19121 1 19115 1 19121 2 6 19118 1 19121 3 19115 4 0 1 19121 4 6 12575 0 0 1 19139 1 19137 1 19139 2 2 19135 1 19139 3 19137 3 0 1 19139 4 2 18536 8 0 1 19141 1 19139 1 19141 2 2 19140 1 19141 3 19139 4 0 1 19141 4 2 9820 7 0 1 19157 1 19155 1 19157 2 2 19156 1 19157 3 19155 3 0 1 19157 4 2 12944 3 0 1 19163 1 19161 1 19163 2 2 19159 1 19163 3 19161 3 0 1 19163 4 2 16983 7 0 1 19181 1 19179 1 19181 2 2 19177 1 19181 3 19179 3 0 1 19181 4 2 13168 6 0 1 19183 1 19180 1 19183 2 3 19182 1 19183 3 19180 1 0 1 19183 4 3 10706 2 0 1 19207 1 19202 1 19207 2 5 19205 1 19207 3 19202 3 0 1 19207 4 5 17416 9 0 1 19211 1 19205 1 19211 2 6 19208 1 19211 3 19205 3 0 1 19211 4 6 17571 7 0 1 19213 1 19208 1 19213 2 5 19210 1 19213 3 19208 1 0 1 19213 4 5 13122 1 0 1 19219 1 19217 1 19219 2 2 19210 1 19219 3 19217 5 0 1 19219 4 2 15652 2 0 1 19231 1 19225 1 19231 2 6 19229 1 19231 3 19225 2 0 1 19231 4 6 13006 10 0 1 19237 1 19235 1 19237 2 2 19233 1 19237 3 19235 4 0 1 19237 4 2 10465 6 0 1 19249 1 19242 1 19249 2 7 19242 1 19249 3 19242 1 0 1 19249 4 7 10637 0 0 1 19259 1 19257 1 19259 2 2 19255 1 19259 3 19257 3 0 1 19259 4 2 18438 7 0 1 19267 1 19264 1 19267 2 3 19266 1 19267 3 19264 1 0 1 19267 4 3 11639 5 0 1 19273 1 19268 1 19273 2 5 19268 1 19273 3 19268 5 0 1 19273 4 5 13201 18 0 1 19289 1 19286 1 19289 2 3 19276 1 19289 3 19286 5 0 1 19289 4 3 14941 1 0 1 19301 1 19299 1 19301 2 2 19297 1 19301 3 19299 2 0 1 19301 4 2 16927 6 0 1 19309 1 19303 1 19309 2 6 19305 1 19309 3 19303 4 0 1 19309 4 6 18808 2 0 1 19319 1 19308 1 19319 2 11 19318 1 19319 3 19308 4 0 1 19319 4 11 18667 3 0 1 19333 1 19331 1 19333 2 2 19332 1 19333 3 19331 4 0 1 19333 4 2 9822 3 0 1 19373 1 19371 1 19373 2 2 19358 1 19373 3 19371 4 0 1 19373 4 2 13948 1 0 1 19379 1 19377 1 19379 2 2 19378 1 19379 3 19377 3 0 1 19379 4 2 10801 4 0 1 19381 1 19374 1 19381 2 7 19379 1 19381 3 19374 2 0 1 19381 4 7 12050 4 0 1 19387 1 19385 1 19387 2 2 19383 1 19387 3 19385 4 0 1 19387 4 2 13594 10 0 1 19391 1 19380 1 19391 2 11 19389 1 19391 3 19380 4 0 1 19391 4 11 11000 6 0 1 19403 1 19401 1 19403 2 2 19402 1 19403 3 19401 2 0 1 19403 4 2 10684 2 0 1 19417 1 19412 1 19417 2 5 19416 1 19417 3 19412 1 0 1 19417 4 5 15493 6 0 1 19421 1 19418 1 19421 2 3 19412 1 19421 3 19418 4 0 1 19421 4 3 13945 1 0 1 19423 1 19420 1 19423 2 3 19422 1 19423 3 19420 1 0 1 19423 4 3 14877 5 0 1 19427 1 19425 1 19427 2 2 19423 1 19427 3 19425 3 0 1 19427 4 2 11849 20 0 1 19429 1 19423 1 19429 2 6 19421 1 19429 3 19423 9 0 1 19429 4 6 11211 0 0 1 19433 1 19430 1 19433 2 3 19428 1 19433 3 19430 1 0 1 19433 4 3 13274 0 0 1 19441 1 19428 1 19441 2 13 19440 1 19441 3 19428 2 0 1 19441 4 13 14039 14 0 1 19447 1 19444 1 19447 2 3 19446 1 19447 3 19444 9 0 1 19447 4 3 18565 5 0 1 19457 1 19454 1 19457 2 3 19450 1 19457 3 19454 1 0 1 19457 4 3 19115 1 0 1 19463 1 19458 1 19463 2 5 19455 1 19463 3 19458 9 0 1 19463 4 5 16645 3 0 1 19469 1 19467 1 19469 2 2 19465 1 19469 3 19467 2 0 1 19469 4 2 16973 12 0 1 19471 1 19460 1 19471 2 11 19469 1 19471 3 19460 8 0 1 19471 4 11 14971 6 0 1 19477 1 19471 1 19477 2 6 19476 1 19477 3 19471 3 0 1 19477 4 6 14529 6 0 1 19483 1 19481 1 19483 2 2 19479 1 19483 3 19481 4 0 1 19483 4 2 15277 20 0 1 19489 1 19470 1 19489 2 19 19484 1 19489 3 19470 2 0 1 19489 4 19 14131 22 0 1 19501 1 19499 1 19501 2 2 19500 1 19501 3 19499 6 0 1 19501 4 2 16335 7 0 1 19507 1 19505 1 19507 2 2 19506 1 19507 3 19505 2 0 1 19507 4 2 17426 2 0 1 19531 1 19518 1 19531 2 13 19527 1 19531 3 19518 2 0 1 19531 4 13 19519 8 0 1 19541 1 19539 1 19541 2 2 19537 1 19541 3 19539 3 0 1 19541 4 2 14530 12 0 1 19543 1 19540 1 19543 2 3 19542 1 19543 3 19540 1 0 1 19543 4 3 13152 2 0 1 19553 1 19550 1 19553 2 3 19552 1 19553 3 19550 8 0 1 19553 4 3 14809 4 0 1 19559 1 19546 1 19559 2 13 19557 1 19559 3 19546 2 0 1 19559 4 13 17030 3 0 1 19571 1 19569 1 19571 2 2 19567 1 19571 3 19569 3 0 1 19571 4 2 11687 9 0 1 19577 1 19574 1 19577 2 3 19576 1 19577 3 19574 4 0 1 19577 4 3 17994 4 0 1 19583 1 19578 1 19583 2 5 19582 1 19583 3 19578 1 0 1 19583 4 5 19041 2 0 1 19597 1 19595 1 19597 2 2 19593 1 19597 3 19595 6 0 1 19597 4 2 18971 12 0 1 19603 1 19601 1 19603 2 2 19602 1 19603 3 19601 2 0 1 19603 4 2 19596 8 0 1 19609 1 19596 1 19609 2 13 19596 1 19609 3 19596 4 0 1 19609 4 13 19570 0 0 1 19661 1 19659 1 19661 2 2 19660 1 19661 3 19659 5 0 1 19661 4 2 17605 4 0 1 19681 1 19670 1 19681 2 11 19680 1 19681 3 19670 4 0 1 19681 4 11 14428 30 0 1 19687 1 19682 1 19687 2 5 19686 1 19687 3 19682 2 0 1 19687 4 5 11861 2 0 1 19697 1 19694 1 19697 2 3 19696 1 19697 3 19694 3 0 1 19697 4 3 19300 4 0 1 19699 1 19692 1 19699 2 7 19697 1 19699 3 19692 2 0 1 19699 4 7 12581 6 0 1 19709 1 19707 1 19709 2 2 19702 1 19709 3 19707 2 0 1 19709 4 2 11056 9 0 1 19717 1 19715 1 19717 2 2 19716 1 19717 3 19715 2 0 1 19717 4 2 10550 6 0 1 19727 1 19722 1 19727 2 5 19725 1 19727 3 19722 1 0 1 19727 4 5 19723 3 0 1 19739 1 19737 1 19739 2 2 19738 1 19739 3 19737 3 0 1 19739 4 2 13586 2 0 1 19751 1 19744 1 19751 2 7 19750 1 19751 3 19744 5 0 1 19751 4 7 12836 3 0 1 19753 1 19748 1 19753 2 5 19750 1 19753 3 19748 9 0 1 19753 4 5 19742 14 0 1 19759 1 19756 1 19759 2 3 19757 1 19759 3 19756 3 0 1 19759 4 3 11645 3 0 1 19763 1 19761 1 19763 2 2 19757 1 19763 3 19761 4 0 1 19763 4 2 11361 0 0 1 19777 1 19766 1 19777 2 11 19775 1 19777 3 19766 4 0 1 19777 4 11 19757 12 0 1 19793 1 19790 1 19793 2 3 19788 1 19793 3 19790 1 0 1 19793 4 3 16165 2 0 1 19801 1 19788 1 19801 2 13 19790 1 19801 3 19788 5 0 1 19801 4 13 16129 24 0 1 19813 1 19811 1 19813 2 2 19812 1 19813 3 19811 2 0 1 19813 4 2 18848 3 0 1 19819 1 19816 1 19819 2 3 19818 1 19819 3 19816 1 0 1 19819 4 3 16578 2 0 1 19841 1 19838 1 19841 2 3 19840 1 19841 3 19838 1 0 1 19841 4 3 10211 7 0 1 19843 1 19824 1 19843 2 19 19840 1 19843 3 19824 2 0 1 19843 4 19 15188 10 0 1 19853 1 19851 1 19853 2 2 19848 1 19853 3 19851 7 0 1 19853 4 2 15733 0 0 1 19861 1 19850 1 19861 2 11 19859 1 19861 3 19850 4 0 1 19861 4 11 19546 0 0 1 19867 1 19865 1 19867 2 2 19863 1 19867 3 19865 4 0 1 19867 4 2 17475 8 0 1 19889 1 19886 1 19889 2 3 19883 1 19889 3 19886 13 0 1 19889 4 3 19877 0 0 1 19891 1 19889 1 19891 2 2 19887 1 19891 3 19889 2 0 1 19891 4 2 11654 8 0 1 19913 1 19910 1 19913 2 3 19907 1 19913 3 19910 1 0 1 19913 4 3 10168 9 0 1 19919 1 19912 1 19919 2 7 19918 1 19919 3 19912 4 0 1 19919 4 7 11212 6 0 1 19927 1 19921 1 19927 2 6 19924 1 19927 3 19921 7 0 1 19927 4 6 17010 7 0 1 19937 1 19934 1 19937 2 3 19932 1 19937 3 19934 4 0 1 19937 4 3 11705 8 0 1 19949 1 19947 1 19949 2 2 19948 1 19949 3 19947 3 0 1 19949 4 2 18260 3 0 1 19961 1 19955 1 19961 2 6 19960 1 19961 3 19955 1 0 1 19961 4 6 12333 4 0 1 19963 1 19961 1 19963 2 2 19962 1 19963 3 19961 4 0 1 19963 4 2 15034 11 0 1 19973 1 19971 1 19973 2 2 19969 1 19973 3 19971 3 0 1 19973 4 2 10367 7 0 1 19979 1 19977 1 19979 2 2 19975 1 19979 3 19977 2 0 1 19979 4 2 17346 7 0 1 19991 1 19980 1 19991 2 11 19990 1 19991 3 19980 5 0 1 19991 4 11 13741 3 0 1 19993 1 19983 1 19993 2 10 19990 1 19993 3 19983 2 0 1 19993 4 10 10617 8 0 1 19997 1 19995 1 19997 2 2 19996 1 19997 3 19995 2 0 1 19997 4 2 16717 3 0 1 20011 1 19999 1 20011 2 12 20009 1 20011 3 19999 4 0 1 20011 4 12 15522 3 0 1 20021 1 20018 1 20021 2 3 20019 1 20021 3 20018 5 0 1 20021 4 3 20017 4 0 1 20023 1 20020 1 20023 2 3 20021 1 20023 3 20020 3 0 1 20023 4 3 20019 4 0 1 20029 1 20027 1 20029 2 2 20025 1 20029 3 20027 4 0 1 20029 4 2 17747 6 0 1 20047 1 20044 1 20047 2 3 20045 1 20047 3 20044 3 0 1 20047 4 3 10742 6 0 1 20051 1 20049 1 20051 2 2 20050 1 20051 3 20049 4 0 1 20051 4 2 15376 6 0 1 20063 1 20058 1 20063 2 5 20062 1 20063 3 20058 1 0 1 20063 4 5 17486 5 0 1 20071 1 20068 1 20071 2 3 20070 1 20071 3 20068 3 0 1 20071 4 3 13551 3 0 1 20089 1 20082 1 20089 2 7 20080 1 20089 3 20082 2 0 1 20089 4 7 16179 2 0 1 20101 1 20095 1 20101 2 6 20100 1 20101 3 20095 2 0 1 20101 4 6 16896 19 0 1 20107 1 20105 1 20107 2 2 20106 1 20107 3 20105 2 0 1 20107 4 2 20100 8 0 1 20113 1 20103 1 20113 2 10 20112 1 20113 3 20103 5 0 1 20113 4 10 19737 16 0 1 20117 1 20115 1 20117 2 2 20112 1 20117 3 20115 3 0 1 20117 4 2 17193 2 0 1 20123 1 20121 1 20123 2 2 20122 1 20123 3 20121 3 0 1 20123 4 2 20116 8 0 1 20129 1 20126 1 20129 2 3 20128 1 20129 3 20126 3 0 1 20129 4 3 14233 4 0 1 20143 1 20138 1 20143 2 5 20142 1 20143 3 20138 1 0 1 20143 4 5 15741 3 0 1 20147 1 20141 1 20147 2 6 20138 1 20147 3 20141 2 0 1 20147 4 6 16405 2 0 1 20149 1 20147 1 20149 2 2 20148 1 20149 3 20147 6 0 1 20149 4 2 11354 3 0 1 20161 1 20148 1 20161 2 13 20158 1 20161 3 20148 7 0 1 20161 4 13 10924 22 0 1 20173 1 20171 1 20173 2 2 20172 1 20173 3 20171 5 0 1 20173 4 2 12648 3 0 1 20177 1 20174 1 20177 2 3 20171 1 20177 3 20174 14 0 1 20177 4 3 12724 9 0 1 20183 1 20178 1 20183 2 5 20175 1 20183 3 20178 2 0 1 20183 4 5 19020 1 0 1 20201 1 20195 1 20201 2 6 20195 1 20201 3 20195 2 0 1 20201 4 6 15004 0 0 1 20219 1 20217 1 20219 2 2 20218 1 20219 3 20217 3 0 1 20219 4 2 11006 2 0 1 20231 1 20202 1 20231 2 29 20230 1 20231 3 20202 6 0 1 20231 4 29 19120 3 0 1 20233 1 20228 1 20233 2 5 20228 1 20233 3 20228 1 0 1 20233 4 5 16403 10 0 1 20249 1 20246 1 20249 2 3 20243 1 20249 3 20246 1 0 1 20249 4 3 20237 0 0 1 20261 1 20259 1 20261 2 2 20260 1 20261 3 20259 4 0 1 20261 4 2 18378 3 0 1 20269 1 20267 1 20269 2 2 20265 1 20269 3 20267 2 0 1 20269 4 2 19095 6 0 1 20287 1 20282 1 20287 2 5 20286 1 20287 3 20282 3 0 1 20287 4 5 11622 3 0 1 20297 1 20294 1 20297 2 3 20296 1 20297 3 20294 4 0 1 20297 4 3 12438 11 0 1 20323 1 20321 1 20323 2 2 20319 1 20323 3 20321 4 0 1 20323 4 2 19228 8 0 1 20327 1 20322 1 20327 2 5 20325 1 20327 3 20322 2 0 1 20327 4 5 20323 3 0 1 20333 1 20330 1 20333 2 3 20326 1 20333 3 20330 11 0 1 20333 4 3 15379 2 0 1 20341 1 20339 1 20341 2 2 20340 1 20341 3 20339 6 0 1 20341 4 2 10330 3 0 1 20347 1 20344 1 20347 2 3 20346 1 20347 3 20344 4 0 1 20347 4 3 11117 2 0 1 20353 1 20348 1 20353 2 5 20348 1 20353 3 20348 2 0 1 20353 4 5 20106 15 0 1 20357 1 20355 1 20357 2 2 20349 1 20357 3 20355 4 0 1 20357 4 2 12291 19 0 1 20359 1 20348 1 20359 2 11 20356 1 20359 3 20348 2 0 1 20359 4 11 19263 4 0 1 20369 1 20366 1 20369 2 3 20364 1 20369 3 20366 4 0 1 20369 4 3 14324 2 0 1 20389 1 20383 1 20389 2 6 20385 1 20389 3 20383 2 0 1 20389 4 6 10912 2 0 1 20393 1 20390 1 20393 2 3 20392 1 20393 3 20390 1 0 1 20393 4 3 12277 7 0 1 20399 1 20392 1 20399 2 7 20395 1 20399 3 20392 7 0 1 20399 4 7 10542 5 0 1 20407 1 20402 1 20407 2 5 20405 1 20407 3 20402 3 0 1 20407 4 5 20403 3 0 1 20411 1 20405 1 20411 2 6 20410 1 20411 3 20405 1 0 1 20411 4 6 10887 5 0 1 20431 1 20428 1 20431 2 3 20429 1 20431 3 20428 13 0 1 20431 4 3 20427 4 0 1 20441 1 20438 1 20441 2 3 20435 1 20441 3 20438 4 0 1 20441 4 3 20429 0 0 1 20443 1 20441 1 20443 2 2 20442 1 20443 3 20441 2 0 1 20443 4 2 16404 2 0 1 20477 1 20475 1 20477 2 2 20473 1 20477 3 20475 3 0 1 20477 4 2 12367 7 0 1 20479 1 20476 1 20479 2 3 20478 1 20479 3 20476 3 0 1 20479 4 3 16508 2 0 1 20483 1 20478 1 20483 2 5 20481 1 20483 3 20478 6 0 1 20483 4 5 20479 3 0 1 20507 1 20505 1 20507 2 2 20503 1 20507 3 20505 3 0 1 20507 4 2 11073 7 0 1 20509 1 20507 1 20509 2 2 20505 1 20509 3 20507 4 0 1 20509 4 2 11765 6 0 1 20521 1 20510 1 20521 2 11 20512 1 20521 3 20510 6 0 1 20521 4 11 13028 20 0 1 20533 1 20531 1 20533 2 2 20529 1 20533 3 20531 9 0 1 20533 4 2 12737 12 0 1 20543 1 20538 1 20543 2 5 20532 1 20543 3 20538 1 0 1 20543 4 5 12630 6 0 1 20549 1 20547 1 20549 2 2 20545 1 20549 3 20547 3 0 1 20549 4 2 12215 12 0 1 20551 1 20548 1 20551 2 3 20549 1 20551 3 20548 1 0 1 20551 4 3 11603 3 0 1 20563 1 20560 1 20563 2 3 20548 1 20563 3 20560 1 0 1 20563 4 3 13174 3 0 1 20593 1 20588 1 20593 2 5 20586 1 20593 3 20588 1 0 1 20593 4 5 10926 12 0 1 20599 1 20596 1 20599 2 3 20598 1 20599 3 20596 1 0 1 20599 4 3 20396 2 0 1 20611 1 20609 1 20611 2 2 20610 1 20611 3 20609 4 0 1 20611 4 2 19726 2 0 1 20627 1 20625 1 20627 2 2 20626 1 20627 3 20625 3 0 1 20627 4 2 11219 2 0 1 20639 1 20628 1 20639 2 11 20636 1 20639 3 20628 8 0 1 20639 4 11 19354 6 0 1 20641 1 20634 1 20641 2 7 20634 1 20641 3 20634 2 0 1 20641 4 7 17957 0 0 1 20663 1 20658 1 20663 2 5 20655 1 20663 3 20658 2 0 1 20663 4 5 14980 3 0 1 20681 1 20678 1 20681 2 3 20676 1 20681 3 20678 3 0 1 20681 4 3 11466 2 0 1 20693 1 20691 1 20693 2 2 20689 1 20693 3 20691 3 0 1 20693 4 2 11356 9 0 1 20707 1 20702 1 20707 2 5 20705 1 20707 3 20702 3 0 1 20707 4 5 20703 3 0 1 20717 1 20715 1 20717 2 2 20713 1 20717 3 20715 3 0 1 20717 4 2 19390 6 0 1 20719 1 20716 1 20719 2 3 20718 1 20719 3 20716 3 0 1 20719 4 3 16971 3 0 1 20731 1 20729 1 20731 2 2 20727 1 20731 3 20729 2 0 1 20731 4 2 15429 8 0 1 20743 1 20738 1 20743 2 5 20742 1 20743 3 20738 5 0 1 20743 4 5 13294 5 0 1 20747 1 20742 1 20747 2 5 20746 1 20747 3 20742 3 0 1 20747 4 5 19111 8 0 1 20749 1 20747 1 20749 2 2 20745 1 20749 3 20747 4 0 1 20749 4 2 16542 10 0 1 20753 1 20750 1 20753 2 3 20748 1 20753 3 20750 3 0 1 20753 4 3 15131 0 0 1 20759 1 20752 1 20759 2 7 20758 1 20759 3 20752 8 0 1 20759 4 7 17518 2 0 1 20771 1 20769 1 20771 2 2 20767 1 20771 3 20769 3 0 1 20771 4 2 10858 8 0 1 20773 1 20771 1 20773 2 2 20769 1 20773 3 20771 4 0 1 20773 4 2 11356 10 0 1 20789 1 20787 1 20789 2 2 20785 1 20789 3 20787 3 0 1 20789 4 2 15511 1 0 1 20807 1 20802 1 20807 2 5 20805 1 20807 3 20802 7 0 1 20807 4 5 20803 3 0 1 20809 1 20802 1 20809 2 7 20802 1 20809 3 20802 2 0 1 20809 4 7 17529 0 0 1 20849 1 20846 1 20849 2 3 20843 1 20849 3 20846 11 0 1 20849 4 3 20837 0 0 1 20857 1 20847 1 20857 2 10 20856 1 20857 3 20847 5 0 1 20857 4 10 18094 14 0 1 20873 1 20870 1 20873 2 3 20868 1 20873 3 20870 4 0 1 20873 4 3 19344 0 0 1 20879 1 20868 1 20879 2 11 20877 1 20879 3 20868 1 0 1 20879 4 11 12172 7 0 1 20887 1 20884 1 20887 2 3 20885 1 20887 3 20884 1 0 1 20887 4 3 17620 6 0 1 20897 1 20894 1 20897 2 3 20892 1 20897 3 20894 4 0 1 20897 4 3 18719 0 0 1 20899 1 20897 1 20899 2 2 20895 1 20899 3 20897 2 0 1 20899 4 2 11108 8 0 1 20903 1 20898 1 20903 2 5 20901 1 20903 3 20898 1 0 1 20903 4 5 20899 3 0 1 20921 1 20918 1 20921 2 3 20915 1 20921 3 20918 4 0 1 20921 4 3 20909 0 0 1 20929 1 20922 1 20929 2 7 20926 1 20929 3 20922 3 0 1 20929 4 7 15261 14 0 1 20939 1 20937 1 20939 2 2 20928 1 20939 3 20937 10 0 1 20939 4 2 12137 3 0 1 20947 1 20944 1 20947 2 3 20940 1 20947 3 20944 1 0 1 20947 4 3 17590 8 0 1 20959 1 20952 1 20959 2 7 20948 1 20959 3 20952 3 0 1 20959 4 7 18067 0 0 1 20963 1 20961 1 20963 2 2 20962 1 20963 3 20961 2 0 1 20963 4 2 20712 17 0 1 20981 1 20979 1 20981 2 2 20977 1 20981 3 20979 2 0 1 20981 4 2 17538 6 0 1 20983 1 20980 1 20983 2 3 20982 1 20983 3 20980 4 0 1 20983 4 3 10920 2 0 1 21001 1 20990 1 21001 2 11 20992 1 21001 3 20990 2 0 1 21001 4 11 11284 20 0 1 21011 1 21009 1 21011 2 2 21004 1 21011 3 21009 2 0 1 21011 4 2 12497 1 0 1 21013 1 21011 1 21013 2 2 21012 1 21013 3 21011 2 0 1 21013 4 2 15841 6 0 1 21017 1 21014 1 21017 2 3 21011 1 21017 3 21014 5 0 1 21017 4 3 12444 11 0 1 21019 1 21017 1 21019 2 2 21018 1 21019 3 21017 6 0 1 21019 4 2 17038 6 0 1 21023 1 21018 1 21023 2 5 21020 1 21023 3 21018 3 0 1 21023 4 5 18234 4 0 1 21031 1 21019 1 21031 2 12 21030 1 21031 3 21019 1 0 1 21031 4 12 11608 2 0 1 21059 1 21057 1 21059 2 2 21058 1 21059 3 21057 3 0 1 21059 4 2 17715 2 0 1 21061 1 21054 1 21061 2 7 21059 1 21061 3 21054 1 0 1 21061 4 7 14335 4 0 1 21067 1 21065 1 21067 2 2 21063 1 21067 3 21065 5 0 1 21067 4 2 16954 8 0 1 21089 1 21086 1 21089 2 3 21079 1 21089 3 21086 6 0 1 21089 4 3 11010 4 0 1 21101 1 21099 1 21101 2 2 21100 1 21101 3 21099 3 0 1 21101 4 2 12337 9 0 1 21107 1 21105 1 21107 2 2 21102 1 21107 3 21105 10 0 1 21107 4 2 18689 0 0 1 21121 1 21102 1 21121 2 19 21109 1 21121 3 21102 7 0 1 21121 4 19 11023 50 0 1 21139 1 21137 1 21139 2 2 21138 1 21139 3 21137 7 0 1 21139 4 2 13810 7 0 1 21143 1 21133 1 21143 2 10 21139 1 21143 3 21133 3 0 1 21143 4 10 16832 5 0 1 21149 1 21146 1 21149 2 3 21147 1 21149 3 21146 6 0 1 21149 4 3 21141 10 0 1 21157 1 21155 1 21157 2 2 21156 1 21157 3 21155 4 0 1 21157 4 2 13289 7 0 1 21163 1 21161 1 21163 2 2 21159 1 21163 3 21161 4 0 1 21163 4 2 11414 8 0 1 21169 1 21156 1 21169 2 13 21156 1 21169 3 21156 1 0 1 21169 4 13 21130 0 0 1 21179 1 21177 1 21179 2 2 21175 1 21179 3 21177 2 0 1 21179 4 2 13268 7 0 1 21187 1 21185 1 21187 2 2 21186 1 21187 3 21185 2 0 1 21187 4 2 18507 2 0 1 21191 1 21184 1 21191 2 7 21190 1 21191 3 21184 2 0 1 21191 4 7 20985 3 0 1 21193 1 21182 1 21193 2 11 21192 1 21193 3 21182 4 0 1 21193 4 11 13689 6 0 1 21211 1 21209 1 21211 2 2 21207 1 21211 3 21209 6 0 1 21211 4 2 20728 8 0 1 21221 1 21219 1 21221 2 2 21217 1 21221 3 21219 3 0 1 21221 4 2 18148 6 0 1 21227 1 21225 1 21227 2 2 21226 1 21227 3 21225 3 0 1 21227 4 2 15984 13 0 1 21247 1 21244 1 21247 2 3 21246 1 21247 3 21244 7 0 1 21247 4 3 14636 23 0 1 21269 1 21267 1 21269 2 2 21265 1 21269 3 21267 3 0 1 21269 4 2 13497 1 0 1 21277 1 21271 1 21277 2 6 21275 1 21277 3 21271 1 0 1 21277 4 6 11311 8 0 1 21283 1 21272 1 21283 2 11 21281 1 21283 3 21272 1 0 1 21283 4 11 21030 6 0 1 21313 1 21308 1 21313 2 5 21312 1 21313 3 21308 2 0 1 21313 4 5 11188 6 0 1 21317 1 21315 1 21317 2 2 21310 1 21317 3 21315 5 0 1 21317 4 2 17994 4 0 1 21319 1 21305 1 21319 2 14 21317 1 21319 3 21305 2 0 1 21319 4 14 11947 4 0 1 21323 1 21318 1 21323 2 5 21321 1 21323 3 21318 3 0 1 21323 4 5 15462 0 0 1 21341 1 21339 1 21341 2 2 21340 1 21341 3 21339 3 0 1 21341 4 2 11664 4 0 1 21347 1 21345 1 21347 2 2 21343 1 21347 3 21345 3 0 1 21347 4 2 19528 7 0 1 21377 1 21374 1 21377 2 3 21369 1 21377 3 21374 1 0 1 21377 4 3 20407 2 0 1 21379 1 21377 1 21379 2 2 21375 1 21379 3 21377 2 0 1 21379 4 2 10816 8 0 1 21383 1 21378 1 21383 2 5 21382 1 21383 3 21378 2 0 1 21383 4 5 11578 4 0 1 21391 1 21385 1 21391 2 6 21389 1 21391 3 21385 7 0 1 21391 4 6 17645 3 0 1 21397 1 21395 1 21397 2 2 21396 1 21397 3 21395 2 0 1 21397 4 2 16917 3 0 1 21401 1 21398 1 21401 2 3 21394 1 21401 3 21398 1 0 1 21401 4 3 17194 1 0 1 21407 1 21402 1 21407 2 5 21406 1 21407 3 21402 9 0 1 21407 4 5 15684 2 0 1 21419 1 21417 1 21419 2 2 21415 1 21419 3 21417 3 0 1 21419 4 2 15943 7 0 1 21433 1 21428 1 21433 2 5 21428 1 21433 3 21428 6 0 1 21433 4 5 18101 19 0 1 21467 1 21465 1 21467 2 2 21466 1 21467 3 21465 2 0 1 21467 4 2 15783 4 0 1 21481 1 21468 1 21481 2 13 21480 1 21481 3 21468 1 0 1 21481 4 13 11187 14 0 1 21487 1 21484 1 21487 2 3 21485 1 21487 3 21484 4 0 1 21487 4 3 20081 6 0 1 21491 1 21489 1 21491 2 2 21486 1 21491 3 21489 2 0 1 21491 4 2 17541 3 0 1 21493 1 21491 1 21493 2 2 21492 1 21493 3 21491 2 0 1 21493 4 2 15459 3 0 1 21499 1 21496 1 21499 2 3 21492 1 21499 3 21496 3 0 1 21499 4 3 13890 5 0 1 21503 1 21498 1 21503 2 5 21502 1 21503 3 21498 2 0 1 21503 4 5 14072 4 0 1 21517 1 21512 1 21517 2 5 21512 1 21517 3 21512 3 0 1 21517 4 5 16883 7 0 1 21521 1 21518 1 21521 2 3 21516 1 21521 3 21518 3 0 1 21521 4 3 15845 2 0 1 21523 1 21521 1 21523 2 2 21522 1 21523 3 21521 2 0 1 21523 4 2 20994 7 0 1 21529 1 21518 1 21529 2 11 21528 1 21529 3 21518 3 0 1 21529 4 11 15558 20 0 1 21557 1 21555 1 21557 2 2 21553 1 21557 3 21555 11 0 1 21557 4 2 12548 7 0 1 21559 1 21544 1 21559 2 15 21554 1 21559 3 21544 4 0 1 21559 4 15 16632 2 0 1 21563 1 21561 1 21563 2 2 21562 1 21563 3 21561 2 0 1 21563 4 2 21556 8 0 1 21569 1 21566 1 21569 2 3 21564 1 21569 3 21566 5 0 1 21569 4 3 19927 2 0 1 21577 1 21572 1 21577 2 5 21576 1 21577 3 21572 3 0 1 21577 4 5 12406 6 0 1 21587 1 21585 1 21587 2 2 21586 1 21587 3 21585 3 0 1 21587 4 2 15908 10 0 1 21589 1 21587 1 21589 2 2 21585 1 21589 3 21587 2 0 1 21589 4 2 12637 12 0 1 21599 1 21592 1 21599 2 7 21598 1 21599 3 21592 8 0 1 21599 4 7 15458 2 0 1 21601 1 21594 1 21601 2 7 21594 1 21601 3 21594 11 0 1 21601 4 7 18308 0 0 1 21611 1 21609 1 21611 2 2 21607 1 21611 3 21609 3 0 1 21611 4 2 21023 8 0 1 21613 1 21611 1 21613 2 2 21609 1 21613 3 21611 5 0 1 21613 4 2 21319 6 0 1 21617 1 21614 1 21617 2 3 21612 1 21617 3 21614 1 0 1 21617 4 3 20609 0 0 1 21647 1 21642 1 21647 2 5 21644 1 21647 3 21642 6 0 1 21647 4 5 13870 4 0 1 21649 1 21635 1 21649 2 14 21646 1 21649 3 21635 2 0 1 21649 4 14 10990 10 0 1 21661 1 21659 1 21661 2 2 21660 1 21661 3 21659 6 0 1 21661 4 2 20652 3 0 1 21673 1 21663 1 21673 2 10 21672 1 21673 3 21663 6 0 1 21673 4 10 11562 21 0 1 21683 1 21681 1 21683 2 2 21679 1 21683 3 21681 3 0 1 21683 4 2 21428 7 0 1 21701 1 21699 1 21701 2 2 21697 1 21701 3 21699 3 0 1 21701 4 2 11188 7 0 1 21713 1 21710 1 21713 2 3 21706 1 21713 3 21710 4 0 1 21713 4 3 11351 0 0 1 21727 1 21724 1 21727 2 3 21726 1 21727 3 21724 3 0 1 21727 4 3 20947 5 0 1 21737 1 21731 1 21737 2 6 21735 1 21737 3 21731 3 0 1 21737 4 6 15587 8 0 1 21739 1 21737 1 21739 2 2 21735 1 21739 3 21737 2 0 1 21739 4 2 20761 8 0 1 21751 1 21748 1 21751 2 3 21749 1 21751 3 21748 8 0 1 21751 4 3 18831 3 0 1 21757 1 21752 1 21757 2 5 21756 1 21757 3 21752 3 0 1 21757 4 5 20260 3 0 1 21767 1 21762 1 21767 2 5 21766 1 21767 3 21762 3 0 1 21767 4 5 11790 3 0 1 21773 1 21771 1 21773 2 2 21769 1 21773 3 21771 2 0 1 21773 4 2 14021 1 0 1 21787 1 21764 1 21787 2 23 21786 1 21787 3 21764 4 0 1 21787 4 23 17555 11 0 1 21799 1 21792 1 21799 2 7 21788 1 21799 3 21792 4 0 1 21799 4 7 12115 5 0 1 21803 1 21801 1 21803 2 2 21802 1 21803 3 21801 2 0 1 21803 4 2 13905 4 0 1 21817 1 21810 1 21817 2 7 21810 1 21817 3 21810 11 0 1 21817 4 7 16726 22 0 1 21821 1 21819 1 21821 2 2 21817 1 21821 3 21819 2 0 1 21821 4 2 15700 6 0 1 21839 1 21828 1 21839 2 11 21835 1 21839 3 21828 5 0 1 21839 4 11 14928 5 0 1 21841 1 21830 1 21841 2 11 21836 1 21841 3 21830 6 0 1 21841 4 11 21822 24 0 1 21851 1 21845 1 21851 2 6 21849 1 21851 3 21845 3 0 1 21851 4 6 15992 0 0 1 21859 1 21857 1 21859 2 2 21858 1 21859 3 21857 6 0 1 21859 4 2 16731 2 0 1 21863 1 21858 1 21863 2 5 21861 1 21863 3 21858 2 0 1 21863 4 5 18880 5 0 1 21871 1 21865 1 21871 2 6 21870 1 21871 3 21865 6 0 1 21871 4 6 17088 2 0 1 21881 1 21878 1 21881 2 3 21876 1 21881 3 21878 1 0 1 21881 4 3 11106 2 0 1 21893 1 21891 1 21893 2 2 21885 1 21893 3 21891 4 0 1 21893 4 2 20466 3 0 1 21911 1 21898 1 21911 2 13 21910 1 21911 3 21898 10 0 1 21911 4 13 16837 2 0 1 21929 1 21926 1 21929 2 3 21924 1 21929 3 21926 3 0 1 21929 4 3 18844 2 0 1 21937 1 21930 1 21937 2 7 21930 1 21937 3 21930 8 0 1 21937 4 7 19558 12 0 1 21943 1 21938 1 21943 2 5 21941 1 21943 3 21938 2 0 1 21943 4 5 21931 11 0 1 21961 1 21944 1 21961 2 17 21960 1 21961 3 21944 15 0 1 21961 4 17 18877 30 0 1 21977 1 21974 1 21977 2 3 21972 1 21977 3 21974 3 0 1 21977 4 3 18370 0 0 1 21991 1 21988 1 21991 2 3 21990 1 21991 3 21988 7 0 1 21991 4 3 17520 3 0 1 21997 1 21990 1 21997 2 7 21995 1 21997 3 21990 2 0 1 21997 4 7 18589 4 0 1 22003 1 22001 1 22003 2 2 21999 1 22003 3 22001 6 0 1 22003 4 2 20223 8 0 1 22013 1 22011 1 22013 2 2 22012 1 22013 3 22011 2 0 1 22013 4 2 11274 3 0 1 22027 1 22024 1 22027 2 3 22022 1 22027 3 22024 6 0 1 22027 4 3 16824 3 0 1 22031 1 22024 1 22031 2 7 22030 1 22031 3 22024 4 0 1 22031 4 7 22022 4 0 1 22037 1 22035 1 22037 2 2 22033 1 22037 3 22035 3 0 1 22037 4 2 19625 7 0 1 22039 1 22033 1 22039 2 6 22038 1 22039 3 22033 1 0 1 22039 4 6 19033 3 0 1 22051 1 22048 1 22051 2 3 22050 1 22051 3 22048 3 0 1 22051 4 3 11985 2 0 1 22063 1 22058 1 22063 2 5 22061 1 22063 3 22058 3 0 1 22063 4 5 20190 9 0 1 22067 1 22065 1 22067 2 2 22066 1 22067 3 22065 2 0 1 22067 4 2 17808 2 0 1 22073 1 22070 1 22073 2 3 22067 1 22073 3 22070 5 0 1 22073 4 3 15707 9 0 1 22079 1 22072 1 22079 2 7 22075 1 22079 3 22072 2 0 1 22079 4 7 13498 12 0 1 22091 1 22089 1 22091 2 2 22090 1 22091 3 22089 3 0 1 22091 4 2 13125 2 0 1 22093 1 22087 1 22093 2 6 22091 1 22093 3 22087 2 0 1 22093 4 6 19829 8 0 1 22109 1 22107 1 22109 2 2 22103 1 22109 3 22107 3 0 1 22109 4 2 18368 3 0 1 22111 1 22105 1 22111 2 6 22109 1 22111 3 22105 2 0 1 22111 4 6 20781 3 0 1 22123 1 22121 1 22123 2 2 22122 1 22123 3 22121 6 0 1 22123 4 2 17751 17 0 1 22129 1 22110 1 22129 2 19 22124 1 22129 3 22110 1 0 1 22129 4 19 14125 16 0 1 22133 1 22131 1 22133 2 2 22127 1 22133 3 22131 8 0 1 22133 4 2 15963 1 0 1 22147 1 22142 1 22147 2 5 22146 1 22147 3 22142 3 0 1 22147 4 5 16305 24 0 1 22153 1 22148 1 22153 2 5 22152 1 22153 3 22148 1 0 1 22153 4 5 11345 6 0 1 22157 1 22155 1 22157 2 2 22153 1 22157 3 22155 8 0 1 22157 4 2 19121 6 0 1 22159 1 22153 1 22159 2 6 22158 1 22159 3 22153 6 0 1 22159 4 6 21602 2 0 1 22171 1 22169 1 22171 2 2 22167 1 22171 3 22169 2 0 1 22171 4 2 16048 8 0 1 22189 1 22187 1 22189 2 2 22185 1 22189 3 22187 4 0 1 22189 4 2 14003 27 0 1 22193 1 22190 1 22193 2 3 22192 1 22193 3 22190 3 0 1 22193 4 3 12354 6 0 1 22229 1 22227 1 22229 2 2 22221 1 22229 3 22227 5 0 1 22229 4 2 15382 0 0 1 22247 1 22242 1 22247 2 5 22245 1 22247 3 22242 5 0 1 22247 4 5 17628 20 0 1 22259 1 22257 1 22259 2 2 22255 1 22259 3 22257 3 0 1 22259 4 2 12627 15 0 1 22271 1 22264 1 22271 2 7 22270 1 22271 3 22264 9 0 1 22271 4 7 12906 2 0 1 22273 1 22268 1 22273 2 5 22268 1 22273 3 22268 5 0 1 22273 4 5 22062 10 0 1 22277 1 22275 1 22277 2 2 22273 1 22277 3 22275 2 0 1 22277 4 2 18990 1 0 1 22279 1 22276 1 22279 2 3 22277 1 22279 3 22276 1 0 1 22279 4 3 15116 6 0 1 22283 1 22281 1 22283 2 2 22277 1 22283 3 22281 4 0 1 22283 4 2 18879 4 0 1 22291 1 22288 1 22291 2 3 22284 1 22291 3 22288 1 0 1 22291 4 3 20233 5 0 1 22303 1 22297 1 22303 2 6 22300 1 22303 3 22297 1 0 1 22303 4 6 19217 4 0 1 22307 1 22305 1 22307 2 2 22302 1 22307 3 22305 12 0 1 22307 4 2 19485 0 0 1 22343 1 22338 1 22343 2 5 22342 1 22343 3 22338 8 0 1 22343 4 5 20747 7 0 1 22349 1 22347 1 22349 2 2 22340 1 22349 3 22347 3 0 1 22349 4 2 12245 1 0 1 22367 1 22362 1 22367 2 5 22365 1 22367 3 22362 3 0 1 22367 4 5 22363 3 0 1 22369 1 22358 1 22369 2 11 22358 1 22369 3 22358 3 0 1 22369 4 11 20057 22 0 1 22381 1 22371 1 22381 2 10 22378 1 22381 3 22371 3 0 1 22381 4 10 20073 9 0 1 22391 1 22378 1 22391 2 13 22390 1 22391 3 22378 1 0 1 22391 4 13 19015 8 0 1 22397 1 22395 1 22397 2 2 22393 1 22397 3 22395 3 0 1 22397 4 2 17655 7 0 1 22409 1 22406 1 22409 2 3 22408 1 22409 3 22406 5 0 1 22409 4 3 11808 7 0 1 22433 1 22430 1 22433 2 3 22428 1 22433 3 22430 1 0 1 22433 4 3 21207 0 0 1 22441 1 22427 1 22441 2 14 22438 1 22441 3 22427 2 0 1 22441 4 14 15277 10 0 1 22447 1 22444 1 22447 2 3 22446 1 22447 3 22444 3 0 1 22447 4 3 16286 5 0 1 22453 1 22448 1 22453 2 5 22452 1 22453 3 22448 2 0 1 22453 4 5 11570 7 0 1 22469 1 22467 1 22469 2 2 22465 1 22469 3 22467 3 0 1 22469 4 2 18906 6 0 1 22481 1 22478 1 22481 2 3 22480 1 22481 3 22478 1 0 1 22481 4 3 20688 7 0 1 22483 1 22481 1 22483 2 2 22479 1 22483 3 22481 2 0 1 22483 4 2 13033 1 0 1 22501 1 22499 1 22501 2 2 22500 1 22501 3 22499 4 0 1 22501 4 2 12237 3 0 1 22511 1 22500 1 22511 2 11 22510 1 22511 3 22500 1 0 1 22511 4 11 19183 5 0 1 22531 1 22529 1 22531 2 2 22530 1 22531 3 22529 4 0 1 22531 4 2 22271 2 0 1 22541 1 22538 1 22541 2 3 22539 1 22541 3 22538 1 0 1 22541 4 3 22533 10 0 1 22543 1 22540 1 22543 2 3 22541 1 22543 3 22540 1 0 1 22543 4 3 20698 6 0 1 22549 1 22547 1 22549 2 2 22545 1 22549 3 22547 2 0 1 22549 4 2 19242 6 0 1 22567 1 22564 1 22567 2 3 22565 1 22567 3 22564 3 0 1 22567 4 3 14944 15 0 1 22571 1 22565 1 22571 2 6 22569 1 22571 3 22565 2 0 1 22571 4 6 22561 7 0 1 22573 1 22567 1 22573 2 6 22572 1 22573 3 22567 7 0 1 22573 4 6 12988 6 0 1 22613 1 22611 1 22613 2 2 22608 1 22613 3 22611 2 0 1 22613 4 2 13162 2 0 1 22619 1 22617 1 22619 2 2 22612 1 22619 3 22617 2 0 1 22619 4 2 19196 0 0 1 22621 1 22619 1 22621 2 2 22617 1 22621 3 22619 2 0 1 22621 4 2 20510 6 0 1 22637 1 22635 1 22637 2 2 22631 1 22637 3 22635 5 0 1 22637 4 2 17813 1 0 1 22639 1 22633 1 22639 2 6 22638 1 22639 3 22633 2 0 1 22639 4 6 22076 2 0 1 22643 1 22641 1 22643 2 2 22639 1 22643 3 22641 2 0 1 22643 4 2 14386 7 0 1 22651 1 22648 1 22651 2 3 22650 1 22651 3 22648 1 0 1 22651 4 3 17235 2 0 1 22669 1 22667 1 22669 2 2 22668 1 22669 3 22667 5 0 1 22669 4 2 15799 7 0 1 22679 1 22666 1 22679 2 13 22677 1 22679 3 22666 1 0 1 22679 4 13 13290 3 0 1 22691 1 22689 1 22691 2 2 22687 1 22691 3 22689 2 0 1 22691 4 2 20225 8 0 1 22697 1 22694 1 22697 2 3 22691 1 22697 3 22694 6 0 1 22697 4 3 22175 1 0 1 22699 1 22687 1 22699 2 12 22698 1 22699 3 22687 1 0 1 22699 4 12 19604 2 0 1 22709 1 22707 1 22709 2 2 22704 1 22709 3 22707 2 0 1 22709 4 2 21768 15 0 1 22717 1 22715 1 22717 2 2 22713 1 22717 3 22715 6 0 1 22717 4 2 22380 6 0 1 22721 1 22718 1 22721 2 3 22720 1 22721 3 22718 5 0 1 22721 4 3 20033 7 0 1 22727 1 22722 1 22727 2 5 22719 1 22727 3 22722 7 0 1 22727 4 5 13027 3 0 1 22739 1 22737 1 22739 2 2 22738 1 22739 3 22737 4 0 1 22739 4 2 12192 4 0 1 22741 1 22734 1 22741 2 7 22739 1 22741 3 22734 2 0 1 22741 4 7 17229 9 0 1 22751 1 22730 1 22751 2 21 22749 1 22751 3 22730 2 0 1 22751 4 21 18369 3 0 1 22769 1 22766 1 22769 2 3 22768 1 22769 3 22766 3 0 1 22769 4 3 16921 7 0 1 22777 1 22770 1 22777 2 7 22774 1 22777 3 22770 2 0 1 22777 4 7 13091 10 0 1 22783 1 22780 1 22783 2 3 22782 1 22783 3 22780 1 0 1 22783 4 3 21890 5 0 1 22787 1 22785 1 22787 2 2 22783 1 22787 3 22785 3 0 1 22787 4 2 11840 7 0 1 22807 1 22804 1 22807 2 3 22805 1 22807 3 22804 4 0 1 22807 4 3 22803 4 0 1 22811 1 22805 1 22811 2 6 22809 1 22811 3 22805 2 0 1 22811 4 6 22226 5 0 1 22817 1 22814 1 22817 2 3 22811 1 22817 3 22814 8 0 1 22817 4 3 12875 1 0 1 22853 1 22851 1 22853 2 2 22849 1 22853 3 22851 2 0 1 22853 4 2 11699 6 0 1 22859 1 22857 1 22859 2 2 22852 1 22859 3 22857 7 0 1 22859 4 2 13165 0 0 1 22861 1 22859 1 22861 2 2 22860 1 22861 3 22859 7 0 1 22861 4 2 11777 7 0 1 22871 1 22864 1 22871 2 7 22870 1 22871 3 22864 4 0 1 22871 4 7 22862 4 0 1 22877 1 22875 1 22877 2 2 22873 1 22877 3 22875 3 0 1 22877 4 2 15815 6 0 1 22901 1 22899 1 22901 2 2 22897 1 22901 3 22899 2 0 1 22901 4 2 22473 7 0 1 22907 1 22902 1 22907 2 5 22902 1 22907 3 22902 3 0 1 22907 4 5 19319 3 0 1 22921 1 22914 1 22921 2 7 22914 1 22921 3 22914 4 0 1 22921 4 7 18100 0 0 1 22937 1 22934 1 22937 2 3 22936 1 22937 3 22934 3 0 1 22937 4 3 12673 6 0 1 22943 1 22938 1 22943 2 5 22940 1 22943 3 22938 2 0 1 22943 4 5 15087 9 0 1 22961 1 22955 1 22961 2 6 22960 1 22961 3 22955 1 0 1 22961 4 6 19430 7 0 1 22963 1 22960 1 22963 2 3 22962 1 22963 3 22960 4 0 1 22963 4 3 12220 2 0 1 22973 1 22971 1 22973 2 2 22972 1 22973 3 22971 3 0 1 22973 4 2 22634 9 0 1 22993 1 22988 1 22993 2 5 22992 1 22993 3 22988 3 0 1 22993 4 5 20272 6 0 1 23003 1 23001 1 23003 2 2 22993 1 23003 3 23001 11 0 1 23003 4 2 18086 2 0 1 23011 1 23004 1 23011 2 7 23009 1 23011 3 23004 5 0 1 23011 4 7 15883 6 0 1 23017 1 23012 1 23017 2 5 23016 1 23017 3 23012 3 0 1 23017 4 5 20398 6 0 1 23021 1 23019 1 23021 2 2 23020 1 23021 3 23019 3 0 1 23021 4 2 21707 4 0 1 23027 1 23025 1 23027 2 2 23023 1 23027 3 23025 3 0 1 23027 4 2 19504 7 0 1 23029 1 23027 1 23029 2 2 23025 1 23029 3 23027 6 0 1 23029 4 2 15045 6 0 1 23039 1 23032 1 23039 2 7 23038 1 23039 3 23032 5 0 1 23039 4 7 16180 10 0 1 23041 1 23030 1 23041 2 11 23036 1 23041 3 23030 1 0 1 23041 4 11 23022 24 0 1 23053 1 23051 1 23053 2 2 23049 1 23053 3 23051 4 0 1 23053 4 2 19444 12 0 1 23057 1 23052 1 23057 2 5 23050 1 23057 3 23052 1 0 1 23057 4 5 16889 1 0 1 23059 1 23056 1 23059 2 3 23042 1 23059 3 23056 4 0 1 23059 4 3 16809 15 0 1 23063 1 23058 1 23063 2 5 23060 1 23063 3 23058 1 0 1 23063 4 5 16943 11 0 1 23071 1 23068 1 23071 2 3 23069 1 23071 3 23068 1 0 1 23071 4 3 17794 6 0 1 23081 1 23078 1 23081 2 3 23075 1 23081 3 23078 1 0 1 23081 4 3 23069 0 0 1 23087 1 23082 1 23087 2 5 23086 1 23087 3 23082 1 0 1 23087 4 5 22201 3 0 1 23099 1 23097 1 23099 2 2 23098 1 23099 3 23097 7 0 1 23099 4 2 16685 12 0 1 23117 1 23115 1 23117 2 2 23113 1 23117 3 23115 3 0 1 23117 4 2 12190 1 0 1 23131 1 23128 1 23131 2 3 23124 1 23131 3 23128 3 0 1 23131 4 3 12649 5 0 1 23143 1 23138 1 23143 2 5 23141 1 23143 3 23138 2 0 1 23143 4 5 23139 3 0 1 23159 1 23148 1 23159 2 11 23153 1 23159 3 23148 1 0 1 23159 4 11 23155 8 0 1 23167 1 23164 1 23167 2 3 23165 1 23167 3 23164 1 0 1 23167 4 3 14687 6 0 1 23173 1 23168 1 23173 2 5 23172 1 23173 3 23168 1 0 1 23173 4 5 21666 6 0 1 23189 1 23187 1 23189 2 2 23188 1 23189 3 23187 3 0 1 23189 4 2 19547 9 0 1 23197 1 23195 1 23197 2 2 23196 1 23197 3 23195 2 0 1 23197 4 2 21941 21 0 1 23201 1 23198 1 23201 2 3 23200 1 23201 3 23198 4 0 1 23201 4 3 19539 7 0 1 23203 1 23200 1 23203 2 3 23198 1 23203 3 23200 4 0 1 23203 4 3 19660 3 0 1 23209 1 23178 1 23209 2 31 23208 1 23209 3 23178 1 0 1 23209 4 31 11886 32 0 1 23227 1 23224 1 23227 2 3 23226 1 23227 3 23224 1 0 1 23227 4 3 13128 5 0 1 23251 1 23249 1 23251 2 2 23247 1 23251 3 23249 5 0 1 23251 4 2 17091 8 0 1 23269 1 23263 1 23269 2 6 23265 1 23269 3 23263 6 0 1 23269 4 6 21069 10 0 1 23279 1 23272 1 23279 2 7 23278 1 23279 3 23272 2 0 1 23279 4 7 22708 6 0 1 23291 1 23285 1 23291 2 6 23290 1 23291 3 23285 1 0 1 23291 4 6 12883 2 0 1 23293 1 23288 1 23293 2 5 23292 1 23293 3 23288 10 0 1 23293 4 5 18037 3 0 1 23297 1 23294 1 23297 2 3 23296 1 23297 3 23294 5 0 1 23297 4 3 14862 18 0 1 23311 1 23308 1 23311 2 3 23310 1 23311 3 23308 5 0 1 23311 4 3 21212 3 0 1 23321 1 23318 1 23321 2 3 23315 1 23321 3 23318 7 0 1 23321 4 3 23309 0 0 1 23327 1 23322 1 23327 2 5 23325 1 23327 3 23322 3 0 1 23327 4 5 21599 10 0 1 23333 1 23331 1 23333 2 2 23329 1 23333 3 23331 3 0 1 23333 4 2 17585 7 0 1 23339 1 23337 1 23339 2 2 23335 1 23339 3 23337 3 0 1 23339 4 2 21157 8 0 1 23357 1 23355 1 23357 2 2 23356 1 23357 3 23355 2 0 1 23357 4 2 14555 6 0 1 23369 1 23366 1 23369 2 3 23364 1 23369 3 23366 1 0 1 23369 4 3 15507 2 0 1 23371 1 23369 1 23371 2 2 23370 1 23371 3 23369 6 0 1 23371 4 2 17462 2 0 1 23399 1 23382 1 23399 2 17 23397 1 23399 3 23382 2 0 1 23399 4 17 23391 3 0 1 23417 1 23414 1 23417 2 3 23408 1 23417 3 23414 1 0 1 23417 4 3 15219 3 0 1 23431 1 23428 1 23431 2 3 23429 1 23431 3 23428 5 0 1 23431 4 3 23427 4 0 1 23447 1 23442 1 23447 2 5 23444 1 23447 3 23442 3 0 1 23447 4 5 18884 6 0 1 23459 1 23457 1 23459 2 2 23450 1 23459 3 23457 2 0 1 23459 4 2 17342 1 0 1 23473 1 23468 1 23473 2 5 23472 1 23473 3 23468 1 0 1 23473 4 5 12620 6 0 1 23497 1 23492 1 23497 2 5 23496 1 23497 3 23492 1 0 1 23497 4 5 23280 6 0 1 23509 1 23507 1 23509 2 2 23508 1 23509 3 23507 4 0 1 23509 4 2 18922 3 0 1 23531 1 23529 1 23531 2 2 23526 1 23531 3 23529 2 0 1 23531 4 2 20955 3 0 1 23537 1 23534 1 23537 2 3 23536 1 23537 3 23534 3 0 1 23537 4 3 20947 6 0 1 23539 1 23537 1 23539 2 2 23534 1 23539 3 23537 6 0 1 23539 4 2 13023 3 0 1 23549 1 23547 1 23549 2 2 23545 1 23549 3 23547 3 0 1 23549 4 2 16278 12 0 1 23557 1 23552 1 23557 2 5 23554 1 23557 3 23552 2 0 1 23557 4 5 13162 9 0 1 23561 1 23558 1 23561 2 3 23556 1 23561 3 23558 3 0 1 23561 4 3 13414 2 0 1 23563 1 23561 1 23563 2 2 23559 1 23563 3 23561 6 0 1 23563 4 2 22059 8 0 1 23567 1 23562 1 23567 2 5 23562 1 23567 3 23562 2 0 1 23567 4 5 15639 6 0 1 23581 1 23575 1 23581 2 6 23577 1 23581 3 23575 9 0 1 23581 4 6 23577 6 0 1 23593 1 23588 1 23593 2 5 23592 1 23593 3 23588 2 0 1 23593 4 5 13402 6 0 1 23599 1 23596 1 23599 2 3 23597 1 23599 3 23596 5 0 1 23599 4 3 23595 4 0 1 23603 1 23601 1 23603 2 2 23602 1 23603 3 23601 2 0 1 23603 4 2 20737 17 0 1 23609 1 23603 1 23609 2 6 23606 1 23609 3 23603 4 0 1 23609 4 6 12496 9 0 1 23623 1 23617 1 23623 2 6 23620 1 23623 3 23617 7 0 1 23623 4 6 20619 5 0 1 23627 1 23625 1 23627 2 2 23623 1 23627 3 23625 3 0 1 23627 4 2 20095 8 0 1 23629 1 23627 1 23629 2 2 23625 1 23629 3 23627 2 0 1 23629 4 2 22694 10 0 1 23633 1 23628 1 23633 2 5 23628 1 23633 3 23628 3 0 1 23633 4 5 22258 8 0 1 23663 1 23658 1 23663 2 5 23661 1 23663 3 23658 1 0 1 23663 4 5 14091 5 0 1 23669 1 23667 1 23669 2 2 23662 1 23669 3 23667 5 0 1 23669 4 2 22391 4 0 1 23671 1 23668 1 23671 2 3 23670 1 23671 3 23668 8 0 1 23671 4 3 13774 2 0 1 23677 1 23672 1 23677 2 5 23676 1 23677 3 23672 3 0 1 23677 4 5 17965 3 0 1 23687 1 23682 1 23687 2 5 23685 1 23687 3 23682 1 0 1 23687 4 5 23683 3 0 1 23689 1 23678 1 23689 2 11 23684 1 23689 3 23678 3 0 1 23689 4 11 17232 16 0 1 23719 1 23713 1 23719 2 6 23717 1 23719 3 23713 1 0 1 23719 4 6 17194 3 0 1 23741 1 23739 1 23741 2 2 23737 1 23741 3 23739 3 0 1 23741 4 2 14491 12 0 1 23743 1 23740 1 23743 2 3 23738 1 23743 3 23740 6 0 1 23743 4 3 12127 6 0 1 23747 1 23745 1 23747 2 2 23746 1 23747 3 23745 2 0 1 23747 4 2 21173 10 0 1 23753 1 23750 1 23753 2 3 23747 1 23753 3 23750 3 0 1 23753 4 3 21853 25 0 1 23761 1 23754 1 23761 2 7 23754 1 23761 3 23754 1 0 1 23761 4 7 13633 0 0 1 23767 1 23764 1 23767 2 3 23766 1 23767 3 23764 3 0 1 23767 4 3 22423 5 0 1 23773 1 23768 1 23773 2 5 23770 1 23773 3 23768 1 0 1 23773 4 5 22420 11 0 1 23789 1 23787 1 23789 2 2 23788 1 23789 3 23787 10 0 1 23789 4 2 20966 3 0 1 23801 1 23798 1 23801 2 3 23791 1 23801 3 23798 1 0 1 23801 4 3 18160 22 0 1 23813 1 23811 1 23813 2 2 23809 1 23813 3 23811 2 0 1 23813 4 2 23057 1 0 1 23819 1 23817 1 23819 2 2 23811 1 23819 3 23817 5 0 1 23819 4 2 19293 2 0 1 23827 1 23825 1 23827 2 2 23826 1 23827 3 23825 2 0 1 23827 4 2 23820 8 0 1 23831 1 23820 1 23831 2 11 23827 1 23831 3 23820 1 0 1 23831 4 11 18265 6 0 1 23833 1 23828 1 23833 2 5 23830 1 23833 3 23828 1 0 1 23833 4 5 23822 14 0 1 23857 1 23852 1 23857 2 5 23856 1 23857 3 23852 2 0 1 23857 4 5 13498 6 0 1 23869 1 23867 1 23869 2 2 23863 1 23869 3 23867 6 0 1 23869 4 2 14180 8 0 1 23873 1 23870 1 23873 2 3 23868 1 23873 3 23870 4 0 1 23873 4 3 13312 0 0 1 23879 1 23872 1 23879 2 7 23878 1 23879 3 23872 1 0 1 23879 4 7 12533 2 0 1 23887 1 23884 1 23887 2 3 23886 1 23887 3 23884 4 0 1 23887 4 3 21324 5 0 1 23893 1 23888 1 23893 2 5 23892 1 23893 3 23888 1 0 1 23893 4 5 21391 3 0 1 23899 1 23897 1 23899 2 2 23895 1 23899 3 23897 6 0 1 23899 4 2 20028 8 0 1 23909 1 23907 1 23909 2 2 23905 1 23909 3 23907 2 0 1 23909 4 2 16857 6 0 1 23911 1 23905 1 23911 2 6 23910 1 23911 3 23905 2 0 1 23911 4 6 22897 2 0 1 23917 1 23915 1 23917 2 2 23916 1 23917 3 23915 6 0 1 23917 4 2 18746 6 0 1 23929 1 23922 1 23929 2 7 23926 1 23929 3 23922 5 0 1 23929 4 7 13359 24 0 1 23957 1 23955 1 23957 2 2 23950 1 23957 3 23955 2 0 1 23957 4 2 18108 2 0 1 23971 1 23961 1 23971 2 10 23969 1 23971 3 23961 2 0 1 23971 4 10 21167 0 0 1 23977 1 23972 1 23977 2 5 23976 1 23977 3 23972 1 0 1 23977 4 5 16580 6 0 1 23981 1 23978 1 23981 2 3 23979 1 23981 3 23978 4 0 1 23981 4 3 23977 4 0 1 23993 1 23990 1 23993 2 3 23985 1 23993 3 23990 3 0 1 23993 4 3 17629 2 0 1 24001 1 23987 1 24001 2 14 23998 1 24001 3 23987 4 0 1 24001 4 14 19905 14 0 1 24007 1 23990 1 24007 2 17 24005 1 24007 3 23990 4 0 1 24007 4 17 23999 3 0 1 24019 1 24017 1 24019 2 2 24015 1 24019 3 24017 2 0 1 24019 4 2 21463 8 0 1 24023 1 24018 1 24023 2 5 24021 1 24023 3 24018 2 0 1 24023 4 5 24019 3 0 1 24029 1 24027 1 24029 2 2 24025 1 24029 3 24027 3 0 1 24029 4 2 17813 1 0 1 24043 1 24041 1 24043 2 2 24042 1 24043 3 24041 2 0 1 24043 4 2 19923 7 0 1 24049 1 24030 1 24049 2 19 24046 1 24049 3 24030 3 0 1 24049 4 19 17444 20 0 1 24061 1 24051 1 24061 2 10 24060 1 24061 3 24051 3 0 1 24061 4 10 15322 14 0 1 24071 1 24060 1 24071 2 11 24070 1 24071 3 24060 2 0 1 24071 4 11 22963 2 0 1 24077 1 24075 1 24077 2 2 24073 1 24077 3 24075 7 0 1 24077 4 2 21575 6 0 1 24083 1 24081 1 24083 2 2 24082 1 24083 3 24081 2 0 1 24083 4 2 15842 4 0 1 24091 1 24084 1 24091 2 7 24089 1 24091 3 24084 3 0 1 24091 4 7 19002 6 0 1 24097 1 24092 1 24097 2 5 24094 1 24097 3 24092 1 0 1 24097 4 5 18233 10 0 1 24103 1 24098 1 24103 2 5 24101 1 24103 3 24098 3 0 1 24103 4 5 16916 17 0 1 24107 1 24105 1 24107 2 2 24106 1 24107 3 24105 2 0 1 24107 4 2 16265 2 0 1 24109 1 24107 1 24109 2 2 24105 1 24109 3 24107 6 0 1 24109 4 2 15418 6 0 1 24113 1 24110 1 24113 2 3 24107 1 24113 3 24110 3 0 1 24113 4 3 13869 16 0 1 24121 1 24108 1 24121 2 13 24109 1 24121 3 24108 6 0 1 24121 4 13 21986 19 0 1 24133 1 24127 1 24133 2 6 24131 1 24133 3 24127 3 0 1 24133 4 6 18645 10 0 1 24137 1 24134 1 24137 2 3 24131 1 24137 3 24134 1 0 1 24137 4 3 22964 1 0 1 24151 1 24145 1 24151 2 6 24149 1 24151 3 24145 3 0 1 24151 4 6 19583 10 0 1 24169 1 24158 1 24169 2 11 24168 1 24169 3 24158 3 0 1 24169 4 11 23491 12 0 1 24179 1 24177 1 24179 2 2 24175 1 24179 3 24177 3 0 1 24179 4 2 18883 7 0 1 24181 1 24164 1 24181 2 17 24180 1 24181 3 24164 1 0 1 24181 4 17 20864 3 0 1 24197 1 24195 1 24197 2 2 24191 1 24197 3 24195 5 0 1 24197 4 2 20105 1 0 1 24203 1 24201 1 24203 2 2 24199 1 24203 3 24201 3 0 1 24203 4 2 23092 8 0 1 24223 1 24220 1 24223 2 3 24221 1 24223 3 24220 1 0 1 24223 4 3 16011 16 0 1 24229 1 24227 1 24229 2 2 24225 1 24229 3 24227 6 0 1 24229 4 2 12395 12 0 1 24239 1 24226 1 24239 2 13 24237 1 24239 3 24226 5 0 1 24239 4 13 17548 3 0 1 24247 1 24244 1 24247 2 3 24242 1 24247 3 24244 1 0 1 24247 4 3 15502 6 0 1 24251 1 24245 1 24251 2 6 24249 1 24251 3 24245 7 0 1 24251 4 6 24241 7 0 1 24281 1 24278 1 24281 2 3 24269 1 24281 3 24278 7 0 1 24281 4 3 23583 0 0 1 24317 1 24315 1 24317 2 2 24316 1 24317 3 24315 2 0 1 24317 4 2 19371 3 0 1 24329 1 24326 1 24329 2 3 24328 1 24329 3 24326 3 0 1 24329 4 3 13839 4 0 1 24337 1 24332 1 24337 2 5 24332 1 24337 3 24332 1 0 1 24337 4 5 13634 15 0 1 24359 1 24348 1 24359 2 11 24357 1 24359 3 24348 2 0 1 24359 4 11 18118 3 0 1 24371 1 24369 1 24371 2 2 24367 1 24371 3 24369 4 0 1 24371 4 2 16480 7 0 1 24373 1 24366 1 24373 2 7 24371 1 24373 3 24366 2 0 1 24373 4 7 14265 4 0 1 24379 1 24377 1 24379 2 2 24375 1 24379 3 24377 5 0 1 24379 4 2 19135 1 0 1 24391 1 24388 1 24391 2 3 24389 1 24391 3 24388 4 0 1 24391 4 3 23642 3 0 1 24407 1 24402 1 24407 2 5 24405 1 24407 3 24402 1 0 1 24407 4 5 16779 8 0 1 24413 1 24411 1 24413 2 2 24405 1 24413 3 24411 3 0 1 24413 4 2 20485 5 0 1 24419 1 24417 1 24419 2 2 24418 1 24419 3 24417 3 0 1 24419 4 2 17258 4 0 1 24421 1 24414 1 24421 2 7 24419 1 24421 3 24414 2 0 1 24421 4 7 14717 12 0 1 24439 1 24433 1 24439 2 6 24435 1 24439 3 24433 2 0 1 24439 4 6 24435 6 0 1 24443 1 24441 1 24443 2 2 24442 1 24443 3 24441 7 0 1 24443 4 2 18400 2 0 1 24469 1 24455 1 24469 2 14 24466 1 24469 3 24455 2 0 1 24469 4 14 20631 1 0 1 24473 1 24470 1 24473 2 3 24467 1 24473 3 24470 12 0 1 24473 4 3 22810 1 0 1 24481 1 24470 1 24481 2 11 24472 1 24481 3 24470 4 0 1 24481 4 11 20309 20 0 1 24499 1 24497 1 24499 2 2 24495 1 24499 3 24497 5 0 1 24499 4 2 19662 1 0 1 24509 1 24507 1 24509 2 2 24501 1 24509 3 24507 3 0 1 24509 4 2 20791 0 0 1 24517 1 24512 1 24517 2 5 24512 1 24517 3 24512 6 0 1 24517 4 5 14823 10 0 1 24527 1 24522 1 24527 2 5 24510 1 24527 3 24522 1 0 1 24527 4 5 21810 19 0 1 24533 1 24531 1 24533 2 2 24532 1 24533 3 24531 3 0 1 24533 4 2 13522 6 0 1 24547 1 24545 1 24547 2 2 24546 1 24547 3 24545 5 0 1 24547 4 2 17155 7 0 1 24551 1 24544 1 24551 2 7 24550 1 24551 3 24544 3 0 1 24551 4 7 24542 4 0 1 24571 1 24564 1 24571 2 7 24569 1 24571 3 24564 1 0 1 24571 4 7 22890 6 0 1 24593 1 24590 1 24593 2 3 24592 1 24593 3 24590 1 0 1 24593 4 3 23409 6 0 1 24611 1 24598 1 24611 2 13 24607 1 24611 3 24598 2 0 1 24611 4 13 13355 7 0 1 24623 1 24618 1 24623 2 5 24622 1 24623 3 24618 2 0 1 24623 4 5 24401 3 0 1 24631 1 24628 1 24631 2 3 24630 1 24631 3 24628 3 0 1 24631 4 3 18822 2 0 1 24659 1 24657 1 24659 2 2 24658 1 24659 3 24657 12 0 1 24659 4 2 24387 2 0 1 24671 1 24660 1 24671 2 11 24670 1 24671 3 24660 2 0 1 24671 4 11 12472 4 0 1 24677 1 24675 1 24677 2 2 24673 1 24677 3 24675 3 0 1 24677 4 2 21473 6 0 1 24683 1 24681 1 24683 2 2 24677 1 24683 3 24681 4 0 1 24683 4 2 20298 0 0 1 24691 1 24689 1 24691 2 2 24687 1 24691 3 24689 4 0 1 24691 4 2 12606 9 0 1 24697 1 24692 1 24697 2 5 24694 1 24697 3 24692 7 0 1 24697 4 5 24686 14 0 1 24709 1 24707 1 24709 2 2 24705 1 24709 3 24707 6 0 1 24709 4 2 17368 10 0 1 24733 1 24731 1 24733 2 2 24729 1 24733 3 24731 6 0 1 24733 4 2 20705 12 0 1 24749 1 24747 1 24749 2 2 24745 1 24749 3 24747 3 0 1 24749 4 2 19862 6 0 1 24763 1 24761 1 24763 2 2 24759 1 24763 3 24761 6 0 1 24763 4 2 15839 8 0 1 24767 1 24762 1 24767 2 5 24766 1 24767 3 24762 1 0 1 24767 4 5 23274 2 0 1 24781 1 24779 1 24781 2 2 24777 1 24781 3 24779 2 0 1 24781 4 2 19579 10 0 1 24793 1 24788 1 24793 2 5 24790 1 24793 3 24788 1 0 1 24793 4 5 15414 10 0 1 24799 1 24793 1 24799 2 6 24798 1 24799 3 24793 1 0 1 24799 4 6 15233 3 0 1 24809 1 24803 1 24809 2 6 24806 1 24809 3 24803 2 0 1 24809 4 6 23226 15 0 1 24821 1 24819 1 24821 2 2 24820 1 24821 3 24819 3 0 1 24821 4 2 16665 9 0 1 24841 1 24827 1 24841 2 14 24839 1 24841 3 24827 1 0 1 24841 4 14 14749 9 0 1 24847 1 24844 1 24847 2 3 24845 1 24847 3 24844 5 0 1 24847 4 3 17856 6 0 1 24851 1 24849 1 24851 2 2 24846 1 24851 3 24849 2 0 1 24851 4 2 24434 9 0 1 24859 1 24857 1 24859 2 2 24855 1 24859 3 24857 2 0 1 24859 4 2 22967 8 0 1 24877 1 24872 1 24877 2 5 24874 1 24877 3 24872 1 0 1 24877 4 5 19054 1 0 1 24889 1 24878 1 24889 2 11 24884 1 24889 3 24878 3 0 1 24889 4 11 24870 24 0 1 24907 1 24905 1 24907 2 2 24903 1 24907 3 24905 4 0 1 24907 4 2 18748 14 0 1 24917 1 24915 1 24917 2 2 24913 1 24917 3 24915 3 0 1 24917 4 2 15180 6 0 1 24919 1 24916 1 24919 2 3 24917 1 24919 3 24916 1 0 1 24919 4 3 19134 3 0 1 24923 1 24921 1 24923 2 2 24922 1 24923 3 24921 2 0 1 24923 4 2 12901 2 0 1 24943 1 24938 1 24943 2 5 24942 1 24943 3 24938 2 0 1 24943 4 5 22421 2 0 1 24953 1 24950 1 24953 2 3 24948 1 24953 3 24950 7 0 1 24953 4 3 12957 0 0 1 24967 1 24964 1 24967 2 3 24966 1 24967 3 24964 7 0 1 24967 4 3 15797 5 0 1 24971 1 24969 1 24971 2 2 24967 1 24971 3 24969 3 0 1 24971 4 2 18660 7 0 1 24977 1 24974 1 24977 2 3 24976 1 24977 3 24974 10 0 1 24977 4 3 23990 7 0 1 24979 1 24977 1 24979 2 2 24978 1 24979 3 24977 4 0 1 24979 4 2 23765 6 0 1 24989 1 24987 1 24989 2 2 24988 1 24989 3 24987 3 0 1 24989 4 2 21711 3 0 1 25013 1 25011 1 25013 2 2 25009 1 25013 3 25011 3 0 1 25013 4 2 21530 6 0 1 25031 1 25018 1 25031 2 13 25029 1 25031 3 25018 6 0 1 25031 4 13 18502 3 0 1 25033 1 25028 1 25033 2 5 25032 1 25033 3 25028 3 0 1 25033 4 5 20483 12 0 1 25037 1 25035 1 25037 2 2 25033 1 25037 3 25035 2 0 1 25037 4 2 22014 1 0 1 25057 1 25052 1 25057 2 5 25056 1 25057 3 25052 1 0 1 25057 4 5 17482 6 0 1 25073 1 25070 1 25073 2 3 25067 1 25073 3 25070 6 0 1 25073 4 3 24625 1 0 1 25087 1 25084 1 25087 2 3 25086 1 25087 3 25084 1 0 1 25087 4 3 18369 2 0 1 25097 1 25094 1 25097 2 3 25092 1 25097 3 25094 3 0 1 25097 4 3 22684 0 0 1 25111 1 25108 1 25111 2 3 25109 1 25111 3 25108 1 0 1 25111 4 3 23263 3 0 1 25117 1 25112 1 25117 2 5 25116 1 25117 3 25112 10 0 1 25117 4 5 19643 6 0 1 25121 1 25118 1 25121 2 3 25120 1 25121 3 25118 3 0 1 25121 4 3 13068 7 0 1 25127 1 25122 1 25127 2 5 25125 1 25127 3 25122 1 0 1 25127 4 5 15511 8 0 1 25147 1 25145 1 25147 2 2 25146 1 25147 3 25145 2 0 1 25147 4 2 24323 2 0 1 25153 1 25143 1 25153 2 10 25152 1 25153 3 25143 5 0 1 25153 4 10 24581 6 0 1 25163 1 25161 1 25163 2 2 25159 1 25163 3 25161 3 0 1 25163 4 2 17257 11 0 1 25169 1 25166 1 25169 2 3 25158 1 25169 3 25166 8 0 1 25169 4 3 24153 8 0 1 25171 1 25168 1 25171 2 3 25160 1 25171 3 25168 3 0 1 25171 4 3 19305 0 0 1 25183 1 25178 1 25183 2 5 25182 1 25183 3 25178 21 0 1 25183 4 5 25164 20 0 1 25189 1 25187 1 25189 2 2 25188 1 25189 3 25187 4 0 1 25189 4 2 15569 3 0 1 25219 1 25217 1 25219 2 2 25210 1 25219 3 25217 6 0 1 25219 4 2 13660 6 0 1 25229 1 25227 1 25229 2 2 25225 1 25229 3 25227 2 0 1 25229 4 2 15951 12 0 1 25237 1 25235 1 25237 2 2 25233 1 25237 3 25235 4 0 1 25237 4 2 12796 9 0 1 25243 1 25241 1 25243 2 2 25239 1 25243 3 25241 4 0 1 25243 4 2 20249 10 0 1 25247 1 25242 1 25247 2 5 25246 1 25247 3 25242 2 0 1 25247 4 5 18166 2 0 1 25253 1 25251 1 25253 2 2 25249 1 25253 3 25251 3 0 1 25253 4 2 16484 7 0 1 25261 1 25254 1 25261 2 7 25259 1 25261 3 25254 4 0 1 25261 4 7 23105 15 0 1 25301 1 25298 1 25301 2 3 25299 1 25301 3 25298 4 0 1 25301 4 3 25297 4 0 1 25303 1 25300 1 25303 2 3 25301 1 25303 3 25300 1 0 1 25303 4 3 20395 3 0 1 25307 1 25305 1 25307 2 2 25303 1 25307 3 25305 4 0 1 25307 4 2 23849 7 0 1 25309 1 25296 1 25309 2 13 25300 1 25309 3 25296 1 0 1 25309 4 13 17876 11 0 1 25321 1 25302 1 25321 2 19 25302 1 25321 3 25302 2 0 1 25321 4 19 17706 8 0 1 25339 1 25336 1 25339 2 3 25338 1 25339 3 25336 17 0 1 25339 4 3 14839 2 0 1 25343 1 25338 1 25343 2 5 25341 1 25343 3 25338 1 0 1 25343 4 5 23928 10 0 1 25349 1 25347 1 25349 2 2 25345 1 25349 3 25347 4 0 1 25349 4 2 15950 12 0 1 25357 1 25355 1 25357 2 2 25356 1 25357 3 25355 2 0 1 25357 4 2 16390 7 0 1 25367 1 25362 1 25367 2 5 25366 1 25367 3 25362 5 0 1 25367 4 5 24452 7 0 1 25373 1 25371 1 25373 2 2 25372 1 25373 3 25371 3 0 1 25373 4 2 18348 21 0 1 25391 1 25384 1 25391 2 7 25390 1 25391 3 25384 1 0 1 25391 4 7 24563 2 0 1 25409 1 25406 1 25409 2 3 25408 1 25409 3 25406 3 0 1 25409 4 3 16382 7 0 1 25411 1 25404 1 25411 2 7 25409 1 25411 3 25404 1 0 1 25411 4 7 17404 6 0 1 25423 1 25420 1 25423 2 3 25422 1 25423 3 25420 11 0 1 25423 4 3 20629 5 0 1 25439 1 25432 1 25439 2 7 25435 1 25439 3 25432 9 0 1 25439 4 7 15607 6 0 1 25447 1 25444 1 25447 2 3 25445 1 25447 3 25444 13 0 1 25447 4 3 20273 6 0 1 25453 1 25451 1 25453 2 2 25443 1 25453 3 25451 4 0 1 25453 4 2 24739 2 0 1 25457 1 25454 1 25457 2 3 25445 1 25457 3 25454 1 0 1 25457 4 3 18293 0 0 1 25463 1 25458 1 25463 2 5 25462 1 25463 3 25458 5 0 1 25463 4 5 18607 3 0 1 25469 1 25467 1 25469 2 2 25468 1 25469 3 25467 3 0 1 25469 4 2 25462 8 0 1 25471 1 25465 1 25471 2 6 25470 1 25471 3 25465 3 0 1 25471 4 6 16657 3 0 1 25523 1 25521 1 25523 2 2 25518 1 25523 3 25521 4 0 1 25523 4 2 24349 3 0 1 25537 1 25527 1 25537 2 10 25536 1 25537 3 25527 2 0 1 25537 4 10 13603 14 0 1 25541 1 25539 1 25541 2 2 25537 1 25541 3 25539 3 0 1 25541 4 2 21841 1 0 1 25561 1 25550 1 25561 2 11 25560 1 25561 3 25550 3 0 1 25561 4 11 18210 30 0 1 25577 1 25574 1 25577 2 3 25576 1 25577 3 25574 3 0 1 25577 4 3 20220 6 0 1 25579 1 25577 1 25579 2 2 25575 1 25579 3 25577 6 0 1 25579 4 2 25025 8 0 1 25583 1 25578 1 25583 2 5 25581 1 25583 3 25578 6 0 1 25583 4 5 20849 5 0 1 25589 1 25587 1 25589 2 2 25581 1 25589 3 25587 5 0 1 25589 4 2 17836 0 0 1 25601 1 25598 1 25601 2 3 25583 1 25601 3 25598 8 0 1 25601 4 3 19529 6 0 1 25603 1 25601 1 25603 2 2 25599 1 25603 3 25601 5 0 1 25603 4 2 14069 8 0 1 25609 1 25602 1 25609 2 7 25598 1 25609 3 25602 1 0 1 25609 4 7 25333 18 0 1 25621 1 25611 1 25621 2 10 25618 1 25621 3 25611 7 0 1 25621 4 10 17653 9 0 1 25633 1 25628 1 25633 2 5 25632 1 25633 3 25628 5 0 1 25633 4 5 16896 6 0 1 25639 1 25636 1 25639 2 3 25637 1 25639 3 25636 3 0 1 25639 4 3 23467 3 0 1 25643 1 25641 1 25643 2 2 25639 1 25643 3 25641 3 0 1 25643 4 2 15275 8 0 1 25657 1 25652 1 25657 2 5 25652 1 25657 3 25652 1 0 1 25657 4 5 13832 10 0 1 25667 1 25665 1 25667 2 2 25666 1 25667 3 25665 2 0 1 25667 4 2 25660 8 0 1 25673 1 25670 1 25673 2 3 25672 1 25673 3 25670 3 0 1 25673 4 3 14189 6 0 1 25679 1 25668 1 25679 2 11 25678 1 25679 3 25668 7 0 1 25679 4 11 22310 2 0 1 25693 1 25691 1 25693 2 2 25692 1 25693 3 25691 2 0 1 25693 4 2 19927 3 0 1 25703 1 25698 1 25703 2 5 25701 1 25703 3 25698 7 0 1 25703 4 5 20340 9 0 1 25717 1 25715 1 25717 2 2 25716 1 25717 3 25715 2 0 1 25717 4 2 19736 3 0 1 25733 1 25731 1 25733 2 2 25728 1 25733 3 25731 8 0 1 25733 4 2 25455 0 0 1 25741 1 25735 1 25741 2 6 25737 1 25741 3 25735 1 0 1 25741 4 6 17719 2 0 1 25747 1 25745 1 25747 2 2 25743 1 25747 3 25745 5 0 1 25747 4 2 19241 8 0 1 25759 1 25756 1 25759 2 3 25758 1 25759 3 25756 1 0 1 25759 4 3 15974 3 0 1 25763 1 25758 1 25763 2 5 25762 1 25763 3 25758 2 0 1 25763 4 5 15195 2 0 1 25771 1 25769 1 25771 2 2 25767 1 25771 3 25769 8 0 1 25771 4 2 21110 8 0 1 25793 1 25790 1 25793 2 3 25787 1 25793 3 25790 7 0 1 25793 4 3 16061 9 0 1 25799 1 25792 1 25799 2 7 25798 1 25799 3 25792 3 0 1 25799 4 7 23379 2 0 1 25801 1 25794 1 25801 2 7 25788 1 25801 3 25794 2 0 1 25801 4 7 13642 2 0 1 25819 1 25816 1 25819 2 3 25809 1 25819 3 25816 1 0 1 25819 4 3 18669 0 0 1 25841 1 25838 1 25841 2 3 25840 1 25841 3 25838 1 0 1 25841 4 3 17379 4 0 1 25847 1 25842 1 25847 2 5 25844 1 25847 3 25842 3 0 1 25847 4 5 15693 6 0 1 25849 1 25842 1 25849 2 7 25842 1 25849 3 25842 1 0 1 25849 4 7 23130 0 0 1 25867 1 25865 1 25867 2 2 25863 1 25867 3 25865 6 0 1 25867 4 2 17712 8 0 1 25873 1 25863 1 25873 2 10 25863 1 25873 3 25863 6 0 1 25873 4 10 21826 0 0 1 25889 1 25886 1 25889 2 3 25888 1 25889 3 25886 4 0 1 25889 4 3 16880 7 0 1 25903 1 25898 1 25903 2 5 25901 1 25903 3 25898 5 0 1 25903 4 5 17698 10 0 1 25913 1 25910 1 25913 2 3 25912 1 25913 3 25910 1 0 1 25913 4 3 23988 7 0 1 25919 1 25908 1 25919 2 11 25918 1 25919 3 25908 1 0 1 25919 4 11 23765 6 0 1 25931 1 25929 1 25931 2 2 25930 1 25931 3 25929 3 0 1 25931 4 2 24429 2 0 1 25933 1 25931 1 25933 2 2 25932 1 25933 3 25931 2 0 1 25933 4 2 25231 12 0 1 25939 1 25936 1 25939 2 3 25926 1 25939 3 25936 3 0 1 25939 4 3 16606 2 0 1 25943 1 25938 1 25943 2 5 25942 1 25943 3 25938 1 0 1 25943 4 5 16536 5 0 1 25951 1 25948 1 25951 2 3 25950 1 25951 3 25948 1 0 1 25951 4 3 22211 2 0 1 25969 1 25962 1 25969 2 7 25966 1 25969 3 25962 2 0 1 25969 4 7 23150 16 0 1 25981 1 25970 1 25981 2 11 25979 1 25981 3 25970 3 0 1 25981 4 11 16071 0 0 1 25997 1 25995 1 25997 2 2 25990 1 25997 3 25995 2 0 1 25997 4 2 18736 2 0 1 25999 1 25992 1 25999 2 7 25987 1 25999 3 25992 3 0 1 25999 4 7 15883 0 0 1 26003 1 26001 1 26003 2 2 25999 1 26003 3 26001 2 0 1 26003 4 2 23173 7 0 1 26017 1 26012 1 26017 2 5 26014 1 26017 3 26012 1 0 1 26017 4 5 26006 14 0 1 26021 1 26019 1 26021 2 2 26017 1 26021 3 26019 2 0 1 26021 4 2 15677 6 0 1 26029 1 26023 1 26029 2 6 26025 1 26029 3 26023 9 0 1 26029 4 6 18412 10 0 1 26041 1 26028 1 26041 2 13 26038 1 26041 3 26028 10 0 1 26041 4 13 19185 20 0 1 26053 1 26051 1 26053 2 2 26052 1 26053 3 26051 2 0 1 26053 4 2 25471 6 0 1 26083 1 26076 1 26083 2 7 26081 1 26083 3 26076 1 0 1 26083 4 7 17280 11 0 1 26099 1 26097 1 26099 2 2 26098 1 26099 3 26097 3 0 1 26099 4 2 14663 2 0 1 26107 1 26105 1 26107 2 2 26103 1 26107 3 26105 4 0 1 26107 4 2 16461 8 0 1 26111 1 26104 1 26111 2 7 26109 1 26111 3 26104 3 0 1 26111 4 7 25336 5 0 1 26113 1 26106 1 26113 2 7 26102 1 26113 3 26106 4 0 1 26113 4 7 20499 26 0 1 26119 1 26116 1 26119 2 3 26117 1 26119 3 26116 1 0 1 26119 4 3 24356 3 0 1 26141 1 26139 1 26141 2 2 26136 1 26141 3 26139 4 0 1 26141 4 2 21261 8 0 1 26153 1 26150 1 26153 2 3 26152 1 26153 3 26150 5 0 1 26153 4 3 18937 4 0 1 26161 1 26148 1 26161 2 13 26152 1 26161 3 26148 1 0 1 26161 4 13 24227 32 0 1 26171 1 26169 1 26171 2 2 26170 1 26171 3 26169 3 0 1 26171 4 2 26164 8 0 1 26177 1 26174 1 26177 2 3 26176 1 26177 3 26174 1 0 1 26177 4 3 18571 7 0 1 26183 1 26178 1 26183 2 5 26181 1 26183 3 26178 1 0 1 26183 4 5 15893 5 0 1 26189 1 26187 1 26189 2 2 26179 1 26189 3 26187 2 0 1 26189 4 2 19369 2 0 1 26203 1 26200 1 26203 2 3 26198 1 26203 3 26200 1 0 1 26203 4 3 17154 3 0 1 26209 1 26198 1 26209 2 11 26208 1 26209 3 26198 3 0 1 26209 4 11 21110 12 0 1 26227 1 26224 1 26227 2 3 26222 1 26227 3 26224 4 0 1 26227 4 3 18650 3 0 1 26237 1 26235 1 26237 2 2 26233 1 26237 3 26235 3 0 1 26237 4 2 15275 6 0 1 26249 1 26246 1 26249 2 3 26244 1 26249 3 26246 1 0 1 26249 4 3 23205 2 0 1 26251 1 26249 1 26251 2 2 26247 1 26251 3 26249 6 0 1 26251 4 2 15154 8 0 1 26261 1 26259 1 26261 2 2 26257 1 26261 3 26259 5 0 1 26261 4 2 23709 7 0 1 26263 1 26260 1 26263 2 3 26262 1 26263 3 26260 1 0 1 26263 4 3 15154 5 0 1 26267 1 26265 1 26267 2 2 26263 1 26267 3 26265 2 0 1 26267 4 2 24302 7 0 1 26293 1 26287 1 26293 2 6 26291 1 26293 3 26287 2 0 1 26293 4 6 21461 4 0 1 26297 1 26294 1 26297 2 3 26296 1 26297 3 26294 3 0 1 26297 4 3 19083 4 0 1 26309 1 26307 1 26309 2 2 26308 1 26309 3 26307 7 0 1 26309 4 2 19641 3 0 1 26317 1 26311 1 26317 2 6 26316 1 26317 3 26311 6 0 1 26317 4 6 20554 6 0 1 26321 1 26318 1 26321 2 3 26315 1 26321 3 26318 1 0 1 26321 4 3 26309 0 0 1 26339 1 26337 1 26339 2 2 26338 1 26339 3 26337 8 0 1 26339 4 2 24248 2 0 1 26347 1 26344 1 26347 2 3 26346 1 26347 3 26344 3 0 1 26347 4 3 19895 5 0 1 26357 1 26355 1 26357 2 2 26350 1 26357 3 26355 8 0 1 26357 4 2 20207 2 0 1 26371 1 26368 1 26371 2 3 26366 1 26371 3 26368 1 0 1 26371 4 3 23788 3 0 1 26387 1 26385 1 26387 2 2 26382 1 26387 3 26385 5 0 1 26387 4 2 21859 0 0 1 26393 1 26390 1 26393 2 3 26387 1 26393 3 26390 5 0 1 26393 4 3 25460 26 0 1 26399 1 26392 1 26399 2 7 26390 1 26399 3 26392 1 0 1 26399 4 7 20930 11 0 1 26407 1 26402 1 26407 2 5 26405 1 26407 3 26402 2 0 1 26407 4 5 26403 3 0 1 26417 1 26414 1 26417 2 3 26408 1 26417 3 26414 5 0 1 26417 4 3 16448 6 0 1 26423 1 26418 1 26423 2 5 26422 1 26423 3 26418 1 0 1 26423 4 5 15901 7 0 1 26431 1 26428 1 26431 2 3 26429 1 26431 3 26428 1 0 1 26431 4 3 21524 3 0 1 26437 1 26432 1 26437 2 5 26436 1 26437 3 26432 8 0 1 26437 4 5 21196 3 0 1 26449 1 26442 1 26449 2 7 26442 1 26449 3 26442 1 0 1 26449 4 7 18096 0 0 1 26459 1 26457 1 26459 2 2 26452 1 26459 3 26457 7 0 1 26459 4 2 14846 1 0 1 26479 1 26476 1 26479 2 3 26478 1 26479 3 26476 7 0 1 26479 4 3 24093 2 0 1 26489 1 26486 1 26489 2 3 26478 1 26489 3 26486 1 0 1 26489 4 3 14238 8 0 1 26497 1 26492 1 26497 2 5 26492 1 26497 3 26492 5 0 1 26497 4 5 21704 15 0 1 26501 1 26499 1 26501 2 2 26500 1 26501 3 26499 3 0 1 26501 4 2 13544 3 0 1 26513 1 26510 1 26513 2 3 26507 1 26513 3 26510 1 0 1 26513 4 3 18750 1 0 1 26539 1 26537 1 26539 2 2 26535 1 26539 3 26537 6 0 1 26539 4 2 20981 8 0 1 26557 1 26555 1 26557 2 2 26556 1 26557 3 26555 4 0 1 26557 4 2 17024 6 0 1 26561 1 26558 1 26561 2 3 26560 1 26561 3 26558 1 0 1 26561 4 3 24291 7 0 1 26573 1 26571 1 26573 2 2 26569 1 26573 3 26571 3 0 1 26573 4 2 25826 7 0 1 26591 1 26569 1 26591 2 22 26589 1 26591 3 26569 1 0 1 26591 4 22 17105 5 0 1 26597 1 26595 1 26597 2 2 26593 1 26597 3 26595 3 0 1 26597 4 2 15264 7 0 1 26627 1 26625 1 26627 2 2 26626 1 26627 3 26625 2 0 1 26627 4 2 21132 2 0 1 26633 1 26630 1 26633 2 3 26627 1 26633 3 26630 5 0 1 26633 4 3 20767 1 0 1 26641 1 26634 1 26641 2 7 26638 1 26641 3 26634 1 0 1 26641 4 7 20536 17 0 1 26647 1 26644 1 26647 2 3 26645 1 26647 3 26644 1 0 1 26647 4 3 17281 6 0 1 26669 1 26667 1 26669 2 2 26668 1 26669 3 26667 4 0 1 26669 4 2 13629 9 0 1 26681 1 26675 1 26681 2 6 26678 1 26681 3 26675 2 0 1 26681 4 6 13523 0 0 1 26683 1 26681 1 26683 2 2 26682 1 26683 3 26681 2 0 1 26683 4 2 14202 2 0 1 26687 1 26682 1 26687 2 5 26685 1 26687 3 26682 8 0 1 26687 4 5 26683 3 0 1 26693 1 26691 1 26693 2 2 26688 1 26693 3 26691 4 0 1 26693 4 2 25003 8 0 1 26699 1 26697 1 26699 2 2 26693 1 26699 3 26697 2 0 1 26699 4 2 25065 4 0 1 26701 1 26679 1 26701 2 22 26700 1 26701 3 26679 1 0 1 26701 4 22 26068 3 0 1 26711 1 26700 1 26711 2 11 26709 1 26711 3 26700 11 0 1 26711 4 11 14485 10 0 1 26713 1 26703 1 26713 2 10 26712 1 26713 3 26703 2 0 1 26713 4 10 21848 14 0 1 26717 1 26715 1 26717 2 2 26716 1 26717 3 26715 2 0 1 26717 4 2 20892 6 0 1 26723 1 26721 1 26723 2 2 26719 1 26723 3 26721 3 0 1 26723 4 2 17493 7 0 1 26729 1 26726 1 26729 2 3 26719 1 26729 3 26726 4 0 1 26729 4 3 16586 4 0 1 26731 1 26728 1 26731 2 3 26724 1 26731 3 26728 5 0 1 26731 4 3 21780 5 0 1 26737 1 26727 1 26737 2 10 26734 1 26737 3 26727 4 0 1 26737 4 10 25022 8 0 1 26759 1 26746 1 26759 2 13 26757 1 26759 3 26746 6 0 1 26759 4 13 22112 4 0 1 26777 1 26774 1 26777 2 3 26771 1 26777 3 26774 1 0 1 26777 4 3 14760 9 0 1 26783 1 26778 1 26783 2 5 26782 1 26783 3 26778 7 0 1 26783 4 5 19230 2 0 1 26801 1 26798 1 26801 2 3 26795 1 26801 3 26798 8 0 1 26801 4 3 26789 0 0 1 26813 1 26811 1 26813 2 2 26812 1 26813 3 26811 2 0 1 26813 4 2 14508 3 0 1 26821 1 26819 1 26821 2 2 26817 1 26821 3 26819 2 0 1 26821 4 2 14326 6 0 1 26833 1 26828 1 26833 2 5 26828 1 26833 3 26828 2 0 1 26833 4 5 24987 20 0 1 26839 1 26836 1 26839 2 3 26837 1 26839 3 26836 5 0 1 26839 4 3 22643 6 0 1 26849 1 26846 1 26849 2 3 26840 1 26849 3 26846 4 0 1 26849 4 3 19139 3 0 1 26861 1 26859 1 26861 2 2 26854 1 26861 3 26859 2 0 1 26861 4 2 19313 4 0 1 26863 1 26858 1 26863 2 5 26861 1 26863 3 26858 1 0 1 26863 4 5 26859 3 0 1 26879 1 26866 1 26879 2 13 26878 1 26879 3 26866 2 0 1 26879 4 13 26387 4 0 1 26881 1 26870 1 26881 2 11 26876 1 26881 3 26870 3 0 1 26881 4 11 26862 24 0 1 26891 1 26885 1 26891 2 6 26889 1 26891 3 26885 3 0 1 26891 4 6 16896 0 0 1 26893 1 26888 1 26893 2 5 26892 1 26893 3 26888 2 0 1 26893 4 5 24300 22 0 1 26903 1 26898 1 26903 2 5 26902 1 26903 3 26898 2 0 1 26903 4 5 23332 2 0 1 26921 1 26908 1 26921 2 13 26916 1 26921 3 26908 6 0 1 26921 4 13 21832 2 0 1 26927 1 26922 1 26927 2 5 26924 1 26927 3 26922 3 0 1 26927 4 5 22601 4 0 1 26947 1 26945 1 26947 2 2 26943 1 26947 3 26945 6 0 1 26947 4 2 23175 8 0 1 26951 1 26944 1 26951 2 7 26949 1 26951 3 26944 2 0 1 26951 4 7 24429 4 0 1 26953 1 26946 1 26953 2 7 26946 1 26953 3 26946 1 0 1 26953 4 7 16703 21 0 1 26959 1 26953 1 26959 2 6 26955 1 26959 3 26953 3 0 1 26959 4 6 16795 5 0 1 26981 1 26978 1 26981 2 3 26976 1 26981 3 26978 7 0 1 26981 4 3 15016 2 0 1 26987 1 26985 1 26987 2 2 26983 1 26987 3 26985 3 0 1 26987 4 2 17425 18 0 1 26993 1 26990 1 26993 2 3 26992 1 26993 3 26990 6 0 1 26993 4 3 24801 11 0 1 27011 1 27009 1 27011 2 2 27003 1 27011 3 27009 5 0 1 27011 4 2 22922 6 0 1 27017 1 27012 1 27017 2 5 27016 1 27017 3 27012 3 0 1 27017 4 5 18792 4 0 1 27031 1 27025 1 27031 2 6 27029 1 27031 3 27025 6 0 1 27031 4 6 17674 4 0 1 27043 1 27041 1 27043 2 2 27039 1 27043 3 27041 6 0 1 27043 4 2 23086 10 0 1 27059 1 27057 1 27059 2 2 27055 1 27059 3 27057 3 0 1 27059 4 2 15396 7 0 1 27061 1 27059 1 27061 2 2 27057 1 27061 3 27059 6 0 1 27061 4 2 17843 6 0 1 27067 1 27065 1 27067 2 2 27066 1 27067 3 27065 2 0 1 27067 4 2 26664 2 0 1 27073 1 27068 1 27073 2 5 27070 1 27073 3 27068 3 0 1 27073 4 5 26840 16 0 1 27077 1 27075 1 27077 2 2 27073 1 27077 3 27075 3 0 1 27077 4 2 14297 12 0 1 27091 1 27089 1 27091 2 2 27087 1 27091 3 27089 2 0 1 27091 4 2 19090 8 0 1 27103 1 27100 1 27103 2 3 27102 1 27103 3 27100 6 0 1 27103 4 3 14162 5 0 1 27107 1 27105 1 27107 2 2 27106 1 27107 3 27105 2 0 1 27107 4 2 21945 10 0 1 27109 1 27102 1 27109 2 7 27103 1 27109 3 27102 4 0 1 27109 4 7 27105 4 0 1 27127 1 27124 1 27127 2 3 27125 1 27127 3 27124 4 0 1 27127 4 3 15454 3 0 1 27143 1 27138 1 27143 2 5 27141 1 27143 3 27138 5 0 1 27143 4 5 26211 5 0 1 27179 1 27177 1 27179 2 2 27175 1 27179 3 27177 3 0 1 27179 4 2 20628 9 0 1 27191 1 27165 1 27191 2 26 27189 1 27191 3 27165 2 0 1 27191 4 26 22000 4 0 1 27197 1 27195 1 27197 2 2 27192 1 27197 3 27195 4 0 1 27197 4 2 19228 7 0 1 27211 1 27201 1 27211 2 10 27210 1 27211 3 27201 4 0 1 27211 4 10 13925 2 0 1 27239 1 27232 1 27239 2 7 27238 1 27239 3 27232 2 0 1 27239 4 7 27230 4 0 1 27241 1 27224 1 27241 2 17 27238 1 27241 3 27224 4 0 1 27241 4 17 22918 20 0 1 27253 1 27251 1 27253 2 2 27249 1 27253 3 27251 6 0 1 27253 4 2 23503 10 0 1 27259 1 27257 1 27259 2 2 27255 1 27259 3 27257 2 0 1 27259 4 2 22941 8 0 1 27271 1 27265 1 27271 2 6 27267 1 27271 3 27265 3 0 1 27271 4 6 18035 5 0 1 27277 1 27271 1 27277 2 6 27276 1 27277 3 27271 2 0 1 27277 4 6 21297 12 0 1 27281 1 27275 1 27281 2 6 27278 1 27281 3 27275 1 0 1 27281 4 6 23165 0 0 1 27283 1 27278 1 27283 2 5 27282 1 27283 3 27278 2 0 1 27283 4 5 24149 5 0 1 27299 1 27297 1 27299 2 2 27292 1 27299 3 27297 7 0 1 27299 4 2 18406 1 0 1 27329 1 27326 1 27329 2 3 27323 1 27329 3 27326 1 0 1 27329 4 3 27317 0 0 1 27337 1 27332 1 27337 2 5 27336 1 27337 3 27332 13 0 1 27337 4 5 22681 6 0 1 27361 1 27354 1 27361 2 7 27354 1 27361 3 27354 5 0 1 27361 4 7 23316 0 0 1 27367 1 27364 1 27367 2 3 27366 1 27367 3 27364 12 0 1 27367 4 3 16245 5 0 1 27397 1 27395 1 27397 2 2 27396 1 27397 3 27395 6 0 1 27397 4 2 26553 3 0 1 27407 1 27402 1 27407 2 5 27405 1 27407 3 27402 1 0 1 27407 4 5 26272 8 0 1 27409 1 27396 1 27409 2 13 27408 1 27409 3 27396 1 0 1 27409 4 13 17344 12 0 1 27427 1 27422 1 27427 2 5 27426 1 27427 3 27422 12 0 1 27427 4 5 26705 10 0 1 27431 1 27414 1 27431 2 17 27430 1 27431 3 27414 3 0 1 27431 4 17 20902 2 0 1 27437 1 27435 1 27437 2 2 27433 1 27437 3 27435 10 0 1 27437 4 2 20670 12 0 1 27449 1 27446 1 27449 2 3 27443 1 27449 3 27446 3 0 1 27449 4 3 27437 0 0 1 27457 1 27450 1 27457 2 7 27454 1 27457 3 27450 2 0 1 27457 4 7 25825 8 0 1 27479 1 27472 1 27479 2 7 27478 1 27479 3 27472 7 0 1 27479 4 7 23201 11 0 1 27481 1 27474 1 27481 2 7 27474 1 27481 3 27474 7 0 1 27481 4 7 16721 0 0 1 27487 1 27484 1 27487 2 3 27485 1 27487 3 27484 14 0 1 27487 4 3 14442 3 0 1 27509 1 27507 1 27509 2 2 27504 1 27509 3 27507 16 0 1 27509 4 2 16018 12 0 1 27527 1 27522 1 27527 2 5 27526 1 27527 3 27522 1 0 1 27527 4 5 18273 2 0 1 27529 1 27522 1 27529 2 7 27522 1 27529 3 27522 4 0 1 27529 4 7 18740 0 0 1 27539 1 27537 1 27539 2 2 27535 1 27539 3 27537 3 0 1 27539 4 2 18112 7 0 1 27541 1 27522 1 27541 2 19 27539 1 27541 3 27522 1 0 1 27541 4 19 14327 0 0 1 27551 1 27534 1 27551 2 17 27549 1 27551 3 27534 10 0 1 27551 4 17 27543 3 0 1 27581 1 27579 1 27581 2 2 27577 1 27581 3 27579 2 0 1 27581 4 2 21932 6 0 1 27583 1 27580 1 27583 2 3 27582 1 27583 3 27580 3 0 1 27583 4 3 18630 2 0 1 27611 1 27609 1 27611 2 2 27607 1 27611 3 27609 3 0 1 27611 4 2 18864 13 0 1 27617 1 27614 1 27617 2 3 27616 1 27617 3 27614 4 0 1 27617 4 3 19393 14 0 1 27631 1 27625 1 27631 2 6 27627 1 27631 3 27625 1 0 1 27631 4 6 21856 5 0 1 27647 1 27642 1 27647 2 5 27645 1 27647 3 27642 1 0 1 27647 4 5 26495 5 0 1 27653 1 27651 1 27653 2 2 27649 1 27653 3 27651 3 0 1 27653 4 2 22982 1 0 1 27673 1 27662 1 27673 2 11 27671 1 27673 3 27662 4 0 1 27673 4 11 21682 7 0 1 27689 1 27686 1 27689 2 3 27688 1 27689 3 27686 12 0 1 27689 4 3 15654 7 0 1 27691 1 27688 1 27691 2 3 27684 1 27691 3 27688 3 0 1 27691 4 3 23649 5 0 1 27697 1 27692 1 27697 2 5 27696 1 27697 3 27692 1 0 1 27697 4 5 14230 8 0 1 27701 1 27699 1 27701 2 2 27697 1 27701 3 27699 2 0 1 27701 4 2 22935 12 0 1 27733 1 27731 1 27733 2 2 27732 1 27733 3 27731 2 0 1 27733 4 2 16728 3 0 1 27737 1 27734 1 27737 2 3 27736 1 27737 3 27734 4 0 1 27737 4 3 22452 7 0 1 27739 1 27736 1 27739 2 3 27738 1 27739 3 27736 3 0 1 27739 4 3 15220 2 0 1 27743 1 27738 1 27743 2 5 27738 1 27743 3 27738 1 0 1 27743 4 5 16117 9 0 1 27749 1 27746 1 27749 2 3 27744 1 27749 3 27746 3 0 1 27749 4 3 24376 2 0 1 27751 1 27748 1 27751 2 3 27749 1 27751 3 27748 10 0 1 27751 4 3 27747 4 0 1 27763 1 27760 1 27763 2 3 27762 1 27763 3 27760 8 0 1 27763 4 3 18860 5 0 1 27767 1 27762 1 27767 2 5 27766 1 27767 3 27762 2 0 1 27767 4 5 22807 3 0 1 27773 1 27771 1 27773 2 2 27768 1 27773 3 27771 5 0 1 27773 4 2 17311 2 0 1 27779 1 27777 1 27779 2 2 27778 1 27779 3 27777 3 0 1 27779 4 2 14110 2 0 1 27791 1 27784 1 27791 2 7 27789 1 27791 3 27784 1 0 1 27791 4 7 18896 4 0 1 27793 1 27788 1 27793 2 5 27790 1 27793 3 27788 1 0 1 27793 4 5 27782 14 0 1 27799 1 27792 1 27799 2 7 27796 1 27799 3 27792 17 0 1 27799 4 7 27175 13 0 1 27803 1 27801 1 27803 2 2 27802 1 27803 3 27801 11 0 1 27803 4 2 21069 10 0 1 27809 1 27806 1 27809 2 3 27804 1 27809 3 27806 1 0 1 27809 4 3 25850 2 0 1 27817 1 27812 1 27817 2 5 27812 1 27817 3 27812 3 0 1 27817 4 5 18284 15 0 1 27823 1 27817 1 27823 2 6 27820 1 27823 3 27817 1 0 1 27823 4 6 20444 5 0 1 27827 1 27825 1 27827 2 2 27821 1 27827 3 27825 9 0 1 27827 4 2 14407 4 0 1 27847 1 27841 1 27847 2 6 27846 1 27847 3 27841 1 0 1 27847 4 6 19020 2 0 1 27851 1 27849 1 27851 2 2 27850 1 27851 3 27849 3 0 1 27851 4 2 23955 4 0 1 27883 1 27880 1 27883 2 3 27878 1 27883 3 27880 5 0 1 27883 4 3 17518 3 0 1 27893 1 27891 1 27893 2 2 27892 1 27893 3 27891 2 0 1 27893 4 2 20167 9 0 1 27901 1 27899 1 27901 2 2 27895 1 27901 3 27899 6 0 1 27901 4 2 17018 8 0 1 27917 1 27915 1 27917 2 2 27913 1 27917 3 27915 3 0 1 27917 4 2 21672 7 0 1 27919 1 27916 1 27919 2 3 27917 1 27919 3 27916 1 0 1 27919 4 3 20139 3 0 1 27941 1 27939 1 27941 2 2 27937 1 27941 3 27939 2 0 1 27941 4 2 23222 6 0 1 27943 1 27938 1 27943 2 5 27942 1 27943 3 27938 2 0 1 27943 4 5 25944 9 0 1 27947 1 27945 1 27947 2 2 27946 1 27947 3 27945 3 0 1 27947 4 2 24727 10 0 1 27953 1 27950 1 27953 2 3 27952 1 27953 3 27950 1 0 1 27953 4 3 26759 4 0 1 27961 1 27948 1 27961 2 13 27948 1 27961 3 27948 4 0 1 27961 4 13 27922 0 0 1 27967 1 27964 1 27967 2 3 27965 1 27967 3 27964 3 0 1 27967 4 3 23857 6 0 1 27983 1 27978 1 27983 2 5 27982 1 27983 3 27978 2 0 1 27983 4 5 25214 2 0 1 27997 1 27992 1 27997 2 5 27996 1 27997 3 27992 5 0 1 27997 4 5 18866 6 0 1 28001 1 27998 1 28001 2 3 28000 1 28001 3 27998 4 0 1 28001 4 3 26370 7 0 1 28019 1 28017 1 28019 2 2 28015 1 28019 3 28017 3 0 1 28019 4 2 14907 9 0 1 28027 1 28025 1 28027 2 2 28022 1 28027 3 28025 2 0 1 28027 4 2 23430 2 0 1 28031 1 28012 1 28031 2 19 28030 1 28031 3 28012 2 0 1 28031 4 19 17916 2 0 1 28051 1 28049 1 28051 2 2 28047 1 28051 3 28049 2 0 1 28051 4 2 24860 8 0 1 28057 1 28052 1 28057 2 5 28056 1 28057 3 28052 2 0 1 28057 4 5 19702 12 0 1 28069 1 28062 1 28069 2 7 28063 1 28069 3 28062 1 0 1 28069 4 7 18824 16 0 1 28081 1 28062 1 28081 2 19 28078 1 28081 3 28062 3 0 1 28081 4 19 22235 20 0 1 28087 1 28084 1 28087 2 3 28085 1 28087 3 28084 4 0 1 28087 4 3 25323 6 0 1 28097 1 28094 1 28097 2 3 28091 1 28097 3 28094 5 0 1 28097 4 3 15760 1 0 1 28099 1 28097 1 28099 2 2 28095 1 28099 3 28097 2 0 1 28099 4 2 27228 8 0 1 28109 1 28107 1 28109 2 2 28105 1 28109 3 28107 2 0 1 28109 4 2 23032 7 0 1 28111 1 28108 1 28111 2 3 28110 1 28111 3 28108 1 0 1 28111 4 3 19480 2 0 1 28123 1 28121 1 28123 2 2 28119 1 28123 3 28121 4 0 1 28123 4 2 23818 8 0 1 28151 1 28144 1 28151 2 7 28150 1 28151 3 28144 2 0 1 28151 4 7 22238 2 0 1 28163 1 28161 1 28163 2 2 28159 1 28163 3 28161 3 0 1 28163 4 2 23095 8 0 1 28181 1 28179 1 28181 2 2 28180 1 28181 3 28179 3 0 1 28181 4 2 23797 3 0 1 28183 1 28180 1 28183 2 3 28181 1 28183 3 28180 1 0 1 28183 4 3 28179 4 0 1 28201 1 28190 1 28201 2 11 28198 1 28201 3 28190 3 0 1 28201 4 11 19509 14 0 1 28211 1 28209 1 28211 2 2 28207 1 28211 3 28209 2 0 1 28211 4 2 18436 8 0 1 28219 1 28216 1 28219 2 3 28206 1 28219 3 28216 1 0 1 28219 4 3 21787 3 0 1 28229 1 28227 1 28229 2 2 28220 1 28229 3 28227 3 0 1 28229 4 2 24350 1 0 1 28277 1 28275 1 28277 2 2 28273 1 28277 3 28275 7 0 1 28277 4 2 18350 6 0 1 28279 1 28276 1 28279 2 3 28277 1 28279 3 28276 3 0 1 28279 4 3 18556 6 0 1 28283 1 28281 1 28283 2 2 28282 1 28283 3 28281 3 0 1 28283 4 2 25284 2 0 1 28289 1 28283 1 28289 2 6 28288 1 28289 3 28283 1 0 1 28289 4 6 17328 7 0 1 28297 1 28292 1 28297 2 5 28292 1 28297 3 28292 3 0 1 28297 4 5 21396 15 0 1 28307 1 28305 1 28307 2 2 28306 1 28307 3 28305 2 0 1 28307 4 2 20261 2 0 1 28309 1 28307 1 28309 2 2 28305 1 28309 3 28307 2 0 1 28309 4 2 27538 10 0 1 28319 1 28312 1 28319 2 7 28318 1 28319 3 28312 4 0 1 28319 4 7 23506 2 0 1 28349 1 28347 1 28349 2 2 28344 1 28349 3 28347 11 0 1 28349 4 2 25323 8 0 1 28351 1 28345 1 28351 2 6 28350 1 28351 3 28345 7 0 1 28351 4 6 26373 3 0 1 28387 1 28385 1 28387 2 2 28383 1 28387 3 28385 6 0 1 28387 4 2 18465 8 0 1 28393 1 28378 1 28393 2 15 28392 1 28393 3 28378 2 0 1 28393 4 15 14936 6 0 1 28403 1 28398 1 28403 2 5 28401 1 28403 3 28398 1 0 1 28403 4 5 28399 3 0 1 28409 1 28406 1 28409 2 3 28400 1 28409 3 28406 1 0 1 28409 4 3 25949 2 0 1 28411 1 28409 1 28411 2 2 28410 1 28411 3 28409 4 0 1 28411 4 2 19551 2 0 1 28429 1 28427 1 28429 2 2 28424 1 28429 3 28427 2 0 1 28429 4 2 19769 11 0 1 28433 1 28430 1 28433 2 3 28427 1 28433 3 28430 3 0 1 28433 4 3 24023 9 0 1 28439 1 28428 1 28439 2 11 28437 1 28439 3 28428 5 0 1 28439 4 11 16708 3 0 1 28447 1 28444 1 28447 2 3 28445 1 28447 3 28444 1 0 1 28447 4 3 28443 4 0 1 28463 1 28458 1 28463 2 5 28458 1 28463 3 28458 2 0 1 28463 4 5 19734 7 0 1 28477 1 28475 1 28477 2 2 28473 1 28477 3 28475 6 0 1 28477 4 2 14427 12 0 1 28493 1 28491 1 28493 2 2 28492 1 28493 3 28491 2 0 1 28493 4 2 23102 4 0 1 28499 1 28497 1 28499 2 2 28493 1 28499 3 28497 2 0 1 28499 4 2 24255 0 0 1 28513 1 28508 1 28513 2 5 28512 1 28513 3 28508 2 0 1 28513 4 5 28274 6 0 1 28517 1 28515 1 28517 2 2 28516 1 28517 3 28515 2 0 1 28517 4 2 27932 4 0 1 28537 1 28532 1 28537 2 5 28536 1 28537 3 28532 1 0 1 28537 4 5 19203 6 0 1 28541 1 28539 1 28541 2 2 28537 1 28541 3 28539 2 0 1 28541 4 2 22580 7 0 1 28547 1 28545 1 28547 2 2 28540 1 28547 3 28545 4 0 1 28547 4 2 18577 1 0 1 28549 1 28547 1 28549 2 2 28548 1 28549 3 28547 6 0 1 28549 4 2 21317 9 0 1 28559 1 28548 1 28559 2 11 28557 1 28559 3 28548 4 0 1 28559 4 11 21583 3 0 1 28571 1 28569 1 28571 2 2 28567 1 28571 3 28569 5 0 1 28571 4 2 24687 8 0 1 28573 1 28571 1 28573 2 2 28572 1 28573 3 28571 6 0 1 28573 4 2 20213 7 0 1 28579 1 28577 1 28579 2 2 28578 1 28579 3 28577 5 0 1 28579 4 2 21361 2 0 1 28591 1 28588 1 28591 2 3 28590 1 28591 3 28588 3 0 1 28591 4 3 19908 3 0 1 28597 1 28595 1 28597 2 2 28593 1 28597 3 28595 4 0 1 28597 4 2 18952 6 0 1 28603 1 28601 1 28603 2 2 28599 1 28603 3 28601 6 0 1 28603 4 2 18823 8 0 1 28607 1 28602 1 28607 2 5 28605 1 28607 3 28602 13 0 1 28607 4 5 28603 3 0 1 28619 1 28617 1 28619 2 2 28615 1 28619 3 28617 3 0 1 28619 4 2 26797 19 0 1 28621 1 28608 1 28621 2 13 28620 1 28621 3 28608 5 0 1 28621 4 13 27089 3 0 1 28627 1 28622 1 28627 2 5 28626 1 28627 3 28622 1 0 1 28627 4 5 24350 5 0 1 28631 1 28620 1 28631 2 11 28625 1 28631 3 28620 1 0 1 28631 4 11 17656 7 0 1 28643 1 28641 1 28643 2 2 28642 1 28643 3 28641 2 0 1 28643 4 2 28636 8 0 1 28649 1 28646 1 28649 2 3 28638 1 28649 3 28646 1 0 1 28649 4 3 17102 4 0 1 28657 1 28652 1 28657 2 5 28649 1 28657 3 28652 2 0 1 28657 4 5 17774 1 0 1 28661 1 28659 1 28661 2 2 28660 1 28661 3 28659 7 0 1 28661 4 2 24490 3 0 1 28663 1 28660 1 28663 2 3 28662 1 28663 3 28660 10 0 1 28663 4 3 17708 5 0 1 28669 1 28663 1 28669 2 6 28668 1 28669 3 28663 1 0 1 28669 4 6 19840 11 0 1 28687 1 28681 1 28687 2 6 28684 1 28687 3 28681 1 0 1 28687 4 6 22832 7 0 1 28697 1 28694 1 28697 2 3 28692 1 28697 3 28694 6 0 1 28697 4 3 14538 2 0 1 28703 1 28698 1 28703 2 5 28689 1 28703 3 28698 12 0 1 28703 4 5 28659 3 0 1 28711 1 28708 1 28711 2 3 28709 1 28711 3 28708 1 0 1 28711 4 3 27443 3 0 1 28723 1 28721 1 28723 2 2 28719 1 28723 3 28721 5 0 1 28723 4 2 22265 8 0 1 28729 1 28707 1 28729 2 22 28728 1 28729 3 28707 4 0 1 28729 4 22 16634 12 0 1 28751 1 28737 1 28751 2 14 28750 1 28751 3 28737 6 0 1 28751 4 14 15346 6 0 1 28753 1 28743 1 28753 2 10 28748 1 28753 3 28743 2 0 1 28753 4 10 24524 10 0 1 28759 1 28756 1 28759 2 3 28757 1 28759 3 28756 7 0 1 28759 4 3 23891 3 0 1 28771 1 28769 1 28771 2 2 28767 1 28771 3 28769 2 0 1 28771 4 2 23259 8 0 1 28789 1 28782 1 28789 2 7 28787 1 28789 3 28782 1 0 1 28789 4 7 20285 4 0 1 28793 1 28790 1 28793 2 3 28792 1 28793 3 28790 4 0 1 28793 4 3 19115 6 0 1 28807 1 28796 1 28807 2 11 28804 1 28807 3 28796 6 0 1 28807 4 11 19354 0 0 1 28813 1 28811 1 28813 2 2 28809 1 28813 3 28811 6 0 1 28813 4 2 19508 9 0 1 28817 1 28814 1 28817 2 3 28816 1 28817 3 28814 5 0 1 28817 4 3 18171 6 0 1 28837 1 28835 1 28837 2 2 28833 1 28837 3 28835 4 0 1 28837 4 2 20125 9 0 1 28843 1 28841 1 28843 2 2 28842 1 28843 3 28841 2 0 1 28843 4 2 22865 2 0 1 28859 1 28857 1 28859 2 2 28858 1 28859 3 28857 3 0 1 28859 4 2 17533 4 0 1 28867 1 28864 1 28867 2 3 28862 1 28867 3 28864 4 0 1 28867 4 3 18464 3 0 1 28871 1 28858 1 28871 2 13 28869 1 28871 3 28858 3 0 1 28871 4 13 14843 3 0 1 28879 1 28876 1 28879 2 3 28877 1 28879 3 28876 11 0 1 28879 4 3 28064 3 0 1 28901 1 28898 1 28901 2 3 28899 1 28901 3 28898 8 0 1 28901 4 3 17058 14 0 1 28909 1 28907 1 28909 2 2 28908 1 28909 3 28907 6 0 1 28909 4 2 15741 7 0 1 28921 1 28910 1 28921 2 11 28916 1 28921 3 28910 3 0 1 28921 4 11 15579 16 0 1 28927 1 28924 1 28927 2 3 28926 1 28927 3 28924 4 0 1 28927 4 3 28027 5 0 1 28933 1 28931 1 28933 2 2 28929 1 28933 3 28931 5 0 1 28933 4 2 19493 9 0 1 28949 1 28947 1 28949 2 2 28945 1 28949 3 28947 2 0 1 28949 4 2 27456 7 0 1 28961 1 28958 1 28961 2 3 28955 1 28961 3 28958 1 0 1 28961 4 3 28949 0 0 1 28979 1 28977 1 28979 2 2 28971 1 28979 3 28977 4 0 1 28979 4 2 18470 6 0 1 29009 1 29006 1 29009 2 3 29008 1 29009 3 29006 3 0 1 29009 4 3 26200 4 0 1 29017 1 29012 1 29017 2 5 29014 1 29017 3 29012 2 0 1 29017 4 5 14998 23 0 1 29021 1 29019 1 29021 2 2 29015 1 29021 3 29019 5 0 1 29021 4 2 28640 4 0 1 29023 1 29020 1 29023 2 3 29021 1 29023 3 29020 1 0 1 29023 4 3 18196 6 0 1 29027 1 29025 1 29027 2 2 29026 1 29027 3 29025 2 0 1 29027 4 2 15411 2 0 1 29033 1 29030 1 29033 2 3 29022 1 29033 3 29030 8 0 1 29033 4 3 18828 5 0 1 29059 1 29057 1 29059 2 2 29054 1 29059 3 29057 2 0 1 29059 4 2 22311 2 0 1 29063 1 29053 1 29063 2 10 29061 1 29063 3 29053 3 0 1 29063 4 10 18950 4 0 1 29077 1 29075 1 29077 2 2 29076 1 29077 3 29075 6 0 1 29077 4 2 14846 9 0 1 29101 1 29099 1 29101 2 2 29097 1 29101 3 29099 2 0 1 29101 4 2 21252 6 0 1 29123 1 29121 1 29123 2 2 29119 1 29123 3 29121 2 0 1 29123 4 2 28287 11 0 1 29129 1 29126 1 29129 2 3 29123 1 29129 3 29126 4 0 1 29129 4 3 29117 0 0 1 29131 1 29129 1 29131 2 2 29127 1 29131 3 29129 2 0 1 29131 4 2 26509 8 0 1 29137 1 29132 1 29137 2 5 29136 1 29137 3 29132 1 0 1 29137 4 5 16303 6 0 1 29147 1 29145 1 29147 2 2 29146 1 29147 3 29145 2 0 1 29147 4 2 19304 4 0 1 29153 1 29150 1 29153 2 3 29147 1 29153 3 29150 3 0 1 29153 4 3 17373 1 0 1 29167 1 29164 1 29167 2 3 29166 1 29167 3 29164 1 0 1 29167 4 3 17782 8 0 1 29173 1 29171 1 29173 2 2 29169 1 29173 3 29171 4 0 1 29173 4 2 21434 10 0 1 29179 1 29166 1 29179 2 13 29178 1 29179 3 29166 4 0 1 29179 4 13 28727 2 0 1 29191 1 29184 1 29191 2 7 29182 1 29191 3 29184 1 0 1 29191 4 7 22099 2 0 1 29201 1 29198 1 29201 2 3 29200 1 29201 3 29198 10 0 1 29201 4 3 28265 7 0 1 29207 1 29202 1 29207 2 5 29205 1 29207 3 29202 7 0 1 29207 4 5 29203 3 0 1 29209 1 29202 1 29209 2 7 29196 1 29209 3 29202 1 0 1 29209 4 7 25391 0 0 1 29221 1 29219 1 29221 2 2 29220 1 29221 3 29219 5 0 1 29221 4 2 23703 7 0 1 29231 1 29218 1 29231 2 13 29229 1 29231 3 29218 2 0 1 29231 4 13 15869 4 0 1 29243 1 29241 1 29243 2 2 29239 1 29243 3 29241 3 0 1 29243 4 2 27114 7 0 1 29251 1 29249 1 29251 2 2 29250 1 29251 3 29249 5 0 1 29251 4 2 27108 7 0 1 29269 1 29263 1 29269 2 6 29265 1 29269 3 29263 2 0 1 29269 4 6 20234 2 0 1 29287 1 29282 1 29287 2 5 29286 1 29287 3 29282 2 0 1 29287 4 5 23381 2 0 1 29297 1 29294 1 29297 2 3 29291 1 29297 3 29294 1 0 1 29297 4 3 16396 25 0 1 29303 1 29296 1 29303 2 7 29301 1 29303 3 29296 7 0 1 29303 4 7 23680 10 0 1 29311 1 29308 1 29311 2 3 29310 1 29311 3 29308 15 0 1 29311 4 3 20443 2 0 1 29327 1 29322 1 29327 2 5 29326 1 29327 3 29322 2 0 1 29327 4 5 19955 2 0 1 29333 1 29331 1 29333 2 2 29332 1 29333 3 29331 2 0 1 29333 4 2 26625 3 0 1 29339 1 29337 1 29339 2 2 29333 1 29339 3 29337 2 0 1 29339 4 2 26845 0 0 1 29347 1 29344 1 29347 2 3 29342 1 29347 3 29344 4 0 1 29347 4 3 22197 3 0 1 29363 1 29361 1 29363 2 2 29362 1 29363 3 29361 2 0 1 29363 4 2 22209 2 0 1 29383 1 29377 1 29383 2 6 29380 1 29383 3 29377 12 0 1 29383 4 6 14840 4 0 1 29387 1 29385 1 29387 2 2 29383 1 29387 3 29385 3 0 1 29387 4 2 17320 16 0 1 29389 1 29387 1 29389 2 2 29388 1 29389 3 29387 5 0 1 29389 4 2 29382 8 0 1 29399 1 29386 1 29399 2 13 29396 1 29399 3 29386 4 0 1 29399 4 13 28356 5 0 1 29401 1 29388 1 29401 2 13 29398 1 29401 3 29388 1 0 1 29401 4 13 24677 22 0 1 29411 1 29409 1 29411 2 2 29404 1 29411 3 29409 2 0 1 29411 4 2 14933 0 0 1 29423 1 29418 1 29423 2 5 29421 1 29423 3 29418 1 0 1 29423 4 5 19236 5 0 1 29429 1 29427 1 29429 2 2 29425 1 29429 3 29427 2 0 1 29429 4 2 25294 7 0 1 29437 1 29435 1 29437 2 2 29433 1 29437 3 29435 6 0 1 29437 4 2 25134 12 0 1 29443 1 29441 1 29443 2 2 29439 1 29443 3 29441 5 0 1 29443 4 2 18291 20 0 1 29453 1 29451 1 29453 2 2 29446 1 29453 3 29451 7 0 1 29453 4 2 15788 2 0 1 29473 1 29468 1 29473 2 5 29468 1 29473 3 29468 1 0 1 29473 4 5 21461 15 0 1 29483 1 29481 1 29483 2 2 29482 1 29483 3 29481 2 0 1 29483 4 2 25211 2 0 1 29501 1 29499 1 29501 2 2 29496 1 29501 3 29499 5 0 1 29501 4 2 20034 2 0 1 29527 1 29524 1 29527 2 3 29525 1 29527 3 29524 3 0 1 29527 4 3 21906 6 0 1 29531 1 29529 1 29531 2 2 29530 1 29531 3 29529 11 0 1 29531 4 2 21925 2 0 1 29537 1 29534 1 29537 2 3 29536 1 29537 3 29534 6 0 1 29537 4 3 25213 6 0 1 29567 1 29562 1 29567 2 5 29566 1 29567 3 29562 5 0 1 29567 4 5 20491 7 0 1 29569 1 29552 1 29569 2 17 29566 1 29569 3 29552 3 0 1 29569 4 17 18151 20 0 1 29573 1 29571 1 29573 2 2 29572 1 29573 3 29571 2 0 1 29573 4 2 26920 6 0 1 29581 1 29571 1 29581 2 10 29580 1 29581 3 29571 2 0 1 29581 4 10 17406 7 0 1 29587 1 29585 1 29587 2 2 29586 1 29587 3 29585 2 0 1 29587 4 2 26406 2 0 1 29599 1 29586 1 29599 2 13 29595 1 29599 3 29586 1 0 1 29599 4 13 19983 9 0 1 29611 1 29608 1 29611 2 3 29610 1 29611 3 29608 4 0 1 29611 4 3 26191 6 0 1 29629 1 29622 1 29629 2 7 29627 1 29629 3 29622 1 0 1 29629 4 7 23634 4 0 1 29633 1 29630 1 29633 2 3 29632 1 29633 3 29630 7 0 1 29633 4 3 25224 4 0 1 29641 1 29634 1 29641 2 7 29634 1 29641 3 29634 1 0 1 29641 4 7 24805 0 0 1 29663 1 29658 1 29663 2 5 29661 1 29663 3 29658 2 0 1 29663 4 5 29659 3 0 1 29669 1 29667 1 29669 2 2 29668 1 29669 3 29667 7 0 1 29669 4 2 27999 3 0 1 29671 1 29665 1 29671 2 6 29669 1 29671 3 29665 3 0 1 29671 4 6 26942 3 0 1 29683 1 29672 1 29683 2 11 29681 1 29683 3 29672 2 0 1 29683 4 11 15914 3 0 1 29717 1 29715 1 29717 2 2 29709 1 29717 3 29715 10 0 1 29717 4 2 24974 3 0 1 29723 1 29721 1 29723 2 2 29719 1 29723 3 29721 3 0 1 29723 4 2 16626 7 0 1 29741 1 29739 1 29741 2 2 29740 1 29741 3 29739 9 0 1 29741 4 2 16425 3 0 1 29753 1 29750 1 29753 2 3 29746 1 29753 3 29750 5 0 1 29753 4 3 26197 4 0 1 29759 1 29752 1 29759 2 7 29758 1 29759 3 29752 1 0 1 29759 4 7 22835 2 0 1 29761 1 29744 1 29761 2 17 29760 1 29761 3 29744 1 0 1 29761 4 17 21538 12 0 1 29789 1 29787 1 29789 2 2 29785 1 29789 3 29787 2 0 1 29789 4 2 16795 6 0 1 29803 1 29796 1 29803 2 7 29801 1 29803 3 29796 2 0 1 29803 4 7 20953 11 0 1 29819 1 29813 1 29819 2 6 29818 1 29819 3 29813 1 0 1 29819 4 6 22081 5 0 1 29833 1 29828 1 29833 2 5 29832 1 29833 3 29828 2 0 1 29833 4 5 21582 6 0 1 29837 1 29835 1 29837 2 2 29836 1 29837 3 29835 2 0 1 29837 4 2 20232 4 0 1 29851 1 29849 1 29851 2 2 29850 1 29851 3 29849 5 0 1 29851 4 2 19580 2 0 1 29863 1 29853 1 29863 2 10 29862 1 29863 3 29853 4 0 1 29863 4 10 24650 2 0 1 29867 1 29865 1 29867 2 2 29863 1 29867 3 29865 3 0 1 29867 4 2 27059 7 0 1 29873 1 29870 1 29873 2 3 29872 1 29873 3 29870 10 0 1 29873 4 3 20724 6 0 1 29879 1 29868 1 29879 2 11 29877 1 29879 3 29868 6 0 1 29879 4 11 25142 3 0 1 29881 1 29874 1 29881 2 7 29878 1 29881 3 29874 3 0 1 29881 4 7 22162 16 0 1 29917 1 29915 1 29917 2 2 29916 1 29917 3 29915 6 0 1 29917 4 2 26532 3 0 1 29921 1 29918 1 29921 2 3 29915 1 29921 3 29918 1 0 1 29921 4 3 29909 0 0 1 29927 1 29922 1 29927 2 5 29924 1 29927 3 29922 10 0 1 29927 4 5 28232 6 0 1 29947 1 29944 1 29947 2 3 29942 1 29947 3 29944 1 0 1 29947 4 3 27189 3 0 1 29959 1 29953 1 29959 2 6 29957 1 29959 3 29953 1 0 1 29959 4 6 23001 3 0 1 29983 1 29978 1 29983 2 5 29981 1 29983 3 29978 9 0 1 29983 4 5 20417 17 0 1 29989 1 29987 1 29989 2 2 29980 1 29989 3 29987 2 0 1 29989 4 2 27546 3 0 1 30011 1 30009 1 30011 2 2 30005 1 30011 3 30009 9 0 1 30011 4 2 26951 0 0 1 30013 1 30011 1 30013 2 2 30009 1 30013 3 30011 5 0 1 30013 4 2 28053 12 0 1 30029 1 30027 1 30029 2 2 30025 1 30029 3 30027 3 0 1 30029 4 2 17215 1 0 1 30047 1 30042 1 30047 2 5 30046 1 30047 3 30042 2 0 1 30047 4 5 22017 3 0 1 30059 1 30057 1 30059 2 2 30055 1 30059 3 30057 3 0 1 30059 4 2 29484 7 0 1 30071 1 30058 1 30071 2 13 30070 1 30071 3 30058 7 0 1 30071 4 13 27810 2 0 1 30089 1 30086 1 30089 2 3 30084 1 30089 3 30086 9 0 1 30089 4 3 15442 2 0 1 30091 1 30070 1 30091 2 21 30090 1 30091 3 30070 2 0 1 30091 4 21 18186 6 0 1 30097 1 30087 1 30097 2 10 30096 1 30097 3 30087 5 0 1 30097 4 10 18998 21 0 1 30103 1 30100 1 30103 2 3 30101 1 30103 3 30100 6 0 1 30103 4 3 22137 6 0 1 30109 1 30107 1 30109 2 2 30102 1 30109 3 30107 5 0 1 30109 4 2 19414 33 0 1 30113 1 30110 1 30113 2 3 30108 1 30113 3 30110 3 0 1 30113 4 3 22214 0 0 1 30119 1 30108 1 30119 2 11 30117 1 30119 3 30108 4 0 1 30119 4 11 22758 8 0 1 30133 1 30128 1 30133 2 5 30132 1 30133 3 30128 1 0 1 30133 4 5 23507 6 0 1 30137 1 30134 1 30137 2 3 30136 1 30137 3 30134 4 0 1 30137 4 3 17463 7 0 1 30139 1 30137 1 30139 2 2 30133 1 30139 3 30137 6 0 1 30139 4 2 20974 12 0 1 30161 1 30158 1 30161 2 3 30160 1 30161 3 30158 4 0 1 30161 4 3 21019 4 0 1 30169 1 30162 1 30169 2 7 30160 1 30169 3 30162 2 0 1 30169 4 7 19551 2 0 1 30181 1 30179 1 30181 2 2 30177 1 30181 3 30179 2 0 1 30181 4 2 18980 6 0 1 30187 1 30182 1 30187 2 5 30186 1 30187 3 30182 1 0 1 30187 4 5 19640 7 0 1 30197 1 30195 1 30197 2 2 30193 1 30197 3 30195 3 0 1 30197 4 2 21691 1 0 1 30203 1 30201 1 30203 2 2 30202 1 30203 3 30201 5 0 1 30203 4 2 30196 8 0 1 30211 1 30209 1 30211 2 2 30203 1 30211 3 30209 6 0 1 30211 4 2 16242 6 0 1 30223 1 30220 1 30223 2 3 30222 1 30223 3 30220 5 0 1 30223 4 3 27943 5 0 1 30241 1 30230 1 30241 2 11 30240 1 30241 3 30230 3 0 1 30241 4 11 16745 12 0 1 30253 1 30251 1 30253 2 2 30252 1 30253 3 30251 2 0 1 30253 4 2 21456 6 0 1 30259 1 30256 1 30259 2 3 30254 1 30259 3 30256 5 0 1 30259 4 3 29870 3 0 1 30269 1 30266 1 30269 2 3 30268 1 30269 3 30266 1 0 1 30269 4 3 21776 3 0 1 30271 1 30268 1 30271 2 3 30270 1 30271 3 30268 4 0 1 30271 4 3 16756 2 0 1 30293 1 30291 1 30293 2 2 30289 1 30293 3 30291 3 0 1 30293 4 2 21473 7 0 1 30307 1 30305 1 30307 2 2 30303 1 30307 3 30305 4 0 1 30307 4 2 26118 8 0 1 30313 1 30308 1 30313 2 5 30312 1 30313 3 30308 8 0 1 30313 4 5 18238 6 0 1 30319 1 30316 1 30319 2 3 30313 1 30319 3 30316 3 0 1 30319 4 3 15805 15 0 1 30323 1 30321 1 30323 2 2 30322 1 30323 3 30321 2 0 1 30323 4 2 28026 2 0 1 30341 1 30339 1 30341 2 2 30335 1 30341 3 30339 9 0 1 30341 4 2 28783 3 0 1 30347 1 30345 1 30347 2 2 30343 1 30347 3 30345 3 0 1 30347 4 2 17617 14 0 1 30367 1 30362 1 30367 2 5 30365 1 30367 3 30362 6 0 1 30367 4 5 30355 11 0 1 30389 1 30387 1 30389 2 2 30385 1 30389 3 30387 2 0 1 30389 4 2 23109 6 0 1 30391 1 30388 1 30391 2 3 30389 1 30391 3 30388 3 0 1 30391 4 3 24019 3 0 1 30403 1 30398 1 30403 2 5 30402 1 30403 3 30398 7 0 1 30403 4 5 19714 14 0 1 30427 1 30422 1 30427 2 5 30426 1 30427 3 30422 2 0 1 30427 4 5 16271 7 0 1 30431 1 30420 1 30431 2 11 30416 1 30431 3 30420 11 0 1 30431 4 11 16803 4 0 1 30449 1 30446 1 30449 2 3 30443 1 30449 3 30446 6 0 1 30449 4 3 30437 0 0 1 30467 1 30465 1 30467 2 2 30463 1 30467 3 30465 3 0 1 30467 4 2 23496 7 0 1 30469 1 30467 1 30469 2 2 30468 1 30469 3 30467 5 0 1 30469 4 2 29917 3 0 1 30491 1 30489 1 30491 2 2 30487 1 30491 3 30489 3 0 1 30491 4 2 29458 16 0 1 30493 1 30487 1 30493 2 6 30491 1 30493 3 30487 2 0 1 30493 4 6 23342 4 0 1 30497 1 30494 1 30497 2 3 30485 1 30497 3 30494 6 0 1 30497 4 3 25756 6 0 1 30509 1 30507 1 30509 2 2 30504 1 30509 3 30507 5 0 1 30509 4 2 27775 2 0 1 30517 1 30515 1 30517 2 2 30513 1 30517 3 30515 5 0 1 30517 4 2 26108 10 0 1 30529 1 30516 1 30529 2 13 30528 1 30529 3 30516 1 0 1 30529 4 13 19269 14 0 1 30539 1 30537 1 30539 2 2 30535 1 30539 3 30537 3 0 1 30539 4 2 17947 7 0 1 30553 1 30548 1 30553 2 5 30550 1 30553 3 30548 2 0 1 30553 4 5 19373 10 0 1 30557 1 30555 1 30557 2 2 30553 1 30557 3 30555 3 0 1 30557 4 2 15679 7 0 1 30559 1 30552 1 30559 2 7 30548 1 30559 3 30552 7 0 1 30559 4 7 27067 0 0 1 30577 1 30572 1 30577 2 5 30574 1 30577 3 30572 6 0 1 30577 4 5 30566 14 0 1 30593 1 30590 1 30593 2 3 30592 1 30593 3 30590 6 0 1 30593 4 3 17254 4 0 1 30631 1 30628 1 30631 2 3 30630 1 30631 3 30628 3 0 1 30631 4 3 19988 2 0 1 30637 1 30635 1 30637 2 2 30636 1 30637 3 30635 2 0 1 30637 4 2 23467 3 0 1 30643 1 30641 1 30643 2 2 30639 1 30643 3 30641 10 0 1 30643 4 2 20662 8 0 1 30649 1 30642 1 30649 2 7 30638 1 30649 3 30642 1 0 1 30649 4 7 22659 30 0 1 30661 1 30659 1 30661 2 2 30657 1 30661 3 30659 5 0 1 30661 4 2 20324 6 0 1 30671 1 30660 1 30671 2 11 30670 1 30671 3 30660 1 0 1 30671 4 11 17644 3 0 1 30677 1 30675 1 30677 2 2 30676 1 30677 3 30675 3 0 1 30677 4 2 23980 6 0 1 30689 1 30686 1 30689 2 3 30683 1 30689 3 30686 1 0 1 30689 4 3 30677 0 0 1 30697 1 30687 1 30697 2 10 30692 1 30697 3 30687 2 0 1 30697 4 10 28684 16 0 1 30703 1 30700 1 30703 2 3 30702 1 30703 3 30700 7 0 1 30703 4 3 22014 5 0 1 30707 1 30705 1 30707 2 2 30706 1 30707 3 30705 3 0 1 30707 4 2 23927 4 0 1 30713 1 30710 1 30713 2 3 30708 1 30713 3 30710 3 0 1 30713 4 3 27578 0 0 1 30727 1 30724 1 30727 2 3 30725 1 30727 3 30724 5 0 1 30727 4 3 24780 6 0 1 30757 1 30752 1 30757 2 5 30756 1 30757 3 30752 2 0 1 30757 4 5 26454 6 0 1 30763 1 30761 1 30763 2 2 30762 1 30763 3 30761 4 0 1 30763 4 2 25015 7 0 1 30773 1 30770 1 30773 2 3 30772 1 30773 3 30770 1 0 1 30773 4 3 30762 12 0 1 30781 1 30779 1 30781 2 2 30777 1 30781 3 30779 4 0 1 30781 4 2 19287 6 0 1 30803 1 30801 1 30803 2 2 30799 1 30803 3 30801 2 0 1 30803 4 2 16549 13 0 1 30809 1 30806 1 30809 2 3 30787 1 30809 3 30806 4 0 1 30809 4 3 27459 5 0 1 30817 1 30812 1 30817 2 5 30816 1 30817 3 30812 1 0 1 30817 4 5 24603 6 0 1 30829 1 30827 1 30829 2 2 30825 1 30829 3 30827 2 0 1 30829 4 2 16743 10 0 1 30839 1 30832 1 30839 2 7 30837 1 30839 3 30832 13 0 1 30839 4 7 25900 5 0 1 30841 1 30834 1 30841 2 7 30834 1 30841 3 30834 12 0 1 30841 4 7 25905 21 0 1 30851 1 30849 1 30851 2 2 30847 1 30851 3 30849 3 0 1 30851 4 2 26815 8 0 1 30853 1 30851 1 30853 2 2 30849 1 30853 3 30851 6 0 1 30853 4 2 18765 12 0 1 30859 1 30857 1 30859 2 2 30858 1 30859 3 30857 6 0 1 30859 4 2 17937 6 0 1 30869 1 30867 1 30869 2 2 30865 1 30869 3 30867 3 0 1 30869 4 2 22574 1 0 1 30871 1 30868 1 30871 2 3 30869 1 30871 3 30868 3 0 1 30871 4 3 23037 3 0 1 30881 1 30878 1 30881 2 3 30876 1 30881 3 30878 5 0 1 30881 4 3 23515 2 0 1 30893 1 30891 1 30893 2 2 30889 1 30893 3 30891 3 0 1 30893 4 2 30107 12 0 1 30911 1 30894 1 30911 2 17 30909 1 30911 3 30894 2 0 1 30911 4 17 21641 7 0 1 30931 1 30929 1 30931 2 2 30930 1 30931 3 30929 5 0 1 30931 4 2 20931 12 0 1 30937 1 30922 1 30937 2 15 30934 1 30937 3 30922 1 0 1 30937 4 15 16156 20 0 1 30941 1 30939 1 30941 2 2 30937 1 30941 3 30939 2 0 1 30941 4 2 18994 7 0 1 30949 1 30939 1 30949 2 10 30946 1 30949 3 30939 2 0 1 30949 4 10 20186 5 0 1 30971 1 30969 1 30971 2 2 30963 1 30971 3 30969 4 0 1 30971 4 2 30666 6 0 1 30977 1 30974 1 30977 2 3 30972 1 30977 3 30974 3 0 1 30977 4 3 20520 2 0 1 30983 1 30978 1 30983 2 5 30982 1 30983 3 30978 3 0 1 30983 4 5 15644 2 0 1 31013 1 31011 1 31013 2 2 31012 1 31013 3 31011 2 0 1 31013 4 2 23752 4 0 1 31019 1 31017 1 31019 2 2 31015 1 31019 3 31017 2 0 1 31019 4 2 30714 8 0 1 31033 1 31023 1 31033 2 10 31032 1 31033 3 31023 2 0 1 31033 4 10 26446 6 0 1 31039 1 31032 1 31039 2 7 31036 1 31039 3 31032 1 0 1 31039 4 7 19176 0 0 1 31051 1 31040 1 31051 2 11 31050 1 31051 3 31040 2 0 1 31051 4 11 23777 5 0 1 31063 1 31060 1 31063 2 3 31062 1 31063 3 31060 4 0 1 31063 4 3 26380 2 0 1 31069 1 31067 1 31069 2 2 31068 1 31069 3 31067 6 0 1 31069 4 2 25009 7 0 1 31079 1 31068 1 31079 2 11 31077 1 31079 3 31068 6 0 1 31079 4 11 29978 5 0 1 31081 1 31068 1 31081 2 13 31080 1 31081 3 31068 2 0 1 31081 4 13 19769 18 0 1 31091 1 31089 1 31091 2 2 31085 1 31091 3 31089 7 0 1 31091 4 2 18968 7 0 1 31121 1 31118 1 31121 2 3 31111 1 31121 3 31118 4 0 1 31121 4 3 29125 4 0 1 31123 1 31120 1 31123 2 3 31116 1 31123 3 31120 6 0 1 31123 4 3 18218 11 0 1 31139 1 31137 1 31139 2 2 31138 1 31139 3 31137 3 0 1 31139 4 2 17165 2 0 1 31147 1 31145 1 31147 2 2 31143 1 31147 3 31145 6 0 1 31147 4 2 22415 8 0 1 31151 1 31144 1 31151 2 7 31149 1 31151 3 31144 9 0 1 31151 4 7 26366 12 0 1 31153 1 31143 1 31153 2 10 31152 1 31153 3 31143 2 0 1 31153 4 10 30170 15 0 1 31159 1 31156 1 31159 2 3 31158 1 31159 3 31156 1 0 1 31159 4 3 27759 2 0 1 31177 1 31170 1 31177 2 7 31170 1 31177 3 31170 2 0 1 31177 4 7 19612 12 0 1 31181 1 31179 1 31181 2 2 31180 1 31181 3 31179 3 0 1 31181 4 2 28389 3 0 1 31183 1 31180 1 31183 2 3 31181 1 31183 3 31180 6 0 1 31183 4 3 31179 4 0 1 31189 1 31176 1 31189 2 13 31188 1 31189 3 31176 3 0 1 31189 4 13 20344 7 0 1 31193 1 31188 1 31193 2 5 31192 1 31193 3 31188 5 0 1 31193 4 5 20145 6 0 1 31219 1 31209 1 31219 2 10 31217 1 31219 3 31209 2 0 1 31219 4 10 31207 6 0 1 31223 1 31218 1 31223 2 5 31221 1 31223 3 31218 3 0 1 31223 4 5 27619 5 0 1 31231 1 31225 1 31231 2 6 31230 1 31231 3 31225 3 0 1 31231 4 6 24588 3 0 1 31237 1 31231 1 31237 2 6 31235 1 31237 3 31231 7 0 1 31237 4 6 31227 7 0 1 31247 1 31242 1 31247 2 5 31244 1 31247 3 31242 1 0 1 31247 4 5 28170 11 0 1 31249 1 31226 1 31249 2 23 31245 1 31249 3 31226 9 0 1 31249 4 23 26334 27 0 1 31253 1 31251 1 31253 2 2 31252 1 31253 3 31251 3 0 1 31253 4 2 29539 3 0 1 31259 1 31257 1 31259 2 2 31255 1 31259 3 31257 2 0 1 31259 4 2 20506 8 0 1 31267 1 31265 1 31267 2 2 31266 1 31267 3 31265 4 0 1 31267 4 2 27397 2 0 1 31271 1 31264 1 31271 2 7 31270 1 31271 3 31264 1 0 1 31271 4 7 19977 2 0 1 31277 1 31275 1 31277 2 2 31270 1 31277 3 31275 4 0 1 31277 4 2 30358 5 0 1 31307 1 31305 1 31307 2 2 31303 1 31307 3 31305 2 0 1 31307 4 2 27165 13 0 1 31319 1 31312 1 31319 2 7 31308 1 31319 3 31312 10 0 1 31319 4 7 25793 4 0 1 31321 1 31314 1 31321 2 7 31314 1 31321 3 31314 2 0 1 31321 4 7 25513 0 0 1 31327 1 31321 1 31327 2 6 31324 1 31327 3 31321 8 0 1 31327 4 6 21898 4 0 1 31333 1 31328 1 31333 2 5 31332 1 31333 3 31328 2 0 1 31333 4 5 25417 6 0 1 31337 1 31334 1 31337 2 3 31332 1 31337 3 31334 5 0 1 31337 4 3 27679 0 0 1 31357 1 31355 1 31357 2 2 31353 1 31357 3 31355 9 0 1 31357 4 2 24570 12 0 1 31379 1 31377 1 31379 2 2 31378 1 31379 3 31377 5 0 1 31379 4 2 27418 4 0 1 31387 1 31385 1 31387 2 2 31386 1 31387 3 31385 4 0 1 31387 4 2 15928 10 0 1 31391 1 31360 1 31391 2 31 31389 1 31391 3 31360 1 0 1 31391 4 31 16662 4 0 1 31393 1 31388 1 31393 2 5 31390 1 31393 3 31388 2 0 1 31393 4 5 26054 10 0 1 31397 1 31395 1 31397 2 2 31393 1 31397 3 31395 3 0 1 31397 4 2 28910 9 0 1 31469 1 31467 1 31469 2 2 31459 1 31469 3 31467 7 0 1 31469 4 2 19610 0 0 1 31477 1 31471 1 31477 2 6 31475 1 31477 3 31471 1 0 1 31477 4 6 16850 0 0 1 31481 1 31475 1 31481 2 6 31478 1 31481 3 31475 1 0 1 31481 4 6 30304 14 0 1 31489 1 31482 1 31489 2 7 31482 1 31489 3 31482 1 0 1 31489 4 7 28488 0 0 1 31511 1 31504 1 31511 2 7 31510 1 31511 3 31504 4 0 1 31511 4 7 17581 7 0 1 31513 1 31506 1 31513 2 7 31506 1 31513 3 31506 9 0 1 31513 4 7 25338 12 0 1 31517 1 31515 1 31517 2 2 31511 1 31517 3 31515 3 0 1 31517 4 2 30053 1 0 1 31531 1 31529 1 31531 2 2 31530 1 31531 3 31529 5 0 1 31531 4 2 20456 6 0 1 31541 1 31538 1 31541 2 3 31539 1 31541 3 31538 1 0 1 31541 4 3 31537 4 0 1 31543 1 31540 1 31543 2 3 31542 1 31543 3 31540 1 0 1 31543 4 3 20872 2 0 1 31547 1 31545 1 31547 2 2 31546 1 31547 3 31545 2 0 1 31547 4 2 17600 2 0 1 31567 1 31561 1 31567 2 6 31566 1 31567 3 31561 1 0 1 31567 4 6 24886 2 0 1 31573 1 31568 1 31573 2 5 31572 1 31573 3 31568 2 0 1 31573 4 5 18777 3 0 1 31583 1 31578 1 31583 2 5 31578 1 31583 3 31578 1 0 1 31583 4 5 30502 7 0 1 31601 1 31598 1 31601 2 3 31596 1 31601 3 31598 8 0 1 31601 4 3 20344 2 0 1 31607 1 31602 1 31607 2 5 31602 1 31607 3 31602 2 0 1 31607 4 5 30966 7 0 1 31627 1 31624 1 31627 2 3 31626 1 31627 3 31624 4 0 1 31627 4 3 21695 2 0 1 31643 1 31641 1 31643 2 2 31642 1 31643 3 31641 2 0 1 31643 4 2 21228 4 0 1 31649 1 31646 1 31649 2 3 31648 1 31649 3 31646 1 0 1 31649 4 3 27565 4 0 1 31657 1 31652 1 31657 2 5 31656 1 31657 3 31652 2 0 1 31657 4 5 23384 6 0 1 31663 1 31660 1 31663 2 3 31661 1 31663 3 31660 4 0 1 31663 4 3 25142 6 0 1 31667 1 31665 1 31667 2 2 31666 1 31667 3 31665 2 0 1 31667 4 2 21477 2 0 1 31687 1 31684 1 31687 2 3 31686 1 31687 3 31684 1 0 1 31687 4 3 21500 5 0 1 31699 1 31697 1 31699 2 2 31698 1 31699 3 31697 4 0 1 31699 4 2 16753 10 0 1 31721 1 31710 1 31721 2 11 31716 1 31721 3 31710 2 0 1 31721 4 11 29853 11 0 1 31723 1 31720 1 31723 2 3 31716 1 31723 3 31720 3 0 1 31723 4 3 27099 5 0 1 31727 1 31722 1 31727 2 5 31725 1 31727 3 31722 7 0 1 31727 4 5 31723 3 0 1 31729 1 31722 1 31729 2 7 31726 1 31729 3 31722 1 0 1 31729 4 7 23340 24 0 1 31741 1 31735 1 31741 2 6 31737 1 31741 3 31735 2 0 1 31741 4 6 31737 6 0 1 31751 1 31740 1 31751 2 11 31749 1 31751 3 31740 1 0 1 31751 4 11 21928 3 0 1 31769 1 31763 1 31769 2 6 31757 1 31769 3 31763 1 0 1 31769 4 6 17097 5 0 1 31771 1 31761 1 31771 2 10 31769 1 31771 3 31761 5 0 1 31771 4 10 27394 8 0 1 31793 1 31790 1 31793 2 3 31780 1 31793 3 31790 3 0 1 31793 4 3 25278 3 0 1 31799 1 31788 1 31799 2 11 31798 1 31799 3 31788 2 0 1 31799 4 11 28237 2 0 1 31817 1 31814 1 31817 2 3 31812 1 31817 3 31814 9 0 1 31817 4 3 31345 0 0 1 31847 1 31842 1 31847 2 5 31845 1 31847 3 31842 1 0 1 31847 4 5 31843 3 0 1 31849 1 31835 1 31849 2 14 31846 1 31849 3 31835 2 0 1 31849 4 14 25058 10 0 1 31859 1 31857 1 31859 2 2 31855 1 31859 3 31857 9 0 1 31859 4 2 16084 7 0 1 31873 1 31862 1 31873 2 11 31871 1 31873 3 31862 4 0 1 31873 4 11 16816 17 0 1 31883 1 31881 1 31883 2 2 31882 1 31883 3 31881 2 0 1 31883 4 2 20059 4 0 1 31891 1 31889 1 31891 2 2 31890 1 31891 3 31889 6 0 1 31891 4 2 25349 7 0 1 31907 1 31905 1 31907 2 2 31901 1 31907 3 31905 9 0 1 31907 4 2 20919 4 0 1 31957 1 31955 1 31957 2 2 31953 1 31957 3 31955 4 0 1 31957 4 2 24976 12 0 1 31963 1 31961 1 31963 2 2 31959 1 31963 3 31961 4 0 1 31963 4 2 31017 10 0 1 31973 1 31971 1 31973 2 2 31969 1 31973 3 31971 3 0 1 31973 4 2 16771 9 0 1 31981 1 31975 1 31981 2 6 31980 1 31981 3 31975 4 0 1 31981 4 6 22591 22 0 1 31991 1 31984 1 31991 2 7 31988 1 31991 3 31984 1 0 1 31991 4 7 24528 5 0 1 32003 1 32001 1 32003 2 2 31995 1 32003 3 32001 2 0 1 32003 4 2 17396 0 0 1 32009 1 32006 1 32009 2 3 32008 1 32009 3 32006 6 0 1 32009 4 3 19461 4 0 1 32027 1 32025 1 32027 2 2 32023 1 32027 3 32025 3 0 1 32027 4 2 21014 14 0 1 32029 1 32027 1 32029 2 2 32025 1 32029 3 32027 4 0 1 32029 4 2 23167 12 0 1 32051 1 32041 1 32051 2 10 32046 1 32051 3 32041 2 0 1 32051 4 10 25281 3 0 1 32057 1 32054 1 32057 2 3 32050 1 32057 3 32054 1 0 1 32057 4 3 20274 1 0 1 32059 1 32057 1 32059 2 2 32055 1 32059 3 32057 6 0 1 32059 4 2 18541 1 0 1 32063 1 32058 1 32063 2 5 32062 1 32063 3 32058 2 0 1 32063 4 5 18079 2 0 1 32069 1 32067 1 32069 2 2 32065 1 32069 3 32067 3 0 1 32069 4 2 16860 6 0 1 32077 1 32075 1 32077 2 2 32076 1 32077 3 32075 6 0 1 32077 4 2 21600 6 0 1 32083 1 32081 1 32083 2 2 32079 1 32083 3 32081 4 0 1 32083 4 2 22551 8 0 1 32089 1 32076 1 32089 2 13 32088 1 32089 3 32076 5 0 1 32089 4 13 20637 12 0 1 32099 1 32097 1 32099 2 2 32095 1 32099 3 32097 3 0 1 32099 4 2 24817 7 0 1 32117 1 32115 1 32117 2 2 32113 1 32117 3 32115 3 0 1 32117 4 2 20811 7 0 1 32119 1 32116 1 32119 2 3 32118 1 32119 3 32116 1 0 1 32119 4 3 26845 3 0 1 32141 1 32139 1 32141 2 2 32136 1 32141 3 32139 11 0 1 32141 4 2 17811 2 0 1 32143 1 32137 1 32143 2 6 32139 1 32143 3 32137 2 0 1 32143 4 6 24658 1 0 1 32159 1 32152 1 32159 2 7 32157 1 32159 3 32152 4 0 1 32159 4 7 27961 5 0 1 32173 1 32168 1 32173 2 5 32168 1 32173 3 32168 1 0 1 32173 4 5 24843 7 0 1 32183 1 32178 1 32183 2 5 32181 1 32183 3 32178 6 0 1 32183 4 5 32179 3 0 1 32189 1 32187 1 32189 2 2 32188 1 32189 3 32187 3 0 1 32189 4 2 18279 4 0 1 32191 1 32185 1 32191 2 6 32190 1 32191 3 32185 1 0 1 32191 4 6 23688 2 0 1 32203 1 32201 1 32203 2 2 32202 1 32203 3 32201 2 0 1 32203 4 2 24230 2 0 1 32213 1 32211 1 32213 2 2 32209 1 32213 3 32211 3 0 1 32213 4 2 23787 1 0 1 32233 1 32228 1 32233 2 5 32228 1 32233 3 32228 1 0 1 32233 4 5 28092 20 0 1 32237 1 32235 1 32237 2 2 32233 1 32237 3 32235 4 0 1 32237 4 2 18370 6 0 1 32251 1 32248 1 32251 2 3 32250 1 32251 3 32248 14 0 1 32251 4 3 25215 2 0 1 32257 1 32242 1 32257 2 15 32256 1 32257 3 32242 1 0 1 32257 4 15 22507 20 0 1 32261 1 32259 1 32261 2 2 32257 1 32261 3 32259 3 0 1 32261 4 2 29740 1 0 1 32297 1 32294 1 32297 2 3 32291 1 32297 3 32294 6 0 1 32297 4 3 23537 9 0 1 32299 1 32287 1 32299 2 12 32298 1 32299 3 32287 5 0 1 32299 4 12 20907 7 0 1 32303 1 32298 1 32303 2 5 32302 1 32303 3 32298 5 0 1 32303 4 5 20531 7 0 1 32309 1 32307 1 32309 2 2 32300 1 32309 3 32307 4 0 1 32309 4 2 25180 1 0 1 32321 1 32315 1 32321 2 6 32309 1 32321 3 32315 7 0 1 32321 4 6 20416 0 0 1 32323 1 32321 1 32323 2 2 32319 1 32323 3 32321 6 0 1 32323 4 2 30321 10 0 1 32327 1 32322 1 32327 2 5 32326 1 32327 3 32322 3 0 1 32327 4 5 19526 3 0 1 32341 1 32339 1 32341 2 2 32337 1 32341 3 32339 4 0 1 32341 4 2 18167 6 0 1 32353 1 32338 1 32353 2 15 32351 1 32353 3 32338 3 0 1 32353 4 15 32325 16 0 1 32359 1 32356 1 32359 2 3 32358 1 32359 3 32356 1 0 1 32359 4 3 26081 3 0 1 32363 1 32361 1 32363 2 2 32356 1 32363 3 32361 8 0 1 32363 4 2 27433 0 0 1 32369 1 32363 1 32369 2 6 32359 1 32369 3 32363 2 0 1 32369 4 6 25327 4 0 1 32371 1 32369 1 32371 2 2 32370 1 32371 3 32369 6 0 1 32371 4 2 30989 6 0 1 32377 1 32372 1 32377 2 5 32372 1 32377 3 32372 3 0 1 32377 4 5 25952 15 0 1 32381 1 32379 1 32381 2 2 32377 1 32381 3 32379 3 0 1 32381 4 2 30655 1 0 1 32401 1 32394 1 32401 2 7 32394 1 32401 3 32394 5 0 1 32401 4 7 20058 0 0 1 32411 1 32409 1 32411 2 2 32399 1 32411 3 32409 2 0 1 32411 4 2 30480 1 0 1 32413 1 32408 1 32413 2 5 32412 1 32413 3 32408 1 0 1 32413 4 5 20094 6 0 1 32423 1 32418 1 32423 2 5 32421 1 32423 3 32418 2 0 1 32423 4 5 19579 9 0 1 32429 1 32426 1 32429 2 3 32424 1 32429 3 32426 3 0 1 32429 4 3 17357 2 0 1 32441 1 32438 1 32441 2 3 32440 1 32441 3 32438 3 0 1 32441 4 3 29800 7 0 1 32443 1 32441 1 32443 2 2 32442 1 32443 3 32441 4 0 1 32443 4 2 23922 2 0 1 32467 1 32465 1 32467 2 2 32463 1 32467 3 32465 5 0 1 32467 4 2 29034 8 0 1 32479 1 32473 1 32479 2 6 32477 1 32479 3 32473 2 0 1 32479 4 6 28790 3 0 1 32491 1 32489 1 32491 2 2 32487 1 32491 3 32489 2 0 1 32491 4 2 18735 10 0 1 32497 1 32490 1 32497 2 7 32490 1 32497 3 32490 4 0 1 32497 4 7 16766 21 0 1 32503 1 32500 1 32503 2 3 32501 1 32503 3 32500 5 0 1 32503 4 3 32026 3 0 1 32507 1 32505 1 32507 2 2 32506 1 32507 3 32505 2 0 1 32507 4 2 22167 12 0 1 32531 1 32529 1 32531 2 2 32527 1 32531 3 32529 3 0 1 32531 4 2 16799 7 0 1 32533 1 32531 1 32533 2 2 32529 1 32533 3 32531 6 0 1 32533 4 2 25409 17 0 1 32537 1 32534 1 32537 2 3 32536 1 32537 3 32534 5 0 1 32537 4 3 28952 11 0 1 32561 1 32555 1 32561 2 6 32555 1 32561 3 32555 1 0 1 32561 4 6 19428 0 0 1 32563 1 32561 1 32563 2 2 32562 1 32563 3 32561 2 0 1 32563 4 2 24619 7 0 1 32569 1 32562 1 32569 2 7 32562 1 32569 3 32562 1 0 1 32569 4 7 20514 0 0 1 32573 1 32571 1 32573 2 2 32566 1 32573 3 32571 14 0 1 32573 4 2 29250 5 0 1 32579 1 32573 1 32579 2 6 32577 1 32579 3 32573 3 0 1 32579 4 6 23356 0 0 1 32587 1 32585 1 32587 2 2 32583 1 32587 3 32585 4 0 1 32587 4 2 28439 8 0 1 32603 1 32601 1 32603 2 2 32598 1 32603 3 32601 4 0 1 32603 4 2 24530 9 0 1 32609 1 32606 1 32609 2 3 32603 1 32609 3 32606 3 0 1 32609 4 3 19295 3 0 1 32611 1 32608 1 32611 2 3 32610 1 32611 3 32608 6 0 1 32611 4 3 28696 6 0 1 32621 1 32618 1 32621 2 3 32620 1 32621 3 32618 7 0 1 32621 4 3 29276 3 0 1 32633 1 32630 1 32633 2 3 32627 1 32633 3 32630 5 0 1 32633 4 3 28234 13 0 1 32647 1 32644 1 32647 2 3 32646 1 32647 3 32644 3 0 1 32647 4 3 17491 5 0 1 32653 1 32651 1 32653 2 2 32652 1 32653 3 32651 2 0 1 32653 4 2 22423 6 0 1 32687 1 32682 1 32687 2 5 32684 1 32687 3 32682 2 0 1 32687 4 5 30309 6 0 1 32693 1 32691 1 32693 2 2 32692 1 32693 3 32691 2 0 1 32693 4 2 23175 4 0 1 32707 1 32704 1 32707 2 3 32692 1 32707 3 32704 8 0 1 32707 4 3 23204 1 0 1 32713 1 32708 1 32713 2 5 32712 1 32713 3 32708 1 0 1 32713 4 5 18247 6 0 1 32717 1 32715 1 32717 2 2 32703 1 32717 3 32715 2 0 1 32717 4 2 29481 2 0 1 32719 1 32716 1 32719 2 3 32717 1 32719 3 32716 11 0 1 32719 4 3 32715 4 0 1 32749 1 32747 1 32749 2 2 32748 1 32749 3 32747 5 0 1 32749 4 2 30851 3 0 1 32771 1 32769 1 32771 2 2 32767 1 32771 3 32769 2 0 1 32771 4 2 32259 7 0 1 32779 1 32776 1 32779 2 3 32774 1 32779 3 32776 6 0 1 32779 4 3 26012 3 0 1 32783 1 32776 1 32783 2 7 32782 1 32783 3 32776 2 0 1 32783 4 7 28998 3 0 1 32789 1 32787 1 32789 2 2 32781 1 32789 3 32787 2 0 1 32789 4 2 32277 11 0 1 32797 1 32795 1 32797 2 2 32793 1 32797 3 32795 6 0 1 32797 4 2 28616 9 0 1 32801 1 32798 1 32801 2 3 32800 1 32801 3 32798 3 0 1 32801 4 3 22863 4 0 1 32803 1 32798 1 32803 2 5 32801 1 32803 3 32798 2 0 1 32803 4 5 25866 0 0 1 32831 1 32818 1 32831 2 13 32830 1 32831 3 32818 4 0 1 32831 4 13 18423 2 0 1 32833 1 32828 1 32833 2 5 32828 1 32833 3 32828 3 0 1 32833 4 5 29968 10 0 1 32839 1 32833 1 32839 2 6 32835 1 32839 3 32833 2 0 1 32839 4 6 21220 8 0 1 32843 1 32841 1 32843 2 2 32839 1 32843 3 32841 2 0 1 32843 4 2 17834 11 0 1 32869 1 32863 1 32869 2 6 32865 1 32869 3 32863 9 0 1 32869 4 6 27500 10 0 1 32887 1 32884 1 32887 2 3 32886 1 32887 3 32884 1 0 1 32887 4 3 26361 2 0 1 32909 1 32907 1 32909 2 2 32904 1 32909 3 32907 2 0 1 32909 4 2 18890 16 0 1 32911 1 32908 1 32911 2 3 32910 1 32911 3 32908 1 0 1 32911 4 3 18623 2 0 1 32917 1 32915 1 32917 2 2 32916 1 32917 3 32915 6 0 1 32917 4 2 21131 9 0 1 32933 1 32931 1 32933 2 2 32932 1 32933 3 32931 2 0 1 32933 4 2 20665 3 0 1 32939 1 32937 1 32939 2 2 32929 1 32939 3 32937 2 0 1 32939 4 2 21184 0 0 1 32941 1 32939 1 32941 2 2 32940 1 32941 3 32939 5 0 1 32941 4 2 22761 3 0 1 32957 1 32945 1 32957 2 12 32956 1 32957 3 32945 4 0 1 32957 4 12 18115 9 0 1 32969 1 32966 1 32969 2 3 32963 1 32969 3 32966 8 0 1 32969 4 3 32957 0 0 1 32971 1 32960 1 32971 2 11 32970 1 32971 3 32960 1 0 1 32971 4 11 24648 7 0 1 32983 1 32980 1 32983 2 3 32981 1 32983 3 32980 4 0 1 32983 4 3 16927 3 0 1 32987 1 32985 1 32987 2 2 32986 1 32987 3 32985 2 0 1 32987 4 2 28023 2 0 1 32993 1 32990 1 32993 2 3 32987 1 32993 3 32990 1 0 1 32993 4 3 32244 1 0 1 32999 1 32992 1 32999 2 7 32997 1 32999 3 32992 4 0 1 32999 4 7 31501 5 0 1 33013 1 33008 1 33013 2 5 33012 1 33013 3 33008 2 0 1 33013 4 5 17239 6 0 1 33023 1 33018 1 33023 2 5 33018 1 33023 3 33018 2 0 1 33023 4 5 27157 7 0 1 33029 1 33027 1 33029 2 2 33028 1 33029 3 33027 3 0 1 33029 4 2 27592 3 0 1 33037 1 33035 1 33037 2 2 33033 1 33037 3 33035 4 0 1 33037 4 2 26224 6 0 1 33049 1 33020 1 33049 2 29 33048 1 33049 3 33020 3 0 1 33049 4 29 17775 20 0 1 33053 1 33051 1 33053 2 2 33052 1 33053 3 33051 2 0 1 33053 4 2 23062 4 0 1 33071 1 33060 1 33071 2 11 33060 1 33071 3 33060 4 0 1 33071 4 11 30672 0 0 1 33073 1 33068 1 33073 2 5 33072 1 33073 3 33068 3 0 1 33073 4 5 18093 6 0 1 33083 1 33081 1 33083 2 2 33073 1 33083 3 33081 7 0 1 33083 4 2 29809 8 0 1 33091 1 33088 1 33091 2 3 33086 1 33091 3 33088 1 0 1 33091 4 3 27901 3 0 1 33107 1 33105 1 33107 2 2 33101 1 33107 3 33105 9 0 1 33107 4 2 19761 4 0 1 33113 1 33110 1 33113 2 3 33108 1 33113 3 33110 3 0 1 33113 4 3 22628 0 0 1 33119 1 33112 1 33119 2 7 33118 1 33119 3 33112 1 0 1 33119 4 7 33110 4 0 1 33149 1 33147 1 33149 2 2 33145 1 33149 3 33147 3 0 1 33149 4 2 16778 7 0 1 33151 1 33148 1 33151 2 3 33150 1 33151 3 33148 3 0 1 33151 4 3 26104 2 0 1 33161 1 33158 1 33161 2 3 33156 1 33161 3 33158 9 0 1 33161 4 3 20542 2 0 1 33179 1 33177 1 33179 2 2 33178 1 33179 3 33177 3 0 1 33179 4 2 32385 6 0 1 33181 1 33175 1 33181 2 6 33180 1 33181 3 33175 1 0 1 33181 4 6 22519 7 0 1 33191 1 33184 1 33191 2 7 33190 1 33191 3 33184 2 0 1 33191 4 7 20472 2 0 1 33199 1 33196 1 33199 2 3 33197 1 33199 3 33196 3 0 1 33199 4 3 20640 6 0 1 33203 1 33201 1 33203 2 2 33197 1 33203 3 33201 4 0 1 33203 4 2 21507 4 0 1 33211 1 33209 1 33211 2 2 33210 1 33211 3 33209 6 0 1 33211 4 2 25145 2 0 1 33223 1 33213 1 33223 2 10 33222 1 33223 3 33213 4 0 1 33223 4 10 23554 2 0 1 33247 1 33242 1 33247 2 5 33245 1 33247 3 33242 3 0 1 33247 4 5 27069 10 0 1 33287 1 33282 1 33287 2 5 33286 1 33287 3 33282 2 0 1 33287 4 5 23269 2 0 1 33289 1 33260 1 33289 2 29 33282 1 33289 3 33260 1 0 1 33289 4 29 17665 24 0 1 33301 1 33299 1 33301 2 2 33297 1 33301 3 33299 6 0 1 33301 4 2 29088 12 0 1 33311 1 33300 1 33311 2 11 33310 1 33311 3 33300 11 0 1 33311 4 11 20962 2 0 1 33317 1 33315 1 33317 2 2 33309 1 33317 3 33315 10 0 1 33317 4 2 32351 3 0 1 33329 1 33326 1 33329 2 3 33323 1 33329 3 33326 18 0 1 33329 4 3 33317 0 0 1 33331 1 33328 1 33331 2 3 33324 1 33331 3 33328 1 0 1 33331 4 3 19187 5 0 1 33343 1 33340 1 33343 2 3 33342 1 33343 3 33340 6 0 1 33343 4 3 33332 12 0 1 33347 1 33345 1 33347 2 2 33343 1 33347 3 33345 3 0 1 33347 4 2 27382 7 0 1 33349 1 33347 1 33349 2 2 33345 1 33349 3 33347 4 0 1 33349 4 2 28951 6 0 1 33353 1 33350 1 33353 2 3 33348 1 33353 3 33350 1 0 1 33353 4 3 17232 0 0 1 33359 1 33352 1 33359 2 7 33356 1 33359 3 33352 3 0 1 33359 4 7 32248 5 0 1 33377 1 33372 1 33377 2 5 33376 1 33377 3 33372 3 0 1 33377 4 5 17018 6 0 1 33391 1 33385 1 33391 2 6 33389 1 33391 3 33385 1 0 1 33391 4 6 26084 4 0 1 33403 1 33400 1 33403 2 3 33402 1 33403 3 33400 8 0 1 33403 4 3 26826 5 0 1 33409 1 33402 1 33409 2 7 33402 1 33409 3 33402 11 0 1 33409 4 7 26059 0 0 1 33413 1 33411 1 33413 2 2 33405 1 33413 3 33411 4 0 1 33413 4 2 24533 13 0 1 33427 1 33425 1 33427 2 2 33423 1 33427 3 33425 6 0 1 33427 4 2 23368 10 0 1 33457 1 33447 1 33457 2 10 33456 1 33457 3 33447 5 0 1 33457 4 10 25484 12 0 1 33461 1 33458 1 33461 2 3 33460 1 33461 3 33458 7 0 1 33461 4 3 32603 3 0 1 33469 1 33467 1 33469 2 2 33465 1 33469 3 33467 2 0 1 33469 4 2 22958 10 0 1 33479 1 33462 1 33479 2 17 33478 1 33479 3 33462 1 0 1 33479 4 17 26329 2 0 1 33487 1 33481 1 33487 2 6 33484 1 33487 3 33481 1 0 1 33487 4 6 26490 4 0 1 33493 1 33491 1 33493 2 2 33492 1 33493 3 33491 5 0 1 33493 4 2 33486 8 0 1 33503 1 33498 1 33503 2 5 33501 1 33503 3 33498 8 0 1 33503 4 5 20309 5 0 1 33521 1 33515 1 33521 2 6 33518 1 33521 3 33515 4 0 1 33521 4 6 32624 10 0 1 33529 1 33522 1 33529 2 7 33522 1 33529 3 33522 1 0 1 33529 4 7 25410 0 0 1 33533 1 33531 1 33533 2 2 33532 1 33533 3 33531 3 0 1 33533 4 2 18904 6 0 1 33547 1 33545 1 33547 2 2 33546 1 33547 3 33545 4 0 1 33547 4 2 32059 7 0 1 33563 1 33561 1 33563 2 2 33559 1 33563 3 33561 3 0 1 33563 4 2 22030 14 0 1 33569 1 33566 1 33569 2 3 33563 1 33569 3 33566 8 0 1 33569 4 3 33557 0 0 1 33577 1 33572 1 33577 2 5 33572 1 33577 3 33572 1 0 1 33577 4 5 32243 10 0 1 33581 1 33579 1 33581 2 2 33576 1 33581 3 33579 7 0 1 33581 4 2 31633 2 0 1 33587 1 33581 1 33587 2 6 33573 1 33587 3 33581 1 0 1 33587 4 6 26388 9 0 1 33589 1 33587 1 33589 2 2 33588 1 33589 3 33587 6 0 1 33589 4 2 26734 3 0 1 33599 1 33588 1 33599 2 11 33583 1 33599 3 33588 4 0 1 33599 4 11 26711 3 0 1 33601 1 33572 1 33601 2 29 33600 1 33601 3 33572 1 0 1 33601 4 29 29589 12 0 1 33613 1 33608 1 33613 2 5 33612 1 33613 3 33608 5 0 1 33613 4 5 18310 3 0 1 33617 1 33614 1 33617 2 3 33611 1 33617 3 33614 1 0 1 33617 4 3 31668 11 0 1 33619 1 33617 1 33619 2 2 33618 1 33619 3 33617 5 0 1 33619 4 2 28186 2 0 1 33623 1 33618 1 33623 2 5 33622 1 33623 3 33618 3 0 1 33623 4 5 20626 4 0 1 33629 1 33627 1 33629 2 2 33621 1 33629 3 33627 3 0 1 33629 4 2 20008 0 0 1 33637 1 33635 1 33637 2 2 33633 1 33637 3 33635 6 0 1 33637 4 2 23036 6 0 1 33641 1 33638 1 33641 2 3 33630 1 33641 3 33638 1 0 1 33641 4 3 32587 4 0 1 33647 1 33642 1 33647 2 5 33645 1 33647 3 33642 5 0 1 33647 4 5 21492 5 0 1 33679 1 33676 1 33679 2 3 33678 1 33679 3 33676 1 0 1 33679 4 3 32838 3 0 1 33703 1 33698 1 33703 2 5 33701 1 33703 3 33698 3 0 1 33703 4 5 33699 3 0 1 33713 1 33710 1 33713 2 3 33706 1 33713 3 33710 1 0 1 33713 4 3 25095 2 0 1 33721 1 33710 1 33721 2 11 33716 1 33721 3 33710 3 0 1 33721 4 11 33702 24 0 1 33739 1 33737 1 33739 2 2 33738 1 33739 3 33737 6 0 1 33739 4 2 28573 2 0 1 33749 1 33747 1 33749 2 2 33745 1 33749 3 33747 2 0 1 33749 4 2 25591 12 0 1 33751 1 33745 1 33751 2 6 33750 1 33751 3 33745 1 0 1 33751 4 6 22979 3 0 1 33757 1 33755 1 33757 2 2 33756 1 33757 3 33755 2 0 1 33757 4 2 27295 6 0 1 33767 1 33762 1 33767 2 5 33764 1 33767 3 33762 5 0 1 33767 4 5 17486 4 0 1 33769 1 33758 1 33769 2 11 33753 1 33769 3 33758 3 0 1 33769 4 11 33247 5 0 1 33773 1 33771 1 33773 2 2 33772 1 33773 3 33771 2 0 1 33773 4 2 24868 4 0 1 33791 1 33784 1 33791 2 7 33789 1 33791 3 33784 2 0 1 33791 4 7 22107 11 0 1 33797 1 33794 1 33797 2 3 33795 1 33797 3 33794 6 0 1 33797 4 3 32757 14 0 1 33809 1 33806 1 33809 2 3 33808 1 33809 3 33806 12 0 1 33809 4 3 27277 7 0 1 33811 1 33796 1 33811 2 15 33809 1 33811 3 33796 3 0 1 33811 4 15 24502 0 0 1 33827 1 33825 1 33827 2 2 33826 1 33827 3 33825 12 0 1 33827 4 2 33820 8 0 1 33829 1 33827 1 33829 2 2 33828 1 33829 3 33827 8 0 1 33829 4 2 29111 7 0 1 33851 1 33849 1 33851 2 2 33850 1 33851 3 33849 3 0 1 33851 4 2 33049 6 0 1 33857 1 33854 1 33857 2 3 33856 1 33857 3 33854 1 0 1 33857 4 3 30037 4 0 1 33863 1 33858 1 33863 2 5 33861 1 33863 3 33858 7 0 1 33863 4 5 24686 5 0 1 33871 1 33856 1 33871 2 15 33869 1 33871 3 33856 1 0 1 33871 4 15 26736 4 0 1 33889 1 33876 1 33889 2 13 33880 1 33889 3 33876 5 0 1 33889 4 13 24533 28 0 1 33893 1 33891 1 33893 2 2 33892 1 33893 3 33891 2 0 1 33893 4 2 17992 4 0 1 33911 1 33900 1 33911 2 11 33910 1 33911 3 33900 13 0 1 33911 4 11 26841 3 0 1 33923 1 33921 1 33923 2 2 33911 1 33923 3 33921 5 0 1 33923 4 2 20091 23 0 1 33931 1 33929 1 33931 2 2 33925 1 33931 3 33929 6 0 1 33931 4 2 17987 3 0 1 33937 1 33932 1 33937 2 5 33936 1 33937 3 33932 2 0 1 33937 4 5 20229 6 0 1 33941 1 33939 1 33941 2 2 33940 1 33941 3 33939 3 0 1 33941 4 2 26503 3 0 1 33961 1 33948 1 33961 2 13 33960 1 33961 3 33948 15 0 1 33961 4 13 24460 14 0 1 33967 1 33964 1 33967 2 3 33966 1 33967 3 33964 1 0 1 33967 4 3 20622 5 0 1 33997 1 33995 1 33997 2 2 33996 1 33997 3 33995 2 0 1 33997 4 2 28864 3 0 1 34019 1 34017 1 34019 2 2 34009 1 34019 3 34017 4 0 1 34019 4 2 21975 0 0 1 34031 1 34024 1 34031 2 7 34030 1 34031 3 34024 1 0 1 34031 4 7 34022 4 0 1 34033 1 34026 1 34033 2 7 34026 1 34033 3 34026 3 0 1 34033 4 7 19209 12 0 1 34039 1 34036 1 34039 2 3 34037 1 34039 3 34036 4 0 1 34039 4 3 29357 3 0 1 34057 1 34052 1 34057 2 5 34052 1 34057 3 34052 7 0 1 34057 4 5 24647 25 0 1 34061 1 34059 1 34061 2 2 34057 1 34061 3 34059 3 0 1 34061 4 2 28075 1 0 1 34123 1 34121 1 34123 2 2 34122 1 34123 3 34121 4 0 1 34123 4 2 34116 8 0 1 34127 1 34122 1 34127 2 5 34126 1 34127 3 34122 7 0 1 34127 4 5 33807 2 0 1 34129 1 34118 1 34129 2 11 34128 1 34129 3 34118 3 0 1 34129 4 11 27504 18 0 1 34141 1 34139 1 34141 2 2 34137 1 34141 3 34139 4 0 1 34141 4 2 17568 6 0 1 34147 1 34144 1 34147 2 3 34138 1 34147 3 34144 1 0 1 34147 4 3 22260 2 0 1 34157 1 34155 1 34157 2 2 34153 1 34157 3 34155 3 0 1 34157 4 2 19275 12 0 1 34159 1 34156 1 34159 2 3 34154 1 34159 3 34156 4 0 1 34159 4 3 20405 7 0 1 34171 1 34169 1 34171 2 2 34167 1 34171 3 34169 6 0 1 34171 4 2 23285 8 0 1 34183 1 34180 1 34183 2 3 34182 1 34183 3 34180 1 0 1 34183 4 3 26315 2 0 1 34211 1 34209 1 34211 2 2 34207 1 34211 3 34209 16 0 1 34211 4 2 30318 7 0 1 34213 1 34211 1 34213 2 2 34209 1 34213 3 34211 6 0 1 34213 4 2 21739 10 0 1 34217 1 34214 1 34217 2 3 34211 1 34217 3 34214 1 0 1 34217 4 3 30499 12 0 1 34231 1 34225 1 34231 2 6 34229 1 34231 3 34225 3 0 1 34231 4 6 18282 4 0 1 34253 1 34251 1 34253 2 2 34241 1 34253 3 34251 20 0 1 34253 4 2 22385 4 0 1 34259 1 34257 1 34259 2 2 34242 1 34259 3 34257 2 0 1 34259 4 2 27770 7 0 1 34261 1 34259 1 34261 2 2 34260 1 34261 3 34259 6 0 1 34261 4 2 27220 3 0 1 34267 1 34265 1 34267 2 2 34262 1 34267 3 34265 5 0 1 34267 4 2 22256 2 0 1 34273 1 34268 1 34273 2 5 34270 1 34273 3 34268 3 0 1 34273 4 5 20465 18 0 1 34283 1 34281 1 34283 2 2 34277 1 34283 3 34281 9 0 1 34283 4 2 30976 7 0 1 34297 1 34292 1 34297 2 5 34296 1 34297 3 34292 2 0 1 34297 4 5 24969 6 0 1 34301 1 34298 1 34301 2 3 34289 1 34301 3 34298 17 0 1 34301 4 3 30648 2 0 1 34303 1 34286 1 34303 2 17 34302 1 34303 3 34286 1 0 1 34303 4 17 20822 2 0 1 34313 1 34310 1 34313 2 3 34308 1 34313 3 34310 3 0 1 34313 4 3 25339 0 0 1 34319 1 34300 1 34319 2 19 34301 1 34319 3 34300 1 0 1 34319 4 19 29846 19 0 1 34327 1 34322 1 34327 2 5 34326 1 34327 3 34322 3 0 1 34327 4 5 31086 2 0 1 34337 1 34334 1 34337 2 3 34336 1 34337 3 34334 1 0 1 34337 4 3 22979 6 0 1 34351 1 34348 1 34351 2 3 34349 1 34351 3 34348 1 0 1 34351 4 3 32470 3 0 1 34361 1 34358 1 34361 2 3 34360 1 34361 3 34358 3 0 1 34361 4 3 30241 7 0 1 34367 1 34362 1 34367 2 5 34366 1 34367 3 34362 3 0 1 34367 4 5 19563 4 0 1 34369 1 34362 1 34369 2 7 34358 1 34369 3 34362 2 0 1 34369 4 7 21857 18 0 1 34381 1 34375 1 34381 2 6 34380 1 34381 3 34375 2 0 1 34381 4 6 18518 11 0 1 34403 1 34401 1 34403 2 2 34402 1 34403 3 34401 2 0 1 34403 4 2 18263 13 0 1 34421 1 34419 1 34421 2 2 34417 1 34421 3 34419 2 0 1 34421 4 2 32218 23 0 1 34429 1 34427 1 34429 2 2 34428 1 34429 3 34427 4 0 1 34429 4 2 21285 3 0 1 34439 1 34428 1 34439 2 11 34437 1 34439 3 34428 11 0 1 34439 4 11 17799 3 0 1 34457 1 34454 1 34457 2 3 34452 1 34457 3 34454 3 0 1 34457 4 3 25198 0 0 1 34469 1 34459 1 34469 2 10 34460 1 34469 3 34459 7 0 1 34469 4 10 24838 7 0 1 34471 1 34465 1 34471 2 6 34470 1 34471 3 34465 1 0 1 34471 4 6 19446 3 0 1 34483 1 34481 1 34483 2 2 34479 1 34483 3 34481 6 0 1 34483 4 2 24949 8 0 1 34487 1 34482 1 34487 2 5 34486 1 34487 3 34482 1 0 1 34487 4 5 28325 4 0 1 34499 1 34497 1 34499 2 2 34495 1 34499 3 34497 3 0 1 34499 4 2 18492 7 0 1 34501 1 34494 1 34501 2 7 34499 1 34501 3 34494 4 0 1 34501 4 7 28465 12 0 1 34511 1 34504 1 34511 2 7 34509 1 34511 3 34504 1 0 1 34511 4 7 24801 4 0 1 34513 1 34502 1 34513 2 11 34512 1 34513 3 34502 2 0 1 34513 4 11 33682 8 0 1 34519 1 34516 1 34519 2 3 34517 1 34519 3 34516 4 0 1 34519 4 3 25289 3 0 1 34537 1 34532 1 34537 2 5 34536 1 34537 3 34532 11 0 1 34537 4 5 34274 6 0 1 34543 1 34537 1 34543 2 6 34542 1 34543 3 34537 1 0 1 34543 4 6 28376 3 0 1 34549 1 34547 1 34549 2 2 34545 1 34549 3 34547 2 0 1 34549 4 2 19235 6 0 1 34583 1 34578 1 34583 2 5 34582 1 34583 3 34578 1 0 1 34583 4 5 32137 4 0 1 34589 1 34587 1 34589 2 2 34585 1 34589 3 34587 7 0 1 34589 4 2 23410 6 0 1 34591 1 34588 1 34591 2 3 34590 1 34591 3 34588 5 0 1 34591 4 3 24433 2 0 1 34603 1 34601 1 34603 2 2 34599 1 34603 3 34601 4 0 1 34603 4 2 21587 8 0 1 34607 1 34597 1 34607 2 10 34605 1 34607 3 34597 6 0 1 34607 4 10 24077 4 0 1 34613 1 34611 1 34613 2 2 34609 1 34613 3 34611 2 0 1 34613 4 2 30117 1 0 1 34631 1 34624 1 34631 2 7 34630 1 34631 3 34624 3 0 1 34631 4 7 20505 3 0 1 34649 1 34646 1 34649 2 3 34648 1 34649 3 34646 7 0 1 34649 4 3 25174 7 0 1 34651 1 34649 1 34651 2 2 34647 1 34651 3 34649 2 0 1 34651 4 2 27131 8 0 1 34667 1 34665 1 34667 2 2 34663 1 34667 3 34665 2 0 1 34667 4 2 22401 7 0 1 34673 1 34670 1 34673 2 3 34668 1 34673 3 34670 3 0 1 34673 4 3 29380 0 0 1 34679 1 34672 1 34679 2 7 34675 1 34679 3 34672 4 0 1 34679 4 7 28528 5 0 1 34687 1 34682 1 34687 2 5 34686 1 34687 3 34682 11 0 1 34687 4 5 20425 5 0 1 34693 1 34687 1 34693 2 6 34691 1 34693 3 34687 1 0 1 34693 4 6 26188 8 0 1 34703 1 34698 1 34703 2 5 34701 1 34703 3 34698 6 0 1 34703 4 5 24420 5 0 1 34721 1 34718 1 34721 2 3 34716 1 34721 3 34718 1 0 1 34721 4 3 34194 8 0 1 34729 1 34716 1 34729 2 13 34726 1 34729 3 34716 6 0 1 34729 4 13 22002 14 0 1 34739 1 34733 1 34739 2 6 34736 1 34739 3 34733 1 0 1 34739 4 6 29717 1 0 1 34747 1 34745 1 34747 2 2 34746 1 34747 3 34745 2 0 1 34747 4 2 34740 8 0 1 34757 1 34755 1 34757 2 2 34749 1 34757 3 34755 13 0 1 34757 4 2 18057 11 0 1 34759 1 34753 1 34759 2 6 34757 1 34759 3 34753 2 0 1 34759 4 6 25196 4 0 1 34763 1 34761 1 34763 2 2 34759 1 34763 3 34761 3 0 1 34763 4 2 26536 8 0 1 34781 1 34779 1 34781 2 2 34775 1 34781 3 34779 3 0 1 34781 4 2 34012 3 0 1 34807 1 34804 1 34807 2 3 34805 1 34807 3 34804 10 0 1 34807 4 3 30898 3 0 1 34819 1 34817 1 34819 2 2 34814 1 34819 3 34817 2 0 1 34819 4 2 20983 3 0 1 34841 1 34838 1 34841 2 3 34835 1 34841 3 34838 4 0 1 34841 4 3 34829 0 0 1 34843 1 34841 1 34843 2 2 34839 1 34843 3 34841 4 0 1 34843 4 2 21035 8 0 1 34847 1 34840 1 34847 2 7 34845 1 34847 3 34840 2 0 1 34847 4 7 33401 6 0 1 34849 1 34842 1 34849 2 7 34842 1 34849 3 34842 7 0 1 34849 4 7 28928 0 0 1 34871 1 34864 1 34871 2 7 34870 1 34871 3 34864 3 0 1 34871 4 7 22279 2 0 1 34877 1 34875 1 34877 2 2 34876 1 34877 3 34875 2 0 1 34877 4 2 18970 3 0 1 34883 1 34881 1 34883 2 2 34877 1 34883 3 34881 4 0 1 34883 4 2 24993 0 0 1 34897 1 34892 1 34897 2 5 34896 1 34897 3 34892 7 0 1 34897 4 5 25694 11 0 1 34913 1 34910 1 34913 2 3 34908 1 34913 3 34910 1 0 1 34913 4 3 21047 0 0 1 34919 1 34900 1 34919 2 19 34918 1 34919 3 34900 1 0 1 34919 4 19 27648 2 0 1 34939 1 34937 1 34939 2 2 34935 1 34939 3 34937 2 0 1 34939 4 2 22028 10 0 1 34949 1 34947 1 34949 2 2 34945 1 34949 3 34947 3 0 1 34949 4 2 33588 1 0 1 34961 1 34958 1 34961 2 3 34949 1 34961 3 34958 1 0 1 34961 4 3 21770 0 0 1 34963 1 34961 1 34963 2 2 34962 1 34963 3 34961 2 0 1 34963 4 2 32993 2 0 1 34981 1 34979 1 34981 2 2 34977 1 34981 3 34979 6 0 1 34981 4 2 21190 6 0 1 35023 1 35018 1 35023 2 5 35021 1 35023 3 35018 2 0 1 35023 4 5 35019 3 0 1 35027 1 35025 1 35027 2 2 35023 1 35027 3 35025 3 0 1 35027 4 2 33020 11 0 1 35051 1 35049 1 35051 2 2 35047 1 35051 3 35049 3 0 1 35051 4 2 31484 7 0 1 35053 1 35051 1 35053 2 2 35049 1 35053 3 35051 6 0 1 35053 4 2 34378 12 0 1 35059 1 35049 1 35059 2 10 35058 1 35059 3 35049 2 0 1 35059 4 10 24233 2 0 1 35069 1 35067 1 35069 2 2 35065 1 35069 3 35067 3 0 1 35069 4 2 23519 1 0 1 35081 1 35078 1 35081 2 3 35080 1 35081 3 35078 4 0 1 35081 4 3 24328 4 0 1 35083 1 35081 1 35083 2 2 35082 1 35083 3 35081 2 0 1 35083 4 2 30282 11 0 1 35089 1 35078 1 35089 2 11 35086 1 35089 3 35078 11 0 1 35089 4 11 23856 10 0 1 35099 1 35097 1 35099 2 2 35095 1 35099 3 35097 2 0 1 35099 4 2 30378 7 0 1 35107 1 35105 1 35107 2 2 35103 1 35107 3 35105 5 0 1 35107 4 2 33400 8 0 1 35111 1 35098 1 35111 2 13 35106 1 35111 3 35098 2 0 1 35111 4 13 34316 6 0 1 35117 1 35115 1 35117 2 2 35116 1 35117 3 35115 2 0 1 35117 4 2 29689 4 0 1 35129 1 35126 1 35129 2 3 35128 1 35129 3 35126 4 0 1 35129 4 3 30888 4 0 1 35141 1 35139 1 35141 2 2 35137 1 35141 3 35139 2 0 1 35141 4 2 22688 7 0 1 35149 1 35147 1 35149 2 2 35145 1 35149 3 35147 2 0 1 35149 4 2 33603 6 0 1 35153 1 35150 1 35153 2 3 35152 1 35153 3 35150 10 0 1 35153 4 3 30948 7 0 1 35159 1 35148 1 35159 2 11 35158 1 35159 3 35148 2 0 1 35159 4 11 27315 3 0 1 35171 1 35169 1 35171 2 2 35164 1 35171 3 35169 4 0 1 35171 4 2 30035 1 0 1 35201 1 35198 1 35201 2 3 35195 1 35201 3 35198 5 0 1 35201 4 3 35189 0 0 1 35221 1 35215 1 35221 2 6 35217 1 35221 3 35215 4 0 1 35221 4 6 19694 2 0 1 35227 1 35225 1 35227 2 2 35226 1 35227 3 35225 2 0 1 35227 4 2 21352 11 0 1 35251 1 35248 1 35251 2 3 35250 1 35251 3 35248 6 0 1 35251 4 3 34574 7 0 1 35257 1 35250 1 35257 2 7 35250 1 35257 3 35250 5 0 1 35257 4 7 22970 12 0 1 35267 1 35265 1 35267 2 2 35263 1 35267 3 35265 3 0 1 35267 4 2 34156 7 0 1 35279 1 35250 1 35279 2 29 35278 1 35279 3 35250 7 0 1 35279 4 29 18049 2 0 1 35281 1 35258 1 35281 2 23 35278 1 35281 3 35258 1 0 1 35281 4 23 25185 32 0 1 35291 1 35289 1 35291 2 2 35287 1 35291 3 35289 2 0 1 35291 4 2 23112 8 0 1 35311 1 35300 1 35311 2 11 35310 1 35311 3 35300 3 0 1 35311 4 11 20984 3 0 1 35317 1 35312 1 35317 2 5 35316 1 35317 3 35312 1 0 1 35317 4 5 23743 6 0 1 35323 1 35320 1 35323 2 3 35322 1 35323 3 35320 8 0 1 35323 4 3 20708 5 0 1 35327 1 35322 1 35327 2 5 35324 1 35327 3 35322 1 0 1 35327 4 5 23922 4 0 1 35339 1 35337 1 35339 2 2 35338 1 35339 3 35337 3 0 1 35339 4 2 20494 4 0 1 35353 1 35348 1 35353 2 5 35352 1 35353 3 35348 5 0 1 35353 4 5 21644 8 0 1 35363 1 35361 1 35363 2 2 35359 1 35363 3 35361 2 0 1 35363 4 2 29573 7 0 1 35381 1 35378 1 35381 2 3 35379 1 35381 3 35378 3 0 1 35381 4 3 28683 14 0 1 35393 1 35390 1 35393 2 3 35392 1 35393 3 35390 1 0 1 35393 4 3 20372 7 0 1 35401 1 35388 1 35401 2 13 35400 1 35401 3 35388 7 0 1 35401 4 13 24079 14 0 1 35407 1 35401 1 35407 2 6 35406 1 35407 3 35401 2 0 1 35407 4 6 22403 9 0 1 35419 1 35417 1 35419 2 2 35418 1 35419 3 35417 4 0 1 35419 4 2 35412 8 0 1 35423 1 35418 1 35423 2 5 35421 1 35423 3 35418 3 0 1 35423 4 5 31626 5 0 1 35437 1 35431 1 35437 2 6 35436 1 35437 3 35431 1 0 1 35437 4 6 25467 6 0 1 35447 1 35442 1 35447 2 5 35445 1 35447 3 35442 1 0 1 35447 4 5 20162 5 0 1 35449 1 35436 1 35449 2 13 35432 1 35449 3 35436 5 0 1 35449 4 13 30833 6 0 1 35461 1 35455 1 35461 2 6 35457 1 35461 3 35455 1 0 1 35461 4 6 35457 6 0 1 35491 1 35484 1 35491 2 7 35489 1 35491 3 35484 4 0 1 35491 4 7 24761 6 0 1 35507 1 35505 1 35507 2 2 35506 1 35507 3 35505 2 0 1 35507 4 2 32405 2 0 1 35509 1 35507 1 35509 2 2 35508 1 35509 3 35507 4 0 1 35509 4 2 19205 7 0 1 35521 1 35514 1 35521 2 7 35518 1 35521 3 35514 1 0 1 35521 4 7 33397 14 0 1 35527 1 35524 1 35527 2 3 35526 1 35527 3 35524 5 0 1 35527 4 3 20682 5 0 1 35531 1 35525 1 35531 2 6 35530 1 35531 3 35525 1 0 1 35531 4 6 27235 4 0 1 35533 1 35531 1 35533 2 2 35529 1 35533 3 35531 4 0 1 35533 4 2 33119 6 0 1 35537 1 35534 1 35537 2 3 35536 1 35537 3 35534 7 0 1 35537 4 3 30152 4 0 1 35543 1 35538 1 35543 2 5 35542 1 35543 3 35538 3 0 1 35543 4 5 29884 3 0 1 35569 1 35558 1 35569 2 11 35568 1 35569 3 35558 4 0 1 35569 4 11 31907 18 0 1 35573 1 35571 1 35573 2 2 35566 1 35573 3 35571 2 0 1 35573 4 2 22925 4 0 1 35591 1 35574 1 35591 2 17 35589 1 35591 3 35574 1 0 1 35591 4 17 35583 3 0 1 35593 1 35588 1 35593 2 5 35590 1 35593 3 35588 2 0 1 35593 4 5 32282 10 0 1 35597 1 35595 1 35597 2 2 35593 1 35597 3 35595 3 0 1 35597 4 2 32596 9 0 1 35603 1 35601 1 35603 2 2 35599 1 35603 3 35601 3 0 1 35603 4 2 34191 7 0 1 35617 1 35606 1 35617 2 11 35615 1 35617 3 35606 12 0 1 35617 4 11 31025 32 0 1 35671 1 35668 1 35671 2 3 35665 1 35671 3 35668 6 0 1 35671 4 3 33223 7 0 1 35677 1 35675 1 35677 2 2 35676 1 35677 3 35675 2 0 1 35677 4 2 33207 20 0 1 35729 1 35726 1 35729 2 3 35724 1 35729 3 35726 3 0 1 35729 4 3 22054 2 0 1 35731 1 35729 1 35731 2 2 35730 1 35731 3 35729 4 0 1 35731 4 2 20912 6 0 1 35747 1 35745 1 35747 2 2 35739 1 35747 3 35745 5 0 1 35747 4 2 20052 0 0 1 35753 1 35750 1 35753 2 3 35741 1 35753 3 35750 8 0 1 35753 4 3 24804 6 0 1 35759 1 35748 1 35759 2 11 35758 1 35759 3 35748 2 0 1 35759 4 11 31616 4 0 1 35771 1 35765 1 35771 2 6 35769 1 35771 3 35765 6 0 1 35771 4 6 23040 0 0 1 35797 1 35795 1 35797 2 2 35793 1 35797 3 35795 2 0 1 35797 4 2 21997 9 0 1 35801 1 35798 1 35801 2 3 35800 1 35801 3 35798 1 0 1 35801 4 3 18410 4 0 1 35803 1 35789 1 35803 2 14 35802 1 35803 3 35789 12 0 1 35803 4 14 28409 2 0 1 35809 1 35796 1 35809 2 13 35808 1 35809 3 35796 1 0 1 35809 4 13 20668 14 0 1 35831 1 35820 1 35831 2 11 35829 1 35831 3 35820 1 0 1 35831 4 11 27470 3 0 1 35837 1 35835 1 35837 2 2 35833 1 35837 3 35835 3 0 1 35837 4 2 27920 7 0 1 35839 1 35833 1 35839 2 6 35837 1 35839 3 35833 1 0 1 35839 4 6 20789 3 0 1 35851 1 35849 1 35851 2 2 35847 1 35851 3 35849 2 0 1 35851 4 2 32401 8 0 1 35863 1 35860 1 35863 2 3 35861 1 35863 3 35860 3 0 1 35863 4 3 25693 3 0 1 35869 1 35859 1 35869 2 10 35868 1 35869 3 35859 2 0 1 35869 4 10 25437 3 0 1 35879 1 35872 1 35879 2 7 35865 1 35879 3 35872 8 0 1 35879 4 7 26393 16 0 1 35897 1 35894 1 35897 2 3 35881 1 35897 3 35894 1 0 1 35897 4 3 24352 10 0 1 35899 1 35897 1 35899 2 2 35898 1 35899 3 35897 4 0 1 35899 4 2 34062 10 0 1 35911 1 35899 1 35911 2 12 35909 1 35911 3 35899 4 0 1 35911 4 12 30858 4 0 1 35923 1 35921 1 35923 2 2 35922 1 35923 3 35921 5 0 1 35923 4 2 35916 8 0 1 35933 1 35931 1 35933 2 2 35929 1 35933 3 35931 3 0 1 35933 4 2 26455 6 0 1 35951 1 35940 1 35951 2 11 35949 1 35951 3 35940 2 0 1 35951 4 11 20372 3 0 1 35963 1 35961 1 35963 2 2 35956 1 35963 3 35961 5 0 1 35963 4 2 21073 2 0 1 35969 1 35966 1 35969 2 3 35962 1 35969 3 35966 1 0 1 35969 4 3 35285 0 0 1 35977 1 35967 1 35977 2 10 35976 1 35977 3 35967 10 0 1 35977 4 10 29866 6 0 1 35983 1 35980 1 35983 2 3 35982 1 35983 3 35980 1 0 1 35983 4 3 32077 5 0 1 35993 1 35990 1 35993 2 3 35986 1 35993 3 35990 11 0 1 35993 4 3 21439 4 0 1 35999 1 35986 1 35999 2 13 35997 1 35999 3 35986 1 0 1 35999 4 13 19538 3 0 1 36007 1 36004 1 36007 2 3 36005 1 36007 3 36004 3 0 1 36007 4 3 33167 6 0 1 36011 1 36009 1 36011 2 2 36010 1 36011 3 36009 3 0 1 36011 4 2 36004 8 0 1 36013 1 36011 1 36013 2 2 36012 1 36013 3 36011 6 0 1 36013 4 2 30730 3 0 1 36017 1 36014 1 36017 2 3 36012 1 36017 3 36014 1 0 1 36017 4 3 25143 0 0 1 36037 1 36035 1 36037 2 2 36033 1 36037 3 36035 5 0 1 36037 4 2 31822 6 0 1 36061 1 36059 1 36061 2 2 36057 1 36061 3 36059 2 0 1 36061 4 2 24535 10 0 1 36067 1 36062 1 36067 2 5 36065 1 36067 3 36062 1 0 1 36067 4 5 29480 0 0 1 36073 1 36068 1 36073 2 5 36068 1 36073 3 36068 1 0 1 36073 4 5 30882 15 0 1 36083 1 36081 1 36083 2 2 36074 1 36083 3 36081 2 0 1 36083 4 2 34713 1 0 1 36097 1 36092 1 36097 2 5 36094 1 36097 3 36092 1 0 1 36097 4 5 36086 14 0 1 36107 1 36105 1 36107 2 2 36101 1 36107 3 36105 7 0 1 36107 4 2 31026 4 0 1 36109 1 36107 1 36109 2 2 36108 1 36109 3 36107 6 0 1 36109 4 2 25606 3 0 1 36131 1 36129 1 36131 2 2 36126 1 36131 3 36129 2 0 1 36131 4 2 29519 3 0 1 36137 1 36134 1 36137 2 3 36131 1 36137 3 36134 4 0 1 36137 4 3 19639 1 0 1 36151 1 36148 1 36151 2 3 36149 1 36151 3 36148 8 0 1 36151 4 3 32430 3 0 1 36161 1 36158 1 36161 2 3 36153 1 36161 3 36158 3 0 1 36161 4 3 31503 1 0 1 36187 1 36184 1 36187 2 3 36186 1 36187 3 36184 7 0 1 36187 4 3 33102 5 0 1 36191 1 36184 1 36191 2 7 36189 1 36191 3 36184 3 0 1 36191 4 7 34588 4 0 1 36209 1 36206 1 36209 2 3 36195 1 36209 3 36206 8 0 1 36209 4 3 33794 0 0 1 36217 1 36198 1 36217 2 19 36213 1 36217 3 36198 4 0 1 36217 4 19 30943 11 0 1 36229 1 36227 1 36229 2 2 36225 1 36229 3 36227 5 0 1 36229 4 2 23421 10 0 1 36241 1 36222 1 36241 2 19 36238 1 36241 3 36222 1 0 1 36241 4 19 30081 22 0 1 36251 1 36249 1 36251 2 2 36247 1 36251 3 36249 3 0 1 36251 4 2 29127 7 0 1 36263 1 36258 1 36263 2 5 36258 1 36263 3 36258 11 0 1 36263 4 5 29741 8 0 1 36269 1 36267 1 36269 2 2 36265 1 36269 3 36267 2 0 1 36269 4 2 25760 7 0 1 36277 1 36275 1 36277 2 2 36276 1 36277 3 36275 4 0 1 36277 4 2 20036 3 0 1 36293 1 36291 1 36293 2 2 36292 1 36293 3 36291 3 0 1 36293 4 2 19996 6 0 1 36299 1 36297 1 36299 2 2 36295 1 36299 3 36297 2 0 1 36299 4 2 28690 7 0 1 36307 1 36305 1 36307 2 2 36306 1 36307 3 36305 4 0 1 36307 4 2 34759 7 0 1 36313 1 36308 1 36313 2 5 36310 1 36313 3 36308 1 0 1 36313 4 5 32125 18 0 1 36319 1 36313 1 36319 2 6 36315 1 36319 3 36313 1 0 1 36319 4 6 26609 1 0 1 36341 1 36339 1 36341 2 2 36337 1 36341 3 36339 2 0 1 36341 4 2 33197 6 0 1 36343 1 36330 1 36343 2 13 36342 1 36343 3 36330 3 0 1 36343 4 13 23388 2 0 1 36353 1 36350 1 36353 2 3 36348 1 36353 3 36350 3 0 1 36353 4 3 33590 2 0 1 36373 1 36371 1 36373 2 2 36369 1 36373 3 36371 6 0 1 36373 4 2 29979 6 0 1 36383 1 36378 1 36383 2 5 36380 1 36383 3 36378 1 0 1 36383 4 5 30951 4 0 1 36389 1 36386 1 36389 2 3 36387 1 36389 3 36386 6 0 1 36389 4 3 29737 12 0 1 36433 1 36428 1 36433 2 5 36432 1 36433 3 36428 1 0 1 36433 4 5 32929 6 0 1 36451 1 36444 1 36451 2 7 36445 1 36451 3 36444 19 0 1 36451 4 7 36447 4 0 1 36457 1 36452 1 36457 2 5 36456 1 36457 3 36452 2 0 1 36457 4 5 20331 6 0 1 36467 1 36465 1 36467 2 2 36463 1 36467 3 36465 3 0 1 36467 4 2 35613 7 0 1 36469 1 36467 1 36469 2 2 36468 1 36469 3 36467 6 0 1 36469 4 2 23910 9 0 1 36473 1 36470 1 36473 2 3 36472 1 36473 3 36470 1 0 1 36473 4 3 19617 7 0 1 36479 1 36472 1 36479 2 7 36476 1 36479 3 36472 8 0 1 36479 4 7 29389 5 0 1 36493 1 36491 1 36493 2 2 36489 1 36493 3 36491 6 0 1 36493 4 2 26318 6 0 1 36497 1 36494 1 36497 2 3 36496 1 36497 3 36494 4 0 1 36497 4 3 24594 6 0 1 36523 1 36521 1 36523 2 2 36519 1 36523 3 36521 6 0 1 36523 4 2 21049 18 0 1 36527 1 36522 1 36527 2 5 36525 1 36527 3 36522 5 0 1 36527 4 5 36523 3 0 1 36529 1 36522 1 36529 2 7 36522 1 36529 3 36522 4 0 1 36529 4 7 35431 0 0 1 36541 1 36531 1 36541 2 10 36540 1 36541 3 36531 3 0 1 36541 4 10 29944 3 0 1 36551 1 36544 1 36551 2 7 36550 1 36551 3 36544 1 0 1 36551 4 7 21398 2 0 1 36559 1 36553 1 36559 2 6 36557 1 36559 3 36553 2 0 1 36559 4 6 20681 3 0 1 36563 1 36561 1 36563 2 2 36559 1 36563 3 36561 3 0 1 36563 4 2 22728 14 0 1 36571 1 36569 1 36571 2 2 36570 1 36571 3 36569 5 0 1 36571 4 2 31515 2 0 1 36583 1 36576 1 36583 2 7 36580 1 36583 3 36576 1 0 1 36583 4 7 34883 0 0 1 36587 1 36585 1 36587 2 2 36582 1 36587 3 36585 2 0 1 36587 4 2 30336 0 0 1 36599 1 36580 1 36599 2 19 36595 1 36599 3 36580 3 0 1 36599 4 19 28767 9 0 1 36607 1 36604 1 36607 2 3 36606 1 36607 3 36604 3 0 1 36607 4 3 19013 5 0 1 36629 1 36627 1 36629 2 2 36628 1 36629 3 36627 3 0 1 36629 4 2 32104 3 0 1 36637 1 36632 1 36637 2 5 36634 1 36637 3 36632 6 0 1 36637 4 5 33971 1 0 1 36643 1 36640 1 36643 2 3 36642 1 36643 3 36640 1 0 1 36643 4 3 34748 2 0 1 36653 1 36651 1 36653 2 2 36649 1 36653 3 36651 3 0 1 36653 4 2 32200 12 0 1 36671 1 36658 1 36671 2 13 36670 1 36671 3 36658 1 0 1 36671 4 13 28165 4 0 1 36677 1 36675 1 36677 2 2 36673 1 36677 3 36675 4 0 1 36677 4 2 26307 12 0 1 36683 1 36681 1 36683 2 2 36679 1 36683 3 36681 2 0 1 36683 4 2 19255 11 0 1 36691 1 36689 1 36691 2 2 36687 1 36691 3 36689 6 0 1 36691 4 2 27601 8 0 1 36697 1 36692 1 36697 2 5 36696 1 36697 3 36692 2 0 1 36697 4 5 31757 6 0 1 36709 1 36707 1 36709 2 2 36705 1 36709 3 36707 2 0 1 36709 4 2 32935 6 0 1 36713 1 36710 1 36713 2 3 36712 1 36713 3 36710 12 0 1 36713 4 3 21973 7 0 1 36721 1 36684 1 36721 2 37 36716 1 36721 3 36684 8 0 1 36721 4 37 30482 12 0 1 36739 1 36737 1 36739 2 2 36738 1 36739 3 36737 5 0 1 36739 4 2 36407 2 0 1 36749 1 36747 1 36749 2 2 36745 1 36749 3 36747 3 0 1 36749 4 2 28643 1 0 1 36761 1 36755 1 36761 2 6 36751 1 36761 3 36755 1 0 1 36761 4 6 26036 4 0 1 36767 1 36762 1 36767 2 5 36766 1 36767 3 36762 2 0 1 36767 4 5 22326 4 0 1 36779 1 36777 1 36779 2 2 36775 1 36779 3 36777 2 0 1 36779 4 2 20821 8 0 1 36781 1 36779 1 36781 2 2 36780 1 36781 3 36779 6 0 1 36781 4 2 25314 3 0 1 36787 1 36785 1 36787 2 2 36783 1 36787 3 36785 4 0 1 36787 4 2 22006 8 0 1 36791 1 36774 1 36791 2 17 36787 1 36791 3 36774 1 0 1 36791 4 17 22588 7 0 1 36793 1 36778 1 36793 2 15 36790 1 36793 3 36778 2 0 1 36793 4 15 36460 13 0 1 36809 1 36806 1 36809 2 3 36804 1 36809 3 36806 3 0 1 36809 4 3 27220 2 0 1 36821 1 36819 1 36821 2 2 36814 1 36821 3 36819 5 0 1 36821 4 2 20832 9 0 1 36833 1 36830 1 36833 2 3 36827 1 36833 3 36830 5 0 1 36833 4 3 31974 9 0 1 36847 1 36844 1 36847 2 3 36846 1 36847 3 36844 4 0 1 36847 4 3 19359 5 0 1 36857 1 36854 1 36857 2 3 36856 1 36857 3 36854 5 0 1 36857 4 3 32096 7 0 1 36871 1 36856 1 36871 2 15 36870 1 36871 3 36856 5 0 1 36871 4 15 31644 3 0 1 36877 1 36875 1 36877 2 2 36873 1 36877 3 36875 4 0 1 36877 4 2 23194 9 0 1 36887 1 36882 1 36887 2 5 36886 1 36887 3 36882 1 0 1 36887 4 5 31122 3 0 1 36899 1 36897 1 36899 2 2 36893 1 36899 3 36897 9 0 1 36899 4 2 29442 4 0 1 36901 1 36899 1 36901 2 2 36897 1 36901 3 36899 2 0 1 36901 4 2 25191 6 0 1 36913 1 36908 1 36913 2 5 36912 1 36913 3 36908 21 0 1 36913 4 5 18803 6 0 1 36919 1 36916 1 36919 2 3 36917 1 36919 3 36916 3 0 1 36919 4 3 20454 3 0 1 36923 1 36921 1 36923 2 2 36919 1 36923 3 36921 2 0 1 36923 4 2 34345 11 0 1 36929 1 36926 1 36929 2 3 36919 1 36929 3 36926 11 0 1 36929 4 3 21647 4 0 1 36931 1 36929 1 36931 2 2 36930 1 36931 3 36929 4 0 1 36931 4 2 30324 2 0 1 36943 1 36940 1 36943 2 3 36941 1 36943 3 36940 3 0 1 36943 4 3 36935 10 0 1 36947 1 36945 1 36947 2 2 36940 1 36947 3 36945 8 0 1 36947 4 2 24391 0 0 1 36973 1 36971 1 36973 2 2 36972 1 36973 3 36971 2 0 1 36973 4 2 23162 3 0 1 36979 1 36976 1 36979 2 3 36978 1 36979 3 36976 7 0 1 36979 4 3 19090 6 0 1 36997 1 36995 1 36997 2 2 36993 1 36997 3 36995 4 0 1 36997 4 2 21881 6 0 1 37003 1 37001 1 37003 2 2 36999 1 37003 3 37001 5 0 1 37003 4 2 26101 8 0 1 37013 1 37011 1 37013 2 2 37005 1 37013 3 37011 10 0 1 37013 4 2 29720 5 0 1 37019 1 37017 1 37019 2 2 37014 1 37019 3 37017 4 0 1 37019 4 2 22512 3 0 1 37021 1 37015 1 37021 2 6 37020 1 37021 3 37015 4 0 1 37021 4 6 32663 18 0 1 37039 1 37036 1 37039 2 3 37038 1 37039 3 37036 1 0 1 37039 4 3 25707 2 0 1 37049 1 37043 1 37049 2 6 37046 1 37049 3 37043 1 0 1 37049 4 6 23618 15 0 1 37057 1 37052 1 37057 2 5 37048 1 37057 3 37052 3 0 1 37057 4 5 34294 2 0 1 37061 1 37059 1 37061 2 2 37060 1 37061 3 37059 7 0 1 37061 4 2 26907 3 0 1 37087 1 37084 1 37087 2 3 37086 1 37087 3 37084 1 0 1 37087 4 3 35869 5 0 1 37097 1 37094 1 37097 2 3 37091 1 37097 3 37094 7 0 1 37097 4 3 26078 11 0 1 37117 1 37115 1 37117 2 2 37116 1 37117 3 37115 2 0 1 37117 4 2 35600 6 0 1 37123 1 37120 1 37123 2 3 37118 1 37123 3 37120 4 0 1 37123 4 3 29214 3 0 1 37139 1 37137 1 37139 2 2 37135 1 37139 3 37137 2 0 1 37139 4 2 21300 7 0 1 37159 1 37156 1 37159 2 3 37157 1 37159 3 37156 1 0 1 37159 4 3 33865 3 0 1 37171 1 37168 1 37171 2 3 37170 1 37171 3 37168 1 0 1 37171 4 3 24119 2 0 1 37181 1 37179 1 37181 2 2 37166 1 37181 3 37179 4 0 1 37181 4 2 25911 3 0 1 37189 1 37187 1 37189 2 2 37188 1 37189 3 37187 6 0 1 37189 4 2 30260 7 0 1 37199 1 37192 1 37199 2 7 37187 1 37199 3 37192 1 0 1 37199 4 7 19932 18 0 1 37201 1 37194 1 37201 2 7 37194 1 37201 3 37194 12 0 1 37201 4 7 27563 0 0 1 37217 1 37214 1 37217 2 3 37211 1 37217 3 37214 1 0 1 37217 4 3 25495 1 0 1 37223 1 37218 1 37223 2 5 37222 1 37223 3 37218 7 0 1 37223 4 5 29669 4 0 1 37243 1 37241 1 37243 2 2 37242 1 37243 3 37241 4 0 1 37243 4 2 19542 7 0 1 37253 1 37251 1 37253 2 2 37249 1 37253 3 37251 3 0 1 37253 4 2 28291 7 0 1 37273 1 37268 1 37273 2 5 37272 1 37273 3 37268 5 0 1 37273 4 5 34429 6 0 1 37277 1 37275 1 37277 2 2 37269 1 37277 3 37275 5 0 1 37277 4 2 33278 5 0 1 37307 1 37305 1 37307 2 2 37301 1 37307 3 37305 4 0 1 37307 4 2 25085 4 0 1 37309 1 37302 1 37309 2 7 37307 1 37309 3 37302 1 0 1 37309 4 7 19242 4 0 1 37313 1 37310 1 37313 2 3 37301 1 37313 3 37310 1 0 1 37313 4 3 30263 0 0 1 37321 1 37298 1 37321 2 23 37320 1 37321 3 37298 5 0 1 37321 4 23 20097 18 0 1 37337 1 37334 1 37337 2 3 37331 1 37337 3 37334 6 0 1 37337 4 3 19067 1 0 1 37339 1 37336 1 37339 2 3 37332 1 37339 3 37336 1 0 1 37339 4 3 20666 5 0 1 37357 1 37351 1 37357 2 6 37356 1 37357 3 37351 1 0 1 37357 4 6 25712 6 0 1 37361 1 37358 1 37361 2 3 37355 1 37361 3 37358 5 0 1 37361 4 3 37349 0 0 1 37363 1 37360 1 37363 2 3 37362 1 37363 3 37360 1 0 1 37363 4 3 21155 2 0 1 37369 1 37362 1 37369 2 7 37366 1 37369 3 37362 1 0 1 37369 4 7 33527 14 0 1 37379 1 37377 1 37379 2 2 37378 1 37379 3 37377 3 0 1 37379 4 2 29464 4 0 1 37397 1 37395 1 37397 2 2 37396 1 37397 3 37395 2 0 1 37397 4 2 26940 4 0 1 37409 1 37406 1 37409 2 3 37404 1 37409 3 37406 3 0 1 37409 4 3 21337 2 0 1 37423 1 37417 1 37423 2 6 37420 1 37423 3 37417 4 0 1 37423 4 6 37408 18 0 1 37441 1 37424 1 37441 2 17 37430 1 37441 3 37424 2 0 1 37441 4 17 33605 0 0 1 37447 1 37444 1 37447 2 3 37445 1 37447 3 37444 5 0 1 37447 4 3 19779 6 0 1 37463 1 37458 1 37463 2 5 37461 1 37463 3 37458 1 0 1 37463 4 5 37459 3 0 1 37483 1 37481 1 37483 2 2 37482 1 37483 3 37481 5 0 1 37483 4 2 27131 2 0 1 37489 1 37470 1 37489 2 19 37474 1 37489 3 37470 4 0 1 37489 4 19 33346 52 0 1 37493 1 37491 1 37493 2 2 37486 1 37493 3 37491 4 0 1 37493 4 2 27205 2 0 1 37501 1 37499 1 37501 2 2 37497 1 37501 3 37499 2 0 1 37501 4 2 34278 10 0 1 37507 1 37490 1 37507 2 17 37505 1 37507 3 37490 2 0 1 37507 4 17 37499 3 0 1 37511 1 37500 1 37511 2 11 37508 1 37511 3 37500 4 0 1 37511 4 11 31881 6 0 1 37517 1 37515 1 37517 2 2 37513 1 37517 3 37515 3 0 1 37517 4 2 18975 7 0 1 37529 1 37526 1 37529 2 3 37519 1 37529 3 37526 3 0 1 37529 4 3 26883 13 0 1 37537 1 37524 1 37537 2 13 37528 1 37537 3 37524 1 0 1 37537 4 13 30190 2 0 1 37547 1 37545 1 37547 2 2 37546 1 37547 3 37545 3 0 1 37547 4 2 32251 2 0 1 37549 1 37547 1 37549 2 2 37545 1 37549 3 37547 2 0 1 37549 4 2 18991 12 0 1 37561 1 37550 1 37561 2 11 37560 1 37561 3 37550 3 0 1 37561 4 11 19631 8 0 1 37567 1 37564 1 37567 2 3 37566 1 37567 3 37564 3 0 1 37567 4 3 24636 5 0 1 37571 1 37569 1 37571 2 2 37560 1 37571 3 37569 2 0 1 37571 4 2 32823 3 0 1 37573 1 37568 1 37573 2 5 37572 1 37573 3 37568 10 0 1 37573 4 5 19136 3 0 1 37579 1 37577 1 37579 2 2 37578 1 37579 3 37577 6 0 1 37579 4 2 19454 2 0 1 37589 1 37587 1 37589 2 2 37588 1 37589 3 37587 9 0 1 37589 4 2 34854 3 0 1 37591 1 37585 1 37591 2 6 37589 1 37591 3 37585 2 0 1 37591 4 6 33174 10 0 1 37607 1 37602 1 37607 2 5 37605 1 37607 3 37602 1 0 1 37607 4 5 29548 14 0 1 37619 1 37617 1 37619 2 2 37615 1 37619 3 37617 2 0 1 37619 4 2 34006 7 0 1 37633 1 37628 1 37633 2 5 37632 1 37633 3 37628 1 0 1 37633 4 5 36406 12 0 1 37643 1 37641 1 37643 2 2 37639 1 37643 3 37641 3 0 1 37643 4 2 26690 8 0 1 37649 1 37646 1 37649 2 3 37648 1 37649 3 37646 4 0 1 37649 4 3 31939 7 0 1 37657 1 37652 1 37657 2 5 37656 1 37657 3 37652 2 0 1 37657 4 5 28634 6 0 1 37663 1 37660 1 37663 2 3 37662 1 37663 3 37660 6 0 1 37663 4 3 22013 2 0 1 37691 1 37685 1 37691 2 6 37689 1 37691 3 37685 2 0 1 37691 4 6 24698 5 0 1 37693 1 37691 1 37693 2 2 37692 1 37693 3 37691 2 0 1 37693 4 2 22114 3 0 1 37699 1 37696 1 37699 2 3 37687 1 37699 3 37696 3 0 1 37699 4 3 34574 0 0 1 37717 1 37712 1 37717 2 5 37716 1 37717 3 37712 1 0 1 37717 4 5 32095 3 0 1 37747 1 37744 1 37747 2 3 37746 1 37747 3 37744 1 0 1 37747 4 3 25645 5 0 1 37781 1 37779 1 37781 2 2 37776 1 37781 3 37779 2 0 1 37781 4 2 25477 8 0 1 37783 1 37780 1 37783 2 3 37781 1 37783 3 37780 4 0 1 37783 4 3 37775 10 0 1 37799 1 37788 1 37799 2 11 37798 1 37799 3 37788 5 0 1 37799 4 11 19068 2 0 1 37811 1 37805 1 37811 2 6 37810 1 37811 3 37805 2 0 1 37811 4 6 35535 4 0 1 37813 1 37811 1 37813 2 2 37809 1 37813 3 37811 5 0 1 37813 4 2 19352 10 0 1 37831 1 37828 1 37831 2 3 37830 1 37831 3 37828 3 0 1 37831 4 3 31814 3 0 1 37847 1 37842 1 37847 2 5 37846 1 37847 3 37842 1 0 1 37847 4 5 23220 3 0 1 37853 1 37851 1 37853 2 2 37848 1 37853 3 37851 4 0 1 37853 4 2 22552 17 0 1 37861 1 37859 1 37861 2 2 37860 1 37861 3 37859 6 0 1 37861 4 2 22027 3 0 1 37871 1 37864 1 37871 2 7 37864 1 37871 3 37864 5 0 1 37871 4 7 33945 8 0 1 37879 1 37872 1 37879 2 7 37876 1 37879 3 37872 3 0 1 37879 4 7 28903 0 0 1 37889 1 37886 1 37889 2 3 37881 1 37889 3 37886 3 0 1 37889 4 3 25113 1 0 1 37897 1 37892 1 37897 2 5 37894 1 37897 3 37892 1 0 1 37897 4 5 37195 16 0 1 37907 1 37905 1 37907 2 2 37903 1 37907 3 37905 8 0 1 37907 4 2 33823 7 0 1 37951 1 37948 1 37951 2 3 37949 1 37951 3 37948 3 0 1 37951 4 3 29265 3 0 1 37957 1 37955 1 37957 2 2 37956 1 37957 3 37955 5 0 1 37957 4 2 30796 3 0 1 37963 1 37961 1 37963 2 2 37959 1 37963 3 37961 6 0 1 37963 4 2 21601 8 0 1 37967 1 37962 1 37967 2 5 37964 1 37967 3 37962 1 0 1 37967 4 5 35382 6 0 1 37987 1 37982 1 37987 2 5 37985 1 37987 3 37982 1 0 1 37987 4 5 34893 9 0 1 37991 1 37984 1 37991 2 7 37990 1 37991 3 37984 4 0 1 37991 4 7 28727 2 0 1 37993 1 37983 1 37993 2 10 37992 1 37993 3 37983 5 0 1 37993 4 10 35024 16 0 1 37997 1 37995 1 37997 2 2 37993 1 37997 3 37995 3 0 1 37997 4 2 29297 7 0 1 38011 1 38009 1 38011 2 2 38007 1 38011 3 38009 2 0 1 38011 4 2 19512 8 0 1 38039 1 38032 1 38039 2 7 38037 1 38039 3 38032 2 0 1 38039 4 7 33167 4 0 1 38047 1 38044 1 38047 2 3 38045 1 38047 3 38044 1 0 1 38047 4 3 38039 10 0 1 38053 1 38048 1 38053 2 5 38052 1 38053 3 38048 2 0 1 38053 4 5 33474 3 0 1 38069 1 38067 1 38069 2 2 38064 1 38069 3 38067 4 0 1 38069 4 2 21442 2 0 1 38083 1 38080 1 38083 2 3 38078 1 38083 3 38080 4 0 1 38083 4 3 19791 3 0 1 38113 1 38106 1 38113 2 7 38110 1 38113 3 38106 2 0 1 38113 4 7 30887 17 0 1 38119 1 38116 1 38119 2 3 38117 1 38119 3 38116 1 0 1 38119 4 3 38115 4 0 1 38149 1 38143 1 38149 2 6 38148 1 38149 3 38143 4 0 1 38149 4 6 28909 7 0 1 38153 1 38150 1 38153 2 3 38148 1 38153 3 38150 3 0 1 38153 4 3 25251 0 0 1 38167 1 38164 1 38167 2 3 38166 1 38167 3 38164 3 0 1 38167 4 3 32206 5 0 1 38177 1 38174 1 38177 2 3 38176 1 38177 3 38174 5 0 1 38177 4 3 35652 7 0 1 38183 1 38178 1 38183 2 5 38180 1 38183 3 38178 3 0 1 38183 4 5 31711 6 0 1 38189 1 38187 1 38189 2 2 38185 1 38189 3 38187 3 0 1 38189 4 2 27557 6 0 1 38197 1 38195 1 38197 2 2 38196 1 38197 3 38195 8 0 1 38197 4 2 26216 6 0 1 38201 1 38198 1 38201 2 3 38196 1 38201 3 38198 3 0 1 38201 4 3 35721 2 0 1 38219 1 38217 1 38219 2 2 38215 1 38219 3 38217 3 0 1 38219 4 2 26073 7 0 1 38231 1 38218 1 38231 2 13 38230 1 38231 3 38218 3 0 1 38231 4 13 32649 10 0 1 38237 1 38235 1 38237 2 2 38233 1 38237 3 38235 2 0 1 38237 4 2 25637 7 0 1 38239 1 38226 1 38239 2 13 38238 1 38239 3 38226 3 0 1 38239 4 13 19289 2 0 1 38261 1 38259 1 38261 2 2 38260 1 38261 3 38259 3 0 1 38261 4 2 36648 4 0 1 38273 1 38270 1 38273 2 3 38267 1 38273 3 38270 12 0 1 38273 4 3 21659 1 0 1 38281 1 38267 1 38281 2 14 38278 1 38281 3 38267 1 0 1 38281 4 14 24768 20 0 1 38287 1 38280 1 38287 2 7 38284 1 38287 3 38280 2 0 1 38287 4 7 19895 4 0 1 38299 1 38297 1 38299 2 2 38293 1 38299 3 38297 2 0 1 38299 4 2 36650 7 0 1 38303 1 38298 1 38303 2 5 38301 1 38303 3 38298 10 0 1 38303 4 5 26437 10 0 1 38317 1 38315 1 38317 2 2 38316 1 38317 3 38315 2 0 1 38317 4 2 31189 7 0 1 38321 1 38318 1 38321 2 3 38320 1 38321 3 38318 1 0 1 38321 4 3 36923 4 0 1 38327 1 38322 1 38327 2 5 38325 1 38327 3 38322 1 0 1 38327 4 5 30440 5 0 1 38329 1 38316 1 38329 2 13 38328 1 38329 3 38316 1 0 1 38329 4 13 25055 14 0 1 38333 1 38331 1 38333 2 2 38325 1 38333 3 38331 4 0 1 38333 4 2 30289 11 0 1 38351 1 38340 1 38351 2 11 38349 1 38351 3 38340 1 0 1 38351 4 11 37128 3 0 1 38371 1 38361 1 38371 2 10 38370 1 38371 3 38361 3 0 1 38371 4 10 24488 5 0 1 38377 1 38372 1 38377 2 5 38372 1 38377 3 38372 2 0 1 38377 4 5 38100 10 0 1 38393 1 38390 1 38393 2 3 38387 1 38393 3 38390 6 0 1 38393 4 3 20238 1 0 1 38431 1 38425 1 38431 2 6 38430 1 38431 3 38425 2 0 1 38431 4 6 36645 2 0 1 38447 1 38442 1 38447 2 5 38446 1 38447 3 38442 5 0 1 38447 4 5 23340 4 0 1 38449 1 38436 1 38449 2 13 38448 1 38449 3 38436 3 0 1 38449 4 13 29532 8 0 1 38453 1 38451 1 38453 2 2 38449 1 38453 3 38451 4 0 1 38453 4 2 30005 12 0 1 38459 1 38457 1 38459 2 2 38455 1 38459 3 38457 2 0 1 38459 4 2 37440 8 0 1 38461 1 38448 1 38461 2 13 38460 1 38461 3 38448 1 0 1 38461 4 13 33488 7 0 1 38501 1 38499 1 38501 2 2 38493 1 38501 3 38499 2 0 1 38501 4 2 20275 0 0 1 38543 1 38538 1 38543 2 5 38541 1 38543 3 38538 6 0 1 38543 4 5 38539 3 0 1 38557 1 38555 1 38557 2 2 38553 1 38557 3 38555 4 0 1 38557 4 2 22303 10 0 1 38561 1 38558 1 38561 2 3 38555 1 38561 3 38558 7 0 1 38561 4 3 38549 0 0 1 38567 1 38562 1 38567 2 5 38562 1 38567 3 38562 6 0 1 38567 4 5 34251 6 0 1 38569 1 38555 1 38569 2 14 38567 1 38569 3 38555 1 0 1 38569 4 14 38543 15 0 1 38593 1 38588 1 38593 2 5 38588 1 38593 3 38588 3 0 1 38593 4 5 22172 15 0 1 38603 1 38601 1 38603 2 2 38602 1 38603 3 38601 2 0 1 38603 4 2 23298 4 0 1 38609 1 38606 1 38609 2 3 38608 1 38609 3 38606 6 0 1 38609 4 3 38331 7 0 1 38611 1 38608 1 38611 2 3 38604 1 38611 3 38608 3 0 1 38611 4 3 29249 5 0 1 38629 1 38627 1 38629 2 2 38628 1 38629 3 38627 4 0 1 38629 4 2 32309 3 0 1 38639 1 38610 1 38639 2 29 38638 1 38639 3 38610 5 0 1 38639 4 29 29599 2 0 1 38651 1 38649 1 38651 2 2 38645 1 38651 3 38649 9 0 1 38651 4 2 36685 4 0 1 38653 1 38651 1 38653 2 2 38652 1 38653 3 38651 2 0 1 38653 4 2 36591 3 0 1 38669 1 38667 1 38669 2 2 38664 1 38669 3 38667 2 0 1 38669 4 2 33671 15 0 1 38671 1 38665 1 38671 2 6 38669 1 38671 3 38665 2 0 1 38671 4 6 21972 3 0 1 38677 1 38672 1 38677 2 5 38676 1 38677 3 38672 3 0 1 38677 4 5 37582 3 0 1 38693 1 38691 1 38693 2 2 38683 1 38693 3 38691 7 0 1 38693 4 2 32166 2 0 1 38699 1 38697 1 38699 2 2 38698 1 38699 3 38697 3 0 1 38699 4 2 33472 6 0 1 38707 1 38705 1 38707 2 2 38703 1 38707 3 38705 6 0 1 38707 4 2 37302 8 0 1 38711 1 38704 1 38711 2 7 38708 1 38711 3 38704 1 0 1 38711 4 7 34674 5 0 1 38713 1 38708 1 38713 2 5 38712 1 38713 3 38708 5 0 1 38713 4 5 23934 6 0 1 38723 1 38721 1 38723 2 2 38719 1 38723 3 38721 3 0 1 38723 4 2 37759 11 0 1 38729 1 38726 1 38729 2 3 38724 1 38729 3 38726 3 0 1 38729 4 3 29906 2 0 1 38737 1 38732 1 38737 2 5 38736 1 38737 3 38732 3 0 1 38737 4 5 23632 6 0 1 38747 1 38745 1 38747 2 2 38736 1 38747 3 38745 10 0 1 38747 4 2 20734 4 0 1 38749 1 38747 1 38749 2 2 38745 1 38749 3 38747 2 0 1 38749 4 2 24273 6 0 1 38767 1 38762 1 38767 2 5 38765 1 38767 3 38762 1 0 1 38767 4 5 24075 15 0 1 38783 1 38778 1 38783 2 5 38780 1 38783 3 38778 1 0 1 38783 4 5 23214 4 0 1 38791 1 38785 1 38791 2 6 38789 1 38791 3 38785 10 0 1 38791 4 6 30215 4 0 1 38803 1 38798 1 38803 2 5 38801 1 38803 3 38798 1 0 1 38803 4 5 38795 6 0 1 38821 1 38819 1 38821 2 2 38817 1 38821 3 38819 7 0 1 38821 4 2 30471 6 0 1 38833 1 38828 1 38833 2 5 38828 1 38833 3 38828 2 0 1 38833 4 5 37701 18 0 1 38839 1 38833 1 38839 2 6 38838 1 38839 3 38833 1 0 1 38839 4 6 24569 2 0 1 38851 1 38848 1 38851 2 3 38850 1 38851 3 38848 1 0 1 38851 4 3 23661 2 0 1 38861 1 38847 1 38861 2 14 38838 1 38861 3 38847 2 0 1 38861 4 14 23356 0 0 1 38867 1 38865 1 38867 2 2 38866 1 38867 3 38865 2 0 1 38867 4 2 27407 2 0 1 38873 1 38870 1 38873 2 3 38872 1 38873 3 38870 10 0 1 38873 4 3 33001 4 0 1 38891 1 38889 1 38891 2 2 38890 1 38891 3 38889 4 0 1 38891 4 2 26445 10 0 1 38903 1 38898 1 38903 2 5 38902 1 38903 3 38898 1 0 1 38903 4 5 26815 5 0 1 38917 1 38912 1 38917 2 5 38914 1 38917 3 38912 8 0 1 38917 4 5 24190 11 0 1 38921 1 38915 1 38921 2 6 38920 1 38921 3 38915 2 0 1 38921 4 6 25186 7 0 1 38923 1 38921 1 38923 2 2 38922 1 38923 3 38921 6 0 1 38923 4 2 38916 8 0 1 38933 1 38931 1 38933 2 2 38932 1 38933 3 38931 3 0 1 38933 4 2 33245 4 0 1 38953 1 38948 1 38953 2 5 38952 1 38953 3 38948 1 0 1 38953 4 5 35439 6 0 1 38959 1 38956 1 38959 2 3 38954 1 38959 3 38956 6 0 1 38959 4 3 30864 6 0 1 38971 1 38969 1 38971 2 2 38967 1 38971 3 38969 6 0 1 38971 4 2 21563 8 0 1 38977 1 38972 1 38977 2 5 38976 1 38977 3 38972 2 0 1 38977 4 5 26193 6 0 1 38993 1 38990 1 38993 2 3 38987 1 38993 3 38990 3 0 1 38993 4 3 35395 9 0 1 39019 1 39017 1 39019 2 2 39013 1 39019 3 39017 2 0 1 39019 4 2 33763 3 0 1 39023 1 39018 1 39023 2 5 39021 1 39023 3 39018 1 0 1 39023 4 5 24508 5 0 1 39041 1 39038 1 39041 2 3 39040 1 39041 3 39038 1 0 1 39041 4 3 26546 7 0 1 39043 1 39041 1 39043 2 2 39039 1 39043 3 39041 4 0 1 39043 4 2 22536 10 0 1 39047 1 39042 1 39047 2 5 39046 1 39047 3 39042 5 0 1 39047 4 5 33621 3 0 1 39079 1 39076 1 39079 2 3 39077 1 39079 3 39076 3 0 1 39079 4 3 28472 3 0 1 39089 1 39086 1 39089 2 3 39083 1 39089 3 39086 4 0 1 39089 4 3 39077 0 0 1 39097 1 39092 1 39097 2 5 39096 1 39097 3 39092 1 0 1 39097 4 5 30051 6 0 1 39103 1 39098 1 39103 2 5 39101 1 39103 3 39098 2 0 1 39103 4 5 36150 17 0 1 39107 1 39105 1 39107 2 2 39106 1 39107 3 39105 3 0 1 39107 4 2 20557 2 0 1 39113 1 39110 1 39113 2 3 39112 1 39113 3 39110 1 0 1 39113 4 3 30930 4 0 1 39119 1 39108 1 39119 2 11 39118 1 39119 3 39108 1 0 1 39119 4 11 25086 2 0 1 39133 1 39128 1 39133 2 5 39132 1 39133 3 39128 1 0 1 39133 4 5 24278 3 0 1 39139 1 39132 1 39139 2 7 39137 1 39139 3 39132 10 0 1 39139 4 7 34512 6 0 1 39157 1 39151 1 39157 2 6 39156 1 39157 3 39151 1 0 1 39157 4 6 25232 8 0 1 39161 1 39158 1 39161 2 3 39156 1 39161 3 39158 1 0 1 39161 4 3 35010 8 0 1 39163 1 39161 1 39163 2 2 39162 1 39163 3 39161 2 0 1 39163 4 2 39156 8 0 1 39181 1 39175 1 39181 2 6 39177 1 39181 3 39175 2 0 1 39181 4 6 39177 6 0 1 39191 1 39180 1 39191 2 11 39190 1 39191 3 39180 1 0 1 39191 4 11 35745 2 0 1 39199 1 39182 1 39199 2 17 39195 1 39199 3 39182 7 0 1 39199 4 17 36081 15 0 1 39209 1 39206 1 39209 2 3 39203 1 39209 3 39206 4 0 1 39209 4 3 39197 0 0 1 39217 1 39210 1 39217 2 7 39210 1 39217 3 39210 4 0 1 39217 4 7 26512 14 0 1 39227 1 39225 1 39227 2 2 39226 1 39227 3 39225 2 0 1 39227 4 2 39220 8 0 1 39229 1 39227 1 39229 2 2 39225 1 39229 3 39227 5 0 1 39229 4 2 23379 6 0 1 39233 1 39230 1 39233 2 3 39232 1 39233 3 39230 1 0 1 39233 4 3 29629 4 0 1 39239 1 39232 1 39239 2 7 39238 1 39239 3 39232 1 0 1 39239 4 7 36389 2 0 1 39241 1 39234 1 39241 2 7 39234 1 39241 3 39234 2 0 1 39241 4 7 31295 0 0 1 39251 1 39249 1 39251 2 2 39247 1 39251 3 39249 3 0 1 39251 4 2 22058 8 0 1 39293 1 39291 1 39293 2 2 39289 1 39293 3 39291 3 0 1 39293 4 2 33034 9 0 1 39301 1 39294 1 39301 2 7 39299 1 39301 3 39294 1 0 1 39301 4 7 38586 15 0 1 39313 1 39303 1 39313 2 10 39308 1 39313 3 39303 3 0 1 39313 4 10 32642 0 0 1 39317 1 39315 1 39317 2 2 39316 1 39317 3 39315 2 0 1 39317 4 2 36258 6 0 1 39323 1 39321 1 39323 2 2 39319 1 39323 3 39321 5 0 1 39323 4 2 22160 7 0 1 39341 1 39339 1 39341 2 2 39337 1 39341 3 39339 2 0 1 39341 4 2 31163 6 0 1 39343 1 39340 1 39343 2 3 39342 1 39343 3 39340 13 0 1 39343 4 3 23892 8 0 1 39359 1 39348 1 39359 2 11 39356 1 39359 3 39348 2 0 1 39359 4 11 27324 6 0 1 39367 1 39364 1 39367 2 3 39365 1 39367 3 39364 9 0 1 39367 4 3 30496 3 0 1 39371 1 39369 1 39371 2 2 39370 1 39371 3 39369 4 0 1 39371 4 2 35643 4 0 1 39373 1 39351 1 39373 2 22 39371 1 39373 3 39351 3 0 1 39373 4 22 38401 0 0 1 39383 1 39378 1 39383 2 5 39382 1 39383 3 39378 1 0 1 39383 4 5 38278 9 0 1 39397 1 39395 1 39397 2 2 39393 1 39397 3 39395 5 0 1 39397 4 2 36507 12 0 1 39409 1 39402 1 39409 2 7 39406 1 39409 3 39402 1 0 1 39409 4 7 32961 14 0 1 39419 1 39417 1 39419 2 2 39415 1 39419 3 39417 3 0 1 39419 4 2 21067 8 0 1 39439 1 39436 1 39439 2 3 39429 1 39439 3 39436 3 0 1 39439 4 3 23903 3 0 1 39443 1 39441 1 39443 2 2 39442 1 39443 3 39441 2 0 1 39443 4 2 30777 13 0 1 39451 1 39449 1 39451 2 2 39450 1 39451 3 39449 6 0 1 39451 4 2 37321 6 0 1 39461 1 39459 1 39461 2 2 39457 1 39461 3 39459 2 0 1 39461 4 2 20975 12 0 1 39499 1 39497 1 39499 2 2 39498 1 39499 3 39497 6 0 1 39499 4 2 23602 2 0 1 39503 1 39498 1 39503 2 5 39502 1 39503 3 39498 1 0 1 39503 4 5 30046 4 0 1 39509 1 39506 1 39509 2 3 39507 1 39509 3 39506 1 0 1 39509 4 3 39501 10 0 1 39511 1 39508 1 39511 2 3 39510 1 39511 3 39508 5 0 1 39511 4 3 26516 2 0 1 39521 1 39518 1 39521 2 3 39515 1 39521 3 39518 1 0 1 39521 4 3 39509 0 0 1 39541 1 39539 1 39541 2 2 39540 1 39541 3 39539 4 0 1 39541 4 2 20129 3 0 1 39551 1 39544 1 39551 2 7 39548 1 39551 3 39544 5 0 1 39551 4 7 26926 8 0 1 39563 1 39561 1 39563 2 2 39562 1 39563 3 39561 3 0 1 39563 4 2 25866 10 0 1 39569 1 39566 1 39569 2 3 39559 1 39569 3 39566 1 0 1 39569 4 3 21015 3 0 1 39581 1 39579 1 39581 2 2 39580 1 39581 3 39579 3 0 1 39581 4 2 39574 8 0 1 39607 1 39604 1 39607 2 3 39606 1 39607 3 39604 3 0 1 39607 4 3 21811 5 0 1 39619 1 39617 1 39619 2 2 39618 1 39619 3 39617 6 0 1 39619 4 2 19982 7 0 1 39623 1 39618 1 39623 2 5 39622 1 39623 3 39618 5 0 1 39623 4 5 21113 2 0 1 39631 1 39628 1 39631 2 3 39629 1 39631 3 39628 6 0 1 39631 4 3 29962 6 0 1 39659 1 39657 1 39659 2 2 39655 1 39659 3 39657 3 0 1 39659 4 2 30533 7 0 1 39667 1 39664 1 39667 2 3 39658 1 39667 3 39664 5 0 1 39667 4 3 34504 4 0 1 39671 1 39664 1 39671 2 7 39670 1 39671 3 39664 5 0 1 39671 4 7 20353 2 0 1 39679 1 39673 1 39679 2 6 39677 1 39679 3 39673 2 0 1 39679 4 6 29071 3 0 1 39703 1 39698 1 39703 2 5 39702 1 39703 3 39698 1 0 1 39703 4 5 20563 2 0 1 39709 1 39703 1 39709 2 6 39708 1 39709 3 39703 2 0 1 39709 4 6 38547 7 0 1 39719 1 39712 1 39719 2 7 39717 1 39719 3 39712 1 0 1 39719 4 7 38397 4 0 1 39727 1 39724 1 39727 2 3 39726 1 39727 3 39724 3 0 1 39727 4 3 35383 2 0 1 39733 1 39731 1 39733 2 2 39729 1 39733 3 39731 6 0 1 39733 4 2 29299 12 0 1 39749 1 39747 1 39749 2 2 39748 1 39749 3 39747 3 0 1 39749 4 2 29632 3 0 1 39761 1 39758 1 39761 2 3 39756 1 39761 3 39758 8 0 1 39761 4 3 20842 2 0 1 39769 1 39756 1 39769 2 13 39768 1 39769 3 39756 3 0 1 39769 4 13 31398 14 0 1 39779 1 39777 1 39779 2 2 39775 1 39779 3 39777 3 0 1 39779 4 2 26299 13 0 1 39791 1 39780 1 39791 2 11 39789 1 39791 3 39780 6 0 1 39791 4 11 20451 7 0 1 39799 1 39796 1 39799 2 3 39797 1 39799 3 39796 1 0 1 39799 4 3 20740 3 0 1 39821 1 39819 1 39821 2 2 39815 1 39821 3 39819 4 0 1 39821 4 2 23010 3 0 1 39827 1 39825 1 39827 2 2 39823 1 39827 3 39825 3 0 1 39827 4 2 27913 8 0 1 39829 1 39823 1 39829 2 6 39825 1 39829 3 39823 1 0 1 39829 4 6 35544 11 0 1 39839 1 39832 1 39839 2 7 39838 1 39839 3 39832 1 0 1 39839 4 7 34688 2 0 1 39841 1 39810 1 39841 2 31 39840 1 39841 3 39810 8 0 1 39841 4 31 37627 12 0 1 39847 1 39842 1 39847 2 5 39845 1 39847 3 39842 1 0 1 39847 4 5 36920 16 0 1 39857 1 39854 1 39857 2 3 39850 1 39857 3 39854 5 0 1 39857 4 3 32268 19 0 1 39863 1 39858 1 39863 2 5 39861 1 39863 3 39858 2 0 1 39863 4 5 32102 10 0 1 39869 1 39867 1 39869 2 2 39861 1 39869 3 39867 2 0 1 39869 4 2 35127 0 0 1 39877 1 39875 1 39877 2 2 39876 1 39877 3 39875 2 0 1 39877 4 2 27572 9 0 1 39883 1 39880 1 39883 2 3 39882 1 39883 3 39880 3 0 1 39883 4 3 27660 2 0 1 39887 1 39880 1 39887 2 7 39885 1 39887 3 39880 3 0 1 39887 4 7 28653 14 0 1 39901 1 39899 1 39901 2 2 39897 1 39901 3 39899 4 0 1 39901 4 2 32944 12 0 1 39929 1 39926 1 39929 2 3 39921 1 39929 3 39926 3 0 1 39929 4 3 23450 2 0 1 39937 1 39932 1 39937 2 5 39934 1 39937 3 39932 1 0 1 39937 4 5 20329 18 0 1 39953 1 39950 1 39953 2 3 39944 1 39953 3 39950 4 0 1 39953 4 3 21336 3 0 1 39971 1 39969 1 39971 2 2 39967 1 39971 3 39969 2 0 1 39971 4 2 38660 8 0 1 39979 1 39976 1 39979 2 3 39970 1 39979 3 39976 3 0 1 39979 4 3 28841 6 0 1 39983 1 39978 1 39983 2 5 39981 1 39983 3 39978 6 0 1 39983 4 5 39971 11 0 1 39989 1 39987 1 39989 2 2 39985 1 39989 3 39987 3 0 1 39989 4 2 36619 1 0 1 40009 1 39998 1 40009 2 11 40008 1 40009 3 39998 3 0 1 40009 4 11 30730 12 0 1 40013 1 40011 1 40013 2 2 40009 1 40013 3 40011 3 0 1 40013 4 2 29898 6 0 1 40031 1 40012 1 40031 2 19 40030 1 40031 3 40012 5 0 1 40031 4 19 40001 13 0 1 40037 1 40035 1 40037 2 2 40029 1 40037 3 40035 12 0 1 40037 4 2 35214 11 0 1 40039 1 40033 1 40039 2 6 40038 1 40039 3 40033 1 0 1 40039 4 6 38943 3 0 1 40063 1 40060 1 40063 2 3 40061 1 40063 3 40060 1 0 1 40063 4 3 40059 4 0 1 40087 1 40084 1 40087 2 3 40085 1 40087 3 40084 4 0 1 40087 4 3 21667 6 0 1 40093 1 40091 1 40093 2 2 40089 1 40093 3 40091 5 0 1 40093 4 2 30961 6 0 1 40099 1 40096 1 40099 2 3 40094 1 40099 3 40096 6 0 1 40099 4 3 23464 3 0 1 40111 1 40108 1 40111 2 3 40109 1 40111 3 40108 1 0 1 40111 4 3 29259 3 0 1 40123 1 40121 1 40123 2 2 40122 1 40123 3 40121 2 0 1 40123 4 2 34321 2 0 1 40127 1 40122 1 40127 2 5 40124 1 40127 3 40122 7 0 1 40127 4 5 25313 6 0 1 40129 1 40122 1 40129 2 7 40122 1 40129 3 40122 1 0 1 40129 4 7 37548 0 0 1 40151 1 40140 1 40151 2 11 40149 1 40151 3 40140 4 0 1 40151 4 11 24171 3 0 1 40153 1 40148 1 40153 2 5 40148 1 40153 3 40148 2 0 1 40153 4 5 34765 20 0 1 40163 1 40161 1 40163 2 2 40157 1 40163 3 40161 7 0 1 40163 4 2 38283 4 0 1 40169 1 40166 1 40169 2 3 40159 1 40169 3 40166 4 0 1 40169 4 3 29838 4 0 1 40177 1 40167 1 40177 2 10 40176 1 40177 3 40167 5 0 1 40177 4 10 23176 18 0 1 40189 1 40187 1 40189 2 2 40185 1 40189 3 40187 6 0 1 40189 4 2 33230 12 0 1 40193 1 40190 1 40193 2 3 40192 1 40193 3 40190 5 0 1 40193 4 3 25310 7 0 1 40213 1 40207 1 40213 2 6 40211 1 40213 3 40207 3 0 1 40213 4 6 39490 0 0 1 40231 1 40228 1 40231 2 3 40229 1 40231 3 40228 3 0 1 40231 4 3 38577 3 0 1 40237 1 40231 1 40237 2 6 40236 1 40237 3 40231 3 0 1 40237 4 6 21847 6 0 1 40241 1 40238 1 40241 2 3 40236 1 40241 3 40238 3 0 1 40241 4 3 37334 2 0 1 40253 1 40251 1 40253 2 2 40249 1 40253 3 40251 2 0 1 40253 4 2 33918 6 0 1 40277 1 40275 1 40277 2 2 40276 1 40277 3 40275 3 0 1 40277 4 2 36883 3 0 1 40283 1 40281 1 40283 2 2 40282 1 40283 3 40281 3 0 1 40283 4 2 40276 8 0 1 40289 1 40286 1 40289 2 3 40283 1 40289 3 40286 3 0 1 40289 4 3 40277 0 0 1 40343 1 40338 1 40343 2 5 40341 1 40343 3 40338 1 0 1 40343 4 5 40331 11 0 1 40351 1 40348 1 40351 2 3 40349 1 40351 3 40348 4 0 1 40351 4 3 24291 3 0 1 40357 1 40352 1 40357 2 5 40352 1 40357 3 40352 2 0 1 40357 4 5 28961 7 0 1 40361 1 40358 1 40361 2 3 40345 1 40361 3 40358 1 0 1 40361 4 3 27273 1 0 1 40387 1 40385 1 40387 2 2 40383 1 40387 3 40385 6 0 1 40387 4 2 25780 13 0 1 40423 1 40420 1 40423 2 3 40421 1 40423 3 40420 1 0 1 40423 4 3 32670 3 0 1 40427 1 40425 1 40427 2 2 40423 1 40427 3 40425 4 0 1 40427 4 2 25846 8 0 1 40429 1 40415 1 40429 2 14 40425 1 40429 3 40415 5 0 1 40429 4 14 24419 10 0 1 40433 1 40428 1 40433 2 5 40430 1 40433 3 40428 1 0 1 40433 4 5 27145 6 0 1 40459 1 40457 1 40459 2 2 40458 1 40459 3 40457 5 0 1 40459 4 2 27701 2 0 1 40471 1 40468 1 40471 2 3 40470 1 40471 3 40468 6 0 1 40471 4 3 21751 2 0 1 40483 1 40481 1 40483 2 2 40479 1 40483 3 40481 4 0 1 40483 4 2 25023 8 0 1 40487 1 40482 1 40487 2 5 40482 1 40487 3 40482 1 0 1 40487 4 5 32754 7 0 1 40493 1 40491 1 40493 2 2 40492 1 40493 3 40491 3 0 1 40493 4 2 37633 3 0 1 40499 1 40497 1 40499 2 2 40494 1 40499 3 40497 2 0 1 40499 4 2 22620 3 0 1 40507 1 40505 1 40507 2 2 40506 1 40507 3 40505 5 0 1 40507 4 2 36181 7 0 1 40519 1 40513 1 40519 2 6 40509 1 40519 3 40513 3 0 1 40519 4 6 33044 11 0 1 40529 1 40526 1 40529 2 3 40523 1 40529 3 40526 3 0 1 40529 4 3 40517 0 0 1 40531 1 40529 1 40531 2 2 40527 1 40531 3 40529 2 0 1 40531 4 2 26103 8 0 1 40543 1 40540 1 40543 2 3 40537 1 40543 3 40540 1 0 1 40543 4 3 20538 3 0 1 40559 1 40552 1 40559 2 7 40556 1 40559 3 40552 3 0 1 40559 4 7 28279 5 0 1 40577 1 40574 1 40577 2 3 40571 1 40577 3 40574 4 0 1 40577 4 3 23305 11 0 1 40583 1 40578 1 40583 2 5 40581 1 40583 3 40578 3 0 1 40583 4 5 36766 14 0 1 40591 1 40578 1 40591 2 13 40590 1 40591 3 40578 6 0 1 40591 4 13 23143 5 0 1 40597 1 40595 1 40597 2 2 40593 1 40597 3 40595 5 0 1 40597 4 2 27420 9 0 1 40609 1 40587 1 40609 2 22 40606 1 40609 3 40587 5 0 1 40609 4 22 32138 25 0 1 40627 1 40625 1 40627 2 2 40623 1 40627 3 40625 4 0 1 40627 4 2 30140 19 0 1 40637 1 40635 1 40637 2 2 40626 1 40637 3 40635 7 0 1 40637 4 2 20898 6 0 1 40639 1 40632 1 40639 2 7 40630 1 40639 3 40632 1 0 1 40639 4 7 24068 3 0 1 40693 1 40691 1 40693 2 2 40689 1 40693 3 40691 7 0 1 40693 4 2 40242 12 0 1 40697 1 40694 1 40697 2 3 40692 1 40697 3 40694 1 0 1 40697 4 3 32615 2 0 1 40699 1 40697 1 40699 2 2 40693 1 40699 3 40697 2 0 1 40699 4 2 22810 3 0 1 40709 1 40707 1 40709 2 2 40705 1 40709 3 40707 2 0 1 40709 4 2 26989 6 0 1 40739 1 40737 1 40739 2 2 40734 1 40739 3 40737 11 0 1 40739 4 2 26215 3 0 1 40751 1 40737 1 40751 2 14 40750 1 40751 3 40737 5 0 1 40751 4 14 26491 3 0 1 40759 1 40756 1 40759 2 3 40757 1 40759 3 40756 1 0 1 40759 4 3 40755 4 0 1 40763 1 40761 1 40763 2 2 40758 1 40763 3 40761 9 0 1 40763 4 2 25783 0 0 1 40771 1 40761 1 40771 2 10 40769 1 40771 3 40761 2 0 1 40771 4 10 34197 8 0 1 40787 1 40785 1 40787 2 2 40783 1 40787 3 40785 2 0 1 40787 4 2 21438 13 0 1 40801 1 40788 1 40801 2 13 40798 1 40801 3 40788 1 0 1 40801 4 13 20627 10 0 1 40813 1 40811 1 40813 2 2 40812 1 40813 3 40811 2 0 1 40813 4 2 24806 6 0 1 40819 1 40816 1 40819 2 3 40810 1 40819 3 40816 3 0 1 40819 4 3 24908 2 0 1 40823 1 40818 1 40823 2 5 40821 1 40823 3 40818 5 0 1 40823 4 5 40819 3 0 1 40829 1 40827 1 40829 2 2 40828 1 40829 3 40827 7 0 1 40829 4 2 23012 3 0 1 40841 1 40838 1 40841 2 3 40836 1 40841 3 40838 7 0 1 40841 4 3 29237 2 0 1 40847 1 40842 1 40847 2 5 40842 1 40847 3 40842 3 0 1 40847 4 5 29258 8 0 1 40849 1 40838 1 40849 2 11 40848 1 40849 3 40838 2 0 1 40849 4 11 31508 20 0 1 40853 1 40851 1 40853 2 2 40849 1 40853 3 40851 3 0 1 40853 4 2 25624 9 0 1 40867 1 40865 1 40867 2 2 40863 1 40867 3 40865 6 0 1 40867 4 2 24590 8 0 1 40879 1 40873 1 40879 2 6 40877 1 40879 3 40873 3 0 1 40879 4 6 23940 3 0 1 40883 1 40881 1 40883 2 2 40882 1 40883 3 40881 2 0 1 40883 4 2 24907 2 0 1 40897 1 40892 1 40897 2 5 40894 1 40897 3 40892 1 0 1 40897 4 5 37119 24 0 1 40903 1 40900 1 40903 2 3 40901 1 40903 3 40900 1 0 1 40903 4 3 38313 3 0 1 40927 1 40924 1 40927 2 3 40926 1 40927 3 40924 1 0 1 40927 4 3 40256 5 0 1 40933 1 40931 1 40933 2 2 40929 1 40933 3 40931 10 0 1 40933 4 2 39591 15 0 1 40939 1 40937 1 40939 2 2 40938 1 40939 3 40937 4 0 1 40939 4 2 33285 2 0 1 40949 1 40947 1 40949 2 2 40937 1 40949 3 40947 3 0 1 40949 4 2 27494 1 0 1 40961 1 40958 1 40961 2 3 40960 1 40961 3 40958 3 0 1 40961 4 3 36045 7 0 1 40973 1 40971 1 40973 2 2 40969 1 40973 3 40971 3 0 1 40973 4 2 25152 6 0 1 40993 1 40988 1 40993 2 5 40992 1 40993 3 40988 10 0 1 40993 4 5 36660 6 0 1 41011 1 41009 1 41011 2 2 41010 1 41011 3 41009 6 0 1 41011 4 2 30297 2 0 1 41017 1 41012 1 41017 2 5 41016 1 41017 3 41012 11 0 1 41017 4 5 38780 6 0 1 41023 1 41018 1 41023 2 5 41022 1 41023 3 41018 7 0 1 41023 4 5 25426 2 0 1 41039 1 41028 1 41039 2 11 41034 1 41039 3 41028 1 0 1 41039 4 11 35768 7 0 1 41047 1 41042 1 41047 2 5 41045 1 41047 3 41042 2 0 1 41047 4 5 31745 10 0 1 41051 1 41049 1 41051 2 2 41050 1 41051 3 41049 3 0 1 41051 4 2 26951 2 0 1 41057 1 41054 1 41057 2 3 41050 1 41057 3 41054 4 0 1 41057 4 3 25119 2 0 1 41077 1 41075 1 41077 2 2 41073 1 41077 3 41075 4 0 1 41077 4 2 28407 6 0 1 41081 1 41078 1 41081 2 3 41072 1 41081 3 41078 14 0 1 41081 4 3 40794 6 0 1 41113 1 41108 1 41113 2 5 41110 1 41113 3 41108 2 0 1 41113 4 5 40826 16 0 1 41117 1 41115 1 41117 2 2 41112 1 41117 3 41115 2 0 1 41117 4 2 36922 8 0 1 41131 1 41121 1 41131 2 10 41127 1 41131 3 41121 5 0 1 41131 4 10 20741 2 0 1 41141 1 41139 1 41141 2 2 41133 1 41141 3 41139 2 0 1 41141 4 2 25057 0 0 1 41143 1 41140 1 41143 2 3 41141 1 41143 3 41140 1 0 1 41143 4 3 25489 3 0 1 41149 1 41147 1 41149 2 2 41148 1 41149 3 41147 6 0 1 41149 4 2 41142 8 0 1 41161 1 41139 1 41161 2 22 41150 1 41161 3 41139 6 0 1 41161 4 22 31429 0 0 1 41177 1 41174 1 41177 2 3 41171 1 41177 3 41174 3 0 1 41177 4 3 32635 1 0 1 41179 1 41176 1 41179 2 3 41174 1 41179 3 41176 5 0 1 41179 4 3 37566 3 0 1 41183 1 41178 1 41183 2 5 41182 1 41183 3 41178 17 0 1 41183 4 5 34579 2 0 1 41189 1 41187 1 41189 2 2 41179 1 41189 3 41187 7 0 1 41189 4 2 26633 0 0 1 41201 1 41198 1 41201 2 3 41200 1 41201 3 41198 12 0 1 41201 4 3 32563 4 0 1 41203 1 41200 1 41203 2 3 41202 1 41203 3 41200 6 0 1 41203 4 3 29148 5 0 1 41213 1 41211 1 41213 2 2 41209 1 41213 3 41211 12 0 1 41213 4 2 40807 6 0 1 41221 1 41219 1 41221 2 2 41220 1 41221 3 41219 4 0 1 41221 4 2 22592 7 0 1 41227 1 41225 1 41227 2 2 41221 1 41227 3 41225 6 0 1 41227 4 2 24158 22 0 1 41231 1 41224 1 41231 2 7 41229 1 41231 3 41224 1 0 1 41231 4 7 39520 7 0 1 41233 1 41228 1 41233 2 5 41228 1 41233 3 41228 3 0 1 41233 4 5 39339 12 0 1 41243 1 41241 1 41243 2 2 41239 1 41243 3 41241 3 0 1 41243 4 2 29410 16 0 1 41257 1 41252 1 41257 2 5 41256 1 41257 3 41252 7 0 1 41257 4 5 40905 8 0 1 41263 1 41258 1 41263 2 5 41262 1 41263 3 41258 1 0 1 41263 4 5 21896 2 0 1 41269 1 41267 1 41269 2 2 41264 1 41269 3 41267 6 0 1 41269 4 2 25657 15 0 1 41281 1 41264 1 41281 2 17 41278 1 41281 3 41264 4 0 1 41281 4 17 34193 16 0 1 41299 1 41297 1 41299 2 2 41298 1 41299 3 41297 4 0 1 41299 4 2 27828 6 0 1 41333 1 41331 1 41333 2 2 41329 1 41333 3 41331 3 0 1 41333 4 2 40337 1 0 1 41341 1 41339 1 41341 2 2 41340 1 41341 3 41339 6 0 1 41341 4 2 31592 7 0 1 41351 1 41344 1 41351 2 7 41350 1 41351 3 41344 1 0 1 41351 4 7 27913 2 0 1 41357 1 41355 1 41357 2 2 41353 1 41357 3 41355 3 0 1 41357 4 2 38481 7 0 1 41381 1 41378 1 41381 2 3 41380 1 41381 3 41378 5 0 1 41381 4 3 28687 3 0 1 41387 1 41385 1 41387 2 2 41386 1 41387 3 41385 2 0 1 41387 4 2 39457 11 0 1 41389 1 41383 1 41389 2 6 41385 1 41389 3 41383 4 0 1 41389 4 6 31412 2 0 1 41399 1 41392 1 41399 2 7 41397 1 41399 3 41392 1 0 1 41399 4 7 21094 18 0 1 41411 1 41409 1 41411 2 2 41410 1 41411 3 41409 3 0 1 41411 4 2 38845 2 0 1 41413 1 41407 1 41413 2 6 41411 1 41413 3 41407 2 0 1 41413 4 6 21880 8 0 1 41443 1 41441 1 41443 2 2 41442 1 41443 3 41441 6 0 1 41443 4 2 41436 8 0 1 41453 1 41451 1 41453 2 2 41448 1 41453 3 41451 2 0 1 41453 4 2 23622 2 0 1 41467 1 41453 1 41467 2 14 41465 1 41467 3 41453 4 0 1 41467 4 14 24950 0 0 1 41479 1 41476 1 41479 2 3 41477 1 41479 3 41476 9 0 1 41479 4 3 36172 3 0 1 41491 1 41478 1 41491 2 13 41490 1 41491 3 41478 1 0 1 41491 4 13 34900 5 0 1 41507 1 41505 1 41507 2 2 41503 1 41507 3 41505 3 0 1 41507 4 2 22418 8 0 1 41513 1 41510 1 41513 2 3 41512 1 41513 3 41510 1 0 1 41513 4 3 27579 6 0 1 41519 1 41512 1 41519 2 7 41517 1 41519 3 41512 2 0 1 41519 4 7 26294 4 0 1 41521 1 41499 1 41521 2 22 41510 1 41521 3 41499 3 0 1 41521 4 22 26353 0 0 1 41539 1 41536 1 41539 2 3 41528 1 41539 3 41536 1 0 1 41539 4 3 21498 1 0 1 41543 1 41538 1 41543 2 5 41541 1 41543 3 41538 2 0 1 41543 4 5 29025 10 0 1 41549 1 41546 1 41549 2 3 41548 1 41549 3 41546 4 0 1 41549 4 3 21142 3 0 1 41579 1 41577 1 41579 2 2 41578 1 41579 3 41577 12 0 1 41579 4 2 33637 4 0 1 41593 1 41588 1 41593 2 5 41590 1 41593 3 41588 9 0 1 41593 4 5 41582 14 0 1 41597 1 41595 1 41597 2 2 41596 1 41597 3 41595 2 0 1 41597 4 2 25029 4 0 1 41603 1 41601 1 41603 2 2 41597 1 41603 3 41601 4 0 1 41603 4 2 28645 4 0 1 41609 1 41606 1 41609 2 3 41608 1 41609 3 41606 6 0 1 41609 4 3 22146 4 0 1 41611 1 41609 1 41611 2 2 41610 1 41611 3 41609 6 0 1 41611 4 2 40112 2 0 1 41617 1 41612 1 41617 2 5 41612 1 41617 3 41612 1 0 1 41617 4 5 40597 10 0 1 41621 1 41618 1 41621 2 3 41613 1 41621 3 41618 3 0 1 41621 4 3 39277 1 0 1 41627 1 41625 1 41627 2 2 41626 1 41627 3 41625 3 0 1 41627 4 2 38959 2 0 1 41641 1 41628 1 41641 2 13 41632 1 41641 3 41628 1 0 1 41641 4 13 34077 31 0 1 41647 1 41644 1 41647 2 3 41645 1 41647 3 41644 1 0 1 41647 4 3 24249 3 0 1 41651 1 41649 1 41651 2 2 41645 1 41651 3 41649 4 0 1 41651 4 2 40974 0 0 1 41659 1 41656 1 41659 2 3 41658 1 41659 3 41656 11 0 1 41659 4 3 27113 6 0 1 41669 1 41667 1 41669 2 2 41665 1 41669 3 41667 3 0 1 41669 4 2 28432 1 0 1 41681 1 41678 1 41681 2 3 41680 1 41681 3 41678 7 0 1 41681 4 3 40406 7 0 1 41687 1 41682 1 41687 2 5 41685 1 41687 3 41682 3 0 1 41687 4 5 41683 3 0 1 41719 1 41713 1 41719 2 6 41718 1 41719 3 41713 4 0 1 41719 4 6 28988 3 0 1 41729 1 41726 1 41729 2 3 41728 1 41729 3 41726 5 0 1 41729 4 3 32489 7 0 1 41737 1 41732 1 41737 2 5 41736 1 41737 3 41732 3 0 1 41737 4 5 33331 6 0 1 41759 1 41752 1 41759 2 7 41758 1 41759 3 41752 2 0 1 41759 4 7 41302 3 0 1 41761 1 41742 1 41761 2 19 41758 1 41761 3 41742 2 0 1 41761 4 19 21110 10 0 1 41771 1 41769 1 41771 2 2 41767 1 41771 3 41769 3 0 1 41771 4 2 40857 7 0 1 41777 1 41774 1 41777 2 3 41776 1 41777 3 41774 3 0 1 41777 4 3 28975 4 0 1 41801 1 41798 1 41801 2 3 41796 1 41801 3 41798 4 0 1 41801 4 3 37527 2 0 1 41809 1 41788 1 41809 2 21 41805 1 41809 3 41788 3 0 1 41809 4 21 25666 18 0 1 41813 1 41811 1 41813 2 2 41809 1 41813 3 41811 3 0 1 41813 4 2 33303 6 0 1 41843 1 41841 1 41843 2 2 41839 1 41843 3 41841 3 0 1 41843 4 2 37269 7 0 1 41849 1 41846 1 41849 2 3 41843 1 41849 3 41846 3 0 1 41849 4 3 41837 0 0 1 41851 1 41836 1 41851 2 15 41848 1 41851 3 41836 5 0 1 41851 4 15 29500 9 0 1 41863 1 41860 1 41863 2 3 41862 1 41863 3 41860 5 0 1 41863 4 3 35189 5 0 1 41879 1 41866 1 41879 2 13 41878 1 41879 3 41866 6 0 1 41879 4 13 32276 2 0 1 41887 1 41884 1 41887 2 3 41886 1 41887 3 41884 5 0 1 41887 4 3 30353 5 0 1 41893 1 41891 1 41893 2 2 41892 1 41893 3 41891 2 0 1 41893 4 2 41155 6 0 1 41897 1 41894 1 41897 2 3 41892 1 41897 3 41894 1 0 1 41897 4 3 38726 8 0 1 41903 1 41898 1 41903 2 5 41901 1 41903 3 41898 1 0 1 41903 4 5 27030 14 0 1 41911 1 41908 1 41911 2 3 41909 1 41911 3 41908 3 0 1 41911 4 3 41907 4 0 1 41927 1 41922 1 41927 2 5 41926 1 41927 3 41922 5 0 1 41927 4 5 33194 5 0 1 41941 1 41939 1 41941 2 2 41937 1 41941 3 41939 2 0 1 41941 4 2 33233 12 0 1 41947 1 41942 1 41947 2 5 41946 1 41947 3 41942 3 0 1 41947 4 5 40004 2 0 1 41953 1 41948 1 41953 2 5 41950 1 41953 3 41948 6 0 1 41953 4 5 41942 14 0 1 41957 1 41955 1 41957 2 2 41956 1 41957 3 41955 2 0 1 41957 4 2 35105 4 0 1 41959 1 41953 1 41959 2 6 41958 1 41959 3 41953 3 0 1 41959 4 6 38417 2 0 1 41969 1 41966 1 41969 2 3 41963 1 41969 3 41966 5 0 1 41969 4 3 41957 0 0 1 41981 1 41979 1 41981 2 2 41977 1 41981 3 41979 3 0 1 41981 4 2 33173 7 0 1 41983 1 41977 1 41983 2 6 41980 1 41983 3 41977 2 0 1 41983 4 6 39620 5 0 1 41999 1 41988 1 41999 2 11 41997 1 41999 3 41988 4 0 1 41999 4 11 30341 7 0 1 42013 1 42007 1 42013 2 6 42012 1 42013 3 42007 1 0 1 42013 4 6 25317 8 0 1 42017 1 42014 1 42017 2 3 42016 1 42017 3 42014 4 0 1 42017 4 3 41727 7 0 1 42019 1 42017 1 42019 2 2 42018 1 42019 3 42017 5 0 1 42019 4 2 22334 2 0 1 42023 1 42018 1 42023 2 5 42021 1 42023 3 42018 8 0 1 42023 4 5 42019 3 0 1 42043 1 42038 1 42043 2 5 42042 1 42043 3 42038 5 0 1 42043 4 5 35790 2 0 1 42061 1 42055 1 42061 2 6 42060 1 42061 3 42055 2 0 1 42061 4 6 32864 7 0 1 42071 1 42064 1 42071 2 7 42067 1 42071 3 42064 9 0 1 42071 4 7 31233 5 0 1 42073 1 42068 1 42073 2 5 42068 1 42073 3 42068 2 0 1 42073 4 5 38165 12 0 1 42083 1 42081 1 42083 2 2 42079 1 42083 3 42081 3 0 1 42083 4 2 36671 7 0 1 42089 1 42086 1 42089 2 3 42083 1 42089 3 42086 3 0 1 42089 4 3 42077 0 0 1 42101 1 42099 1 42101 2 2 42100 1 42101 3 42099 4 0 1 42101 4 2 26708 4 0 1 42131 1 42129 1 42131 2 2 42130 1 42131 3 42129 4 0 1 42131 4 2 22755 6 0 1 42139 1 42137 1 42139 2 2 42135 1 42139 3 42137 4 0 1 42139 4 2 31828 1 0 1 42157 1 42155 1 42157 2 2 42156 1 42157 3 42155 2 0 1 42157 4 2 41262 7 0 1 42169 1 42158 1 42169 2 11 42168 1 42169 3 42158 3 0 1 42169 4 11 39075 12 0 1 42179 1 42177 1 42179 2 2 42161 1 42179 3 42177 2 0 1 42179 4 2 35470 0 0 1 42181 1 42171 1 42181 2 10 42178 1 42181 3 42171 4 0 1 42181 4 10 35274 1 0 1 42187 1 42174 1 42187 2 13 42186 1 42187 3 42174 1 0 1 42187 4 13 35833 8 0 1 42193 1 42178 1 42193 2 15 42192 1 42193 3 42178 3 0 1 42193 4 15 39181 12 0 1 42197 1 42195 1 42197 2 2 42192 1 42197 3 42195 3 0 1 42197 4 2 33616 17 0 1 42209 1 42206 1 42209 2 3 42208 1 42209 3 42206 1 0 1 42209 4 3 25189 4 0 1 42221 1 42219 1 42221 2 2 42216 1 42221 3 42219 4 0 1 42221 4 2 26446 2 0 1 42223 1 42218 1 42223 2 5 42218 1 42223 3 42218 5 0 1 42223 4 5 24675 12 0 1 42227 1 42225 1 42227 2 2 42226 1 42227 3 42225 2 0 1 42227 4 2 41308 4 0 1 42239 1 42232 1 42239 2 7 42235 1 42239 3 42232 3 0 1 42239 4 7 21824 5 0 1 42257 1 42254 1 42257 2 3 42256 1 42257 3 42254 3 0 1 42257 4 3 27944 4 0 1 42281 1 42270 1 42281 2 11 42270 1 42281 3 42270 13 0 1 42281 4 11 35421 0 0 1 42283 1 42281 1 42283 2 2 42282 1 42283 3 42281 2 0 1 42283 4 2 38525 7 0 1 42293 1 42291 1 42293 2 2 42292 1 42293 3 42291 2 0 1 42293 4 2 26526 6 0 1 42299 1 42297 1 42299 2 2 42298 1 42299 3 42297 3 0 1 42299 4 2 29826 2 0 1 42307 1 42304 1 42307 2 3 42302 1 42307 3 42304 4 0 1 42307 4 3 29452 14 0 1 42323 1 42321 1 42323 2 2 42318 1 42323 3 42321 7 0 1 42323 4 2 37569 3 0 1 42331 1 42328 1 42331 2 3 42322 1 42331 3 42328 3 0 1 42331 4 3 35501 7 0 1 42337 1 42332 1 42337 2 5 42332 1 42337 3 42332 6 0 1 42337 4 5 33700 10 0 1 42349 1 42347 1 42349 2 2 42348 1 42349 3 42347 6 0 1 42349 4 2 41579 3 0 1 42359 1 42352 1 42359 2 7 42358 1 42359 3 42352 1 0 1 42359 4 7 30711 2 0 1 42373 1 42368 1 42373 2 5 42372 1 42373 3 42368 1 0 1 42373 4 5 25617 3 0 1 42379 1 42377 1 42379 2 2 42375 1 42379 3 42377 2 0 1 42379 4 2 33587 8 0 1 42391 1 42385 1 42391 2 6 42387 1 42391 3 42385 3 0 1 42391 4 6 29306 1 0 1 42397 1 42395 1 42397 2 2 42396 1 42397 3 42395 2 0 1 42397 4 2 33251 6 0 1 42403 1 42401 1 42403 2 2 42399 1 42403 3 42401 4 0 1 42403 4 2 26121 8 0 1 42407 1 42402 1 42407 2 5 42406 1 42407 3 42402 1 0 1 42407 4 5 30921 2 0 1 42409 1 42395 1 42409 2 14 42406 1 42409 3 42395 4 0 1 42409 4 14 34944 20 0 1 42433 1 42423 1 42433 2 10 42428 1 42433 3 42423 2 0 1 42433 4 10 24349 0 0 1 42437 1 42435 1 42437 2 2 42436 1 42437 3 42435 2 0 1 42437 4 2 32230 3 0 1 42443 1 42441 1 42443 2 2 42439 1 42443 3 42441 3 0 1 42443 4 2 29817 8 0 1 42451 1 42448 1 42451 2 3 42450 1 42451 3 42448 4 0 1 42451 4 3 32143 2 0 1 42457 1 42446 1 42457 2 11 42455 1 42457 3 42446 5 0 1 42457 4 11 36096 22 0 1 42461 1 42459 1 42461 2 2 42457 1 42461 3 42459 3 0 1 42461 4 2 28461 1 0 1 42463 1 42460 1 42463 2 3 42461 1 42463 3 42460 8 0 1 42463 4 3 42459 4 0 1 42467 1 42462 1 42467 2 5 42466 1 42467 3 42462 1 0 1 42467 4 5 33449 2 0 1 42473 1 42470 1 42473 2 3 42472 1 42473 3 42470 1 0 1 42473 4 3 39182 7 0 1 42487 1 42482 1 42487 2 5 42486 1 42487 3 42482 7 0 1 42487 4 5 33118 2 0 1 42491 1 42489 1 42491 2 2 42487 1 42491 3 42489 3 0 1 42491 4 2 42134 7 0 1 42499 1 42497 1 42499 2 2 42495 1 42499 3 42497 2 0 1 42499 4 2 33589 8 0 1 42509 1 42507 1 42509 2 2 42503 1 42509 3 42507 9 0 1 42509 4 2 41205 4 0 1 42533 1 42531 1 42533 2 2 42529 1 42533 3 42531 3 0 1 42533 4 2 28048 12 0 1 42557 1 42555 1 42557 2 2 42553 1 42557 3 42555 3 0 1 42557 4 2 23138 6 0 1 42569 1 42566 1 42569 2 3 42568 1 42569 3 42566 3 0 1 42569 4 3 40558 7 0 1 42571 1 42569 1 42571 2 2 42567 1 42571 3 42569 6 0 1 42571 4 2 32911 8 0 1 42577 1 42570 1 42577 2 7 42570 1 42577 3 42570 2 0 1 42577 4 7 32664 14 0 1 42589 1 42587 1 42589 2 2 42585 1 42589 3 42587 2 0 1 42589 4 2 26561 12 0 1 42611 1 42609 1 42611 2 2 42607 1 42611 3 42609 3 0 1 42611 4 2 35865 8 0 1 42641 1 42638 1 42641 2 3 42635 1 42641 3 42638 4 0 1 42641 4 3 42629 0 0 1 42643 1 42641 1 42643 2 2 42642 1 42643 3 42641 2 0 1 42643 4 2 27387 7 0 1 42649 1 42638 1 42649 2 11 42646 1 42649 3 42638 3 0 1 42649 4 11 24225 14 0 1 42667 1 42660 1 42667 2 7 42665 1 42667 3 42660 2 0 1 42667 4 7 29827 15 0 1 42677 1 42675 1 42677 2 2 42676 1 42677 3 42675 2 0 1 42677 4 2 38324 4 0 1 42683 1 42681 1 42683 2 2 42679 1 42683 3 42681 3 0 1 42683 4 2 34075 7 0 1 42689 1 42686 1 42689 2 3 42678 1 42689 3 42686 20 0 1 42689 4 3 21718 4 0 1 42697 1 42692 1 42697 2 5 42694 1 42697 3 42692 3 0 1 42697 4 5 29768 29 0 1 42701 1 42698 1 42701 2 3 42700 1 42701 3 42698 7 0 1 42701 4 3 21824 3 0 1 42703 1 42698 1 42703 2 5 42702 1 42703 3 42698 1 0 1 42703 4 5 33987 2 0 1 42709 1 42703 1 42709 2 6 42708 1 42709 3 42703 2 0 1 42709 4 6 26009 11 0 1 42719 1 42700 1 42719 2 19 42718 1 42719 3 42700 9 0 1 42719 4 19 24773 6 0 1 42727 1 42724 1 42727 2 3 42725 1 42727 3 42724 5 0 1 42727 4 3 37668 3 0 1 42737 1 42734 1 42737 2 3 42736 1 42737 3 42734 9 0 1 42737 4 3 39247 6 0 1 42743 1 42736 1 42743 2 7 42741 1 42743 3 42736 7 0 1 42743 4 7 26987 10 0 1 42751 1 42745 1 42751 2 6 42750 1 42751 3 42745 1 0 1 42751 4 6 37845 2 0 1 42767 1 42762 1 42767 2 5 42765 1 42767 3 42762 3 0 1 42767 4 5 37821 14 0 1 42773 1 42770 1 42773 2 3 42771 1 42773 3 42770 4 0 1 42773 4 3 24335 7 0 1 42787 1 42782 1 42787 2 5 42786 1 42787 3 42782 1 0 1 42787 4 5 34696 10 0 1 42793 1 42788 1 42793 2 5 42788 1 42793 3 42788 1 0 1 42793 4 5 26894 15 0 1 42797 1 42795 1 42797 2 2 42796 1 42797 3 42795 2 0 1 42797 4 2 42790 8 0 1 42821 1 42819 1 42821 2 2 42817 1 42821 3 42819 2 0 1 42821 4 2 39582 7 0 1 42829 1 42827 1 42829 2 2 42828 1 42829 3 42827 5 0 1 42829 4 2 32006 3 0 1 42839 1 42828 1 42839 2 11 42837 1 42839 3 42828 7 0 1 42839 4 11 23627 5 0 1 42841 1 42818 1 42841 2 23 42840 1 42841 3 42818 1 0 1 42841 4 23 39641 12 0 1 42853 1 42851 1 42853 2 2 42852 1 42853 3 42851 2 0 1 42853 4 2 38687 14 0 1 42859 1 42849 1 42859 2 10 42858 1 42859 3 42849 2 0 1 42859 4 10 38482 5 0 1 42863 1 42858 1 42863 2 5 42862 1 42863 3 42858 1 0 1 42863 4 5 39068 4 0 1 42899 1 42897 1 42899 2 2 42898 1 42899 3 42897 3 0 1 42899 4 2 22968 4 0 1 42901 1 42895 1 42901 2 6 42897 1 42901 3 42895 8 0 1 42901 4 6 39485 2 0 1 42923 1 42921 1 42923 2 2 42911 1 42923 3 42921 2 0 1 42923 4 2 27243 16 0 1 42929 1 42926 1 42929 2 3 42919 1 42929 3 42926 5 0 1 42929 4 3 38061 3 0 1 42937 1 42932 1 42937 2 5 42932 1 42937 3 42932 1 0 1 42937 4 5 42644 10 0 1 42943 1 42940 1 42943 2 3 42942 1 42943 3 42940 3 0 1 42943 4 3 26521 5 0 1 42953 1 42950 1 42953 2 3 42947 1 42953 3 42950 6 0 1 42953 4 3 35469 25 0 1 42961 1 42950 1 42961 2 11 42956 1 42961 3 42950 2 0 1 42961 4 11 24271 16 0 1 42967 1 42964 1 42967 2 3 42965 1 42967 3 42964 1 0 1 42967 4 3 29612 3 0 1 42979 1 42976 1 42979 2 3 42978 1 42979 3 42976 1 0 1 42979 4 3 31641 6 0 1 42989 1 42987 1 42989 2 2 42981 1 42989 3 42987 8 0 1 42989 4 2 29404 0 0 1 43003 1 42998 1 43003 2 5 43001 1 43003 3 42998 1 0 1 43003 4 5 42995 6 0 1 43013 1 43011 1 43013 2 2 43012 1 43013 3 43011 2 0 1 43013 4 2 25052 4 0 1 43019 1 43017 1 43019 2 2 43015 1 43019 3 43017 3 0 1 43019 4 2 25405 8 0 1 43037 1 43035 1 43037 2 2 43033 1 43037 3 43035 3 0 1 43037 4 2 40246 6 0 1 43049 1 43046 1 43049 2 3 43048 1 43049 3 43046 18 0 1 43049 4 3 25533 4 0 1 43051 1 43049 1 43051 2 2 43047 1 43051 3 43049 2 0 1 43051 4 2 39322 8 0 1 43063 1 43060 1 43063 2 3 43058 1 43063 3 43060 12 0 1 43063 4 3 40513 6 0 1 43067 1 43065 1 43067 2 2 43066 1 43067 3 43065 2 0 1 43067 4 2 38385 4 0 1 43093 1 43088 1 43093 2 5 43090 1 43093 3 43088 1 0 1 43093 4 5 38709 1 0 1 43103 1 43098 1 43103 2 5 43101 1 43103 3 43098 1 0 1 43103 4 5 43099 3 0 1 43117 1 43115 1 43117 2 2 43113 1 43117 3 43115 6 0 1 43117 4 2 33081 6 0 1 43133 1 43131 1 43133 2 2 43127 1 43133 3 43131 3 0 1 43133 4 2 35076 3 0 1 43151 1 43140 1 43151 2 11 43150 1 43151 3 43140 4 0 1 43151 4 11 28114 4 0 1 43159 1 43156 1 43159 2 3 43158 1 43159 3 43156 4 0 1 43159 4 3 34751 3 0 1 43177 1 43172 1 43177 2 5 43174 1 43177 3 43172 1 0 1 43177 4 5 43166 14 0 1 43189 1 43187 1 43189 2 2 43183 1 43189 3 43187 6 0 1 43189 4 2 36760 0 0 1 43201 1 43178 1 43201 2 23 43200 1 43201 3 43178 1 0 1 43201 4 23 29702 14 0 1 43207 1 43204 1 43207 2 3 43206 1 43207 3 43204 4 0 1 43207 4 3 39155 5 0 1 43223 1 43218 1 43223 2 5 43221 1 43223 3 43218 9 0 1 43223 4 5 39112 10 0 1 43237 1 43235 1 43237 2 2 43236 1 43237 3 43235 2 0 1 43237 4 2 24655 7 0 1 43261 1 43259 1 43261 2 2 43257 1 43261 3 43259 2 0 1 43261 4 2 28419 10 0 1 43271 1 43258 1 43271 2 13 43269 1 43271 3 43258 1 0 1 43271 4 13 43259 5 0 1 43283 1 43281 1 43283 2 2 43279 1 43283 3 43281 3 0 1 43283 4 2 38919 7 0 1 43291 1 43288 1 43291 2 3 43290 1 43291 3 43288 1 0 1 43291 4 3 34735 6 0 1 43313 1 43310 1 43313 2 3 43312 1 43313 3 43310 8 0 1 43313 4 3 40552 4 0 1 43319 1 43308 1 43319 2 11 43317 1 43319 3 43308 1 0 1 43319 4 11 38802 3 0 1 43321 1 43308 1 43321 2 13 43320 1 43321 3 43308 1 0 1 43321 4 13 29474 14 0 1 43331 1 43329 1 43331 2 2 43327 1 43331 3 43329 3 0 1 43331 4 2 40546 7 0 1 43391 1 43374 1 43391 2 17 43390 1 43391 3 43374 1 0 1 43391 4 17 27050 2 0 1 43397 1 43395 1 43397 2 2 43393 1 43397 3 43395 3 0 1 43397 4 2 33130 7 0 1 43399 1 43386 1 43399 2 13 43396 1 43399 3 43386 1 0 1 43399 4 13 41165 0 0 1 43403 1 43401 1 43403 2 2 43402 1 43403 3 43401 2 0 1 43403 4 2 32462 2 0 1 43411 1 43408 1 43411 2 3 43402 1 43411 3 43408 3 0 1 43411 4 3 21982 2 0 1 43427 1 43425 1 43427 2 2 43426 1 43427 3 43425 2 0 1 43427 4 2 42961 4 0 1 43441 1 43430 1 43441 2 11 43438 1 43441 3 43430 1 0 1 43441 4 11 34169 10 0 1 43451 1 43449 1 43451 2 2 43447 1 43451 3 43449 3 0 1 43451 4 2 23733 7 0 1 43457 1 43454 1 43457 2 3 43452 1 43457 3 43454 3 0 1 43457 4 3 25956 0 0 1 43481 1 43475 1 43481 2 6 43480 1 43481 3 43475 8 0 1 43481 4 6 32217 7 0 1 43487 1 43482 1 43487 2 5 43485 1 43487 3 43482 5 0 1 43487 4 5 38995 8 0 1 43499 1 43497 1 43499 2 2 43495 1 43499 3 43497 2 0 1 43499 4 2 24344 9 0 1 43517 1 43515 1 43517 2 2 43516 1 43517 3 43515 8 0 1 43517 4 2 29167 9 0 1 43541 1 43539 1 43541 2 2 43537 1 43541 3 43539 3 0 1 43541 4 2 33814 12 0 1 43543 1 43540 1 43543 2 3 43541 1 43543 3 43540 1 0 1 43543 4 3 37975 3 0 1 43573 1 43571 1 43573 2 2 43572 1 43573 3 43571 2 0 1 43573 4 2 32563 3 0 1 43577 1 43574 1 43577 2 3 43576 1 43577 3 43574 8 0 1 43577 4 3 39567 18 0 1 43579 1 43577 1 43579 2 2 43575 1 43579 3 43577 6 0 1 43579 4 2 36760 8 0 1 43591 1 43580 1 43591 2 11 43590 1 43591 3 43580 2 0 1 43591 4 11 39505 2 0 1 43597 1 43595 1 43597 2 2 43593 1 43597 3 43595 6 0 1 43597 4 2 25494 9 0 1 43607 1 43602 1 43607 2 5 43606 1 43607 3 43602 7 0 1 43607 4 5 33614 2 0 1 43609 1 43595 1 43609 2 14 43607 1 43609 3 43595 5 0 1 43609 4 14 43583 15 0 1 43613 1 43611 1 43613 2 2 43612 1 43613 3 43611 2 0 1 43613 4 2 33869 6 0 1 43627 1 43625 1 43627 2 2 43626 1 43627 3 43625 2 0 1 43627 4 2 23387 11 0 1 43633 1 43628 1 43633 2 5 43630 1 43633 3 43628 2 0 1 43633 4 5 42940 29 0 1 43649 1 43646 1 43649 2 3 43644 1 43649 3 43646 3 0 1 43649 4 3 39029 2 0 1 43651 1 43649 1 43651 2 2 43650 1 43651 3 43649 5 0 1 43651 4 2 31013 6 0 1 43661 1 43659 1 43661 2 2 43657 1 43661 3 43659 3 0 1 43661 4 2 42390 6 0 1 43669 1 43667 1 43669 2 2 43665 1 43669 3 43667 4 0 1 43669 4 2 31089 11 0 1 43691 1 43685 1 43691 2 6 43688 1 43691 3 43685 2 0 1 43691 4 6 25082 4 0 1 43711 1 43698 1 43711 2 13 43707 1 43711 3 43698 1 0 1 43711 4 13 40875 6 0 1 43717 1 43712 1 43717 2 5 43712 1 43717 3 43712 2 0 1 43717 4 5 25396 22 0 1 43721 1 43718 1 43721 2 3 43716 1 43721 3 43718 1 0 1 43721 4 3 24256 2 0 1 43753 1 43746 1 43753 2 7 43750 1 43753 3 43746 3 0 1 43753 4 7 34502 10 0 1 43759 1 43756 1 43759 2 3 43757 1 43759 3 43756 4 0 1 43759 4 3 31341 3 0 1 43777 1 43772 1 43777 2 5 43774 1 43777 3 43772 2 0 1 43777 4 5 33589 10 0 1 43781 1 43779 1 43781 2 2 43780 1 43781 3 43779 3 0 1 43781 4 2 28286 4 0 1 43783 1 43780 1 43783 2 3 43781 1 43783 3 43780 1 0 1 43783 4 3 26033 6 0 1 43787 1 43785 1 43787 2 2 43782 1 43787 3 43785 4 0 1 43787 4 2 29567 3 0 1 43789 1 43783 1 43789 2 6 43788 1 43789 3 43783 2 0 1 43789 4 6 26852 11 0 1 43793 1 43790 1 43793 2 3 43792 1 43793 3 43790 1 0 1 43793 4 3 22460 4 0 1 43801 1 43770 1 43801 2 31 43800 1 43801 3 43770 10 0 1 43801 4 31 38713 12 0 1 43853 1 43851 1 43853 2 2 43852 1 43853 3 43851 2 0 1 43853 4 2 33682 3 0 1 43867 1 43864 1 43867 2 3 43866 1 43867 3 43864 1 0 1 43867 4 3 40905 5 0 1 43889 1 43886 1 43889 2 3 43888 1 43889 3 43886 4 0 1 43889 4 3 35759 7 0 1 43891 1 43888 1 43891 2 3 43882 1 43891 3 43888 1 0 1 43891 4 3 27605 2 0 1 43913 1 43910 1 43913 2 3 43906 1 43913 3 43910 1 0 1 43913 4 3 40419 1 0 1 43933 1 43931 1 43933 2 2 43929 1 43933 3 43931 6 0 1 43933 4 2 28743 6 0 1 43943 1 43938 1 43943 2 5 43942 1 43943 3 43938 9 0 1 43943 4 5 26709 2 0 1 43951 1 43945 1 43951 2 6 43950 1 43951 3 43945 1 0 1 43951 4 6 37226 3 0 1 43961 1 43955 1 43961 2 6 43958 1 43961 3 43955 2 0 1 43961 4 6 41983 0 0 1 43963 1 43951 1 43963 2 12 43961 1 43963 3 43951 5 0 1 43963 4 12 31920 0 0 1 43969 1 43958 1 43969 2 11 43964 1 43969 3 43958 1 0 1 43969 4 11 36514 16 0 1 43973 1 43971 1 43973 2 2 43972 1 43973 3 43971 2 0 1 43973 4 2 39500 3 0 1 43987 1 43985 1 43987 2 2 43986 1 43987 3 43985 2 0 1 43987 4 2 25031 20 0 1 43991 1 43974 1 43991 2 17 43989 1 43991 3 43974 2 0 1 43991 4 17 25746 4 0 1 43997 1 43995 1 43997 2 2 43985 1 43997 3 43995 5 0 1 43997 4 2 43240 4 0 1 44017 1 44006 1 44017 2 11 44016 1 44017 3 44006 8 0 1 44017 4 11 27001 11 0 1 44021 1 44019 1 44021 2 2 44020 1 44021 3 44019 3 0 1 44021 4 2 25060 3 0 1 44027 1 44025 1 44027 2 2 44022 1 44027 3 44025 8 0 1 44027 4 2 43513 3 0 1 44029 1 44023 1 44029 2 6 44025 1 44029 3 44023 1 0 1 44029 4 6 44025 6 0 1 44041 1 44030 1 44041 2 11 44030 1 44041 3 44030 1 0 1 44041 4 11 40183 33 0 1 44053 1 44051 1 44053 2 2 44049 1 44053 3 44051 6 0 1 44053 4 2 34020 6 0 1 44059 1 44057 1 44059 2 2 44055 1 44059 3 44057 2 0 1 44059 4 2 41061 8 0 1 44071 1 44068 1 44071 2 3 44069 1 44071 3 44068 6 0 1 44071 4 3 38223 3 0 1 44087 1 44082 1 44087 2 5 44084 1 44087 3 44082 6 0 1 44087 4 5 35704 4 0 1 44089 1 44076 1 44089 2 13 44077 1 44089 3 44076 5 0 1 44089 4 13 37163 5 0 1 44101 1 44095 1 44101 2 6 44100 1 44101 3 44095 9 0 1 44101 4 6 27234 7 0 1 44111 1 44104 1 44111 2 7 44110 1 44111 3 44104 5 0 1 44111 4 7 34808 2 0 1 44119 1 44113 1 44119 2 6 44118 1 44119 3 44113 2 0 1 44119 4 6 24852 2 0 1 44123 1 44121 1 44123 2 2 44119 1 44123 3 44121 4 0 1 44123 4 2 27622 8 0 1 44129 1 44126 1 44129 2 3 44128 1 44129 3 44126 6 0 1 44129 4 3 25052 7 0 1 44131 1 44129 1 44131 2 2 44130 1 44131 3 44129 5 0 1 44131 4 2 44124 8 0 1 44159 1 44148 1 44159 2 11 44157 1 44159 3 44148 1 0 1 44159 4 11 24048 3 0 1 44171 1 44169 1 44171 2 2 44167 1 44171 3 44169 3 0 1 44171 4 2 28055 7 0 1 44179 1 44177 1 44179 2 2 44175 1 44179 3 44177 2 0 1 44179 4 2 22840 8 0 1 44189 1 44187 1 44189 2 2 44184 1 44189 3 44187 3 0 1 44189 4 2 24361 2 0 1 44201 1 44195 1 44201 2 6 44198 1 44201 3 44195 2 0 1 44201 4 6 29090 0 0 1 44203 1 44198 1 44203 2 5 44201 1 44203 3 44198 1 0 1 44203 4 5 30833 0 0 1 44207 1 44202 1 44207 2 5 44206 1 44207 3 44202 1 0 1 44207 4 5 42981 3 0 1 44221 1 44219 1 44221 2 2 44217 1 44221 3 44219 2 0 1 44221 4 2 32008 12 0 1 44249 1 44246 1 44249 2 3 44248 1 44249 3 44246 1 0 1 44249 4 3 30476 7 0 1 44257 1 44252 1 44257 2 5 44252 1 44257 3 44252 7 0 1 44257 4 5 23929 10 0 1 44263 1 44260 1 44263 2 3 44262 1 44263 3 44260 1 0 1 44263 4 3 41855 2 0 1 44267 1 44265 1 44267 2 2 44266 1 44267 3 44265 8 0 1 44267 4 2 29079 2 0 1 44269 1 44267 1 44269 2 2 44265 1 44269 3 44267 5 0 1 44269 4 2 31561 10 0 1 44273 1 44270 1 44273 2 3 44267 1 44273 3 44270 1 0 1 44273 4 3 34723 1 0 1 44279 1 44272 1 44279 2 7 44278 1 44279 3 44272 1 0 1 44279 4 7 43581 6 0 1 44281 1 44274 1 44281 2 7 44274 1 44281 3 44274 5 0 1 44281 4 7 35321 0 0 1 44293 1 44291 1 44293 2 2 44289 1 44293 3 44291 6 0 1 44293 4 2 32613 9 0 1 44351 1 44332 1 44351 2 19 44350 1 44351 3 44332 3 0 1 44351 4 19 27884 2 0 1 44357 1 44355 1 44357 2 2 44356 1 44357 3 44355 2 0 1 44357 4 2 33875 6 0 1 44371 1 44369 1 44371 2 2 44370 1 44371 3 44369 4 0 1 44371 4 2 33187 2 0 1 44381 1 44379 1 44381 2 2 44377 1 44381 3 44379 2 0 1 44381 4 2 22426 6 0 1 44383 1 44380 1 44383 2 3 44381 1 44383 3 44380 4 0 1 44383 4 3 38428 3 0 1 44389 1 44387 1 44389 2 2 44385 1 44389 3 44387 2 0 1 44389 4 2 30976 10 0 1 44417 1 44414 1 44417 2 3 44416 1 44417 3 44414 4 0 1 44417 4 3 22776 4 0 1 44449 1 44436 1 44449 2 13 44448 1 44449 3 44436 1 0 1 44449 4 13 43275 8 0 1 44453 1 44451 1 44453 2 2 44452 1 44453 3 44451 2 0 1 44453 4 2 32208 9 0 1 44483 1 44481 1 44483 2 2 44482 1 44483 3 44481 2 0 1 44483 4 2 44476 8 0 1 44491 1 44478 1 44491 2 13 44487 1 44491 3 44478 5 0 1 44491 4 13 44479 8 0 1 44497 1 44492 1 44497 2 5 44496 1 44497 3 44492 8 0 1 44497 4 5 40423 6 0 1 44501 1 44499 1 44501 2 2 44497 1 44501 3 44499 2 0 1 44501 4 2 40698 6 0 1 44507 1 44505 1 44507 2 2 44503 1 44507 3 44505 3 0 1 44507 4 2 23167 7 0 1 44519 1 44506 1 44519 2 13 44518 1 44519 3 44506 9 0 1 44519 4 13 36891 2 0 1 44531 1 44529 1 44531 2 2 44527 1 44531 3 44529 2 0 1 44531 4 2 25071 7 0 1 44533 1 44531 1 44533 2 2 44532 1 44533 3 44531 2 0 1 44533 4 2 40441 9 0 1 44537 1 44534 1 44537 2 3 44526 1 44537 3 44534 1 0 1 44537 4 3 34804 1 0 1 44543 1 44538 1 44543 2 5 44541 1 44543 3 44538 13 0 1 44543 4 5 30983 8 0 1 44549 1 44547 1 44549 2 2 44541 1 44549 3 44547 2 0 1 44549 4 2 26924 0 0 1 44563 1 44560 1 44563 2 3 44562 1 44563 3 44560 3 0 1 44563 4 3 29486 7 0 1 44579 1 44577 1 44579 2 2 44578 1 44579 3 44577 3 0 1 44579 4 2 32744 2 0 1 44587 1 44584 1 44587 2 3 44580 1 44587 3 44584 7 0 1 44587 4 3 42198 2 0 1 44617 1 44612 1 44617 2 5 44610 1 44617 3 44612 6 0 1 44617 4 5 36621 12 0 1 44621 1 44619 1 44621 2 2 44617 1 44621 3 44619 3 0 1 44621 4 2 25247 1 0 1 44623 1 44618 1 44623 2 5 44621 1 44623 3 44618 6 0 1 44623 4 5 38712 9 0 1 44633 1 44630 1 44633 2 3 44627 1 44633 3 44630 5 0 1 44633 4 3 25261 1 0 1 44641 1 44622 1 44641 2 19 44626 1 44641 3 44622 1 0 1 44641 4 19 29082 53 0 1 44647 1 44642 1 44647 2 5 44645 1 44647 3 44642 3 0 1 44647 4 5 44643 3 0 1 44651 1 44649 1 44651 2 2 44639 1 44651 3 44649 10 0 1 44651 4 2 29349 2 0 1 44657 1 44654 1 44657 2 3 44650 1 44657 3 44654 3 0 1 44657 4 3 35664 1 0 1 44683 1 44681 1 44683 2 2 44679 1 44683 3 44681 6 0 1 44683 4 2 39812 8 0 1 44687 1 44682 1 44687 2 5 44686 1 44687 3 44682 5 0 1 44687 4 5 22753 7 0 1 44699 1 44697 1 44699 2 2 44695 1 44699 3 44697 3 0 1 44699 4 2 22700 13 0 1 44701 1 44699 1 44701 2 2 44700 1 44701 3 44699 4 0 1 44701 4 2 33644 3 0 1 44711 1 44704 1 44711 2 7 44710 1 44711 3 44704 3 0 1 44711 4 7 32919 3 0 1 44729 1 44726 1 44729 2 3 44718 1 44729 3 44726 12 0 1 44729 4 3 33328 8 0 1 44741 1 44739 1 44741 2 2 44737 1 44741 3 44739 2 0 1 44741 4 2 24989 6 0 1 44753 1 44750 1 44753 2 3 44748 1 44753 3 44750 1 0 1 44753 4 3 40201 0 0 1 44771 1 44765 1 44771 2 6 44768 1 44771 3 44765 3 0 1 44771 4 6 37426 1 0 1 44773 1 44768 1 44773 2 5 44768 1 44773 3 44768 7 0 1 44773 4 5 31254 10 0 1 44777 1 44774 1 44777 2 3 44776 1 44777 3 44774 1 0 1 44777 4 3 35882 7 0 1 44789 1 44787 1 44789 2 2 44788 1 44789 3 44787 3 0 1 44789 4 2 25164 3 0 1 44797 1 44795 1 44797 2 2 44793 1 44797 3 44795 4 0 1 44797 4 2 38114 19 0 1 44809 1 44798 1 44809 2 11 44808 1 44809 3 44798 3 0 1 44809 4 11 42414 12 0 1 44819 1 44817 1 44819 2 2 44818 1 44819 3 44817 8 0 1 44819 4 2 39060 4 0 1 44839 1 44833 1 44839 2 6 44837 1 44839 3 44833 2 0 1 44839 4 6 23972 10 0 1 44843 1 44838 1 44843 2 5 44842 1 44843 3 44838 2 0 1 44843 4 5 40321 5 0 1 44851 1 44841 1 44851 2 10 44849 1 44851 3 44841 6 0 1 44851 4 10 44833 11 0 1 44867 1 44865 1 44867 2 2 44863 1 44867 3 44865 3 0 1 44867 4 2 29181 8 0 1 44879 1 44872 1 44879 2 7 44872 1 44879 3 44872 1 0 1 44879 4 7 35745 12 0 1 44887 1 44882 1 44887 2 5 44885 1 44887 3 44882 3 0 1 44887 4 5 22724 10 0 1 44893 1 44888 1 44893 2 5 44892 1 44893 3 44888 2 0 1 44893 4 5 35048 3 0 1 44909 1 44907 1 44909 2 2 44905 1 44909 3 44907 2 0 1 44909 4 2 41382 12 0 1 44917 1 44912 1 44917 2 5 44912 1 44917 3 44912 12 0 1 44917 4 5 36869 7 0 1 44927 1 44920 1 44927 2 7 44920 1 44927 3 44920 11 0 1 44927 4 7 24924 0 0 1 44939 1 44937 1 44939 2 2 44932 1 44939 3 44937 4 0 1 44939 4 2 36433 1 0 1 44953 1 44948 1 44953 2 5 44950 1 44953 3 44948 1 0 1 44953 4 5 23277 23 0 1 44959 1 44956 1 44959 2 3 44958 1 44959 3 44956 4 0 1 44959 4 3 31149 3 0 1 44963 1 44961 1 44963 2 2 44959 1 44963 3 44961 3 0 1 44963 4 2 26831 8 0 1 44971 1 44968 1 44971 2 3 44958 1 44971 3 44968 9 0 1 44971 4 3 24561 2 0 1 44983 1 44980 1 44983 2 3 44981 1 44983 3 44980 3 0 1 44983 4 3 37289 3 0 1 44987 1 44985 1 44987 2 2 44986 1 44987 3 44985 2 0 1 44987 4 2 37946 2 0 1 45007 1 45004 1 45007 2 3 45006 1 45007 3 45004 3 0 1 45007 4 3 39082 16 0 1 45013 1 45011 1 45013 2 2 45012 1 45013 3 45011 6 0 1 45013 4 2 44248 9 0 1 45053 1 45051 1 45053 2 2 45049 1 45053 3 45051 3 0 1 45053 4 2 28099 7 0 1 45061 1 45059 1 45061 2 2 45057 1 45061 3 45059 2 0 1 45061 4 2 37766 6 0 1 45077 1 45075 1 45077 2 2 45072 1 45077 3 45075 7 0 1 45077 4 2 42647 16 0 1 45083 1 45081 1 45083 2 2 45082 1 45083 3 45081 2 0 1 45083 4 2 36140 2 0 1 45119 1 45112 1 45119 2 7 45118 1 45119 3 45112 1 0 1 45119 4 7 43617 3 0 1 45121 1 45114 1 45121 2 7 45118 1 45121 3 45114 4 0 1 45121 4 7 31700 14 0 1 45127 1 45115 1 45127 2 12 45123 1 45127 3 45115 1 0 1 45127 4 12 41102 5 0 1 45131 1 45129 1 45131 2 2 45125 1 45131 3 45129 2 0 1 45131 4 2 28913 4 0 1 45137 1 45134 1 45137 2 3 45124 1 45137 3 45134 4 0 1 45137 4 3 40344 25 0 1 45139 1 45137 1 45139 2 2 45138 1 45139 3 45137 5 0 1 45139 4 2 30734 7 0 1 45161 1 45158 1 45161 2 3 45160 1 45161 3 45158 11 0 1 45161 4 3 34176 4 0 1 45179 1 45173 1 45179 2 6 45171 1 45179 3 45173 10 0 1 45179 4 6 41353 1 0 1 45181 1 45179 1 45181 2 2 45180 1 45181 3 45179 4 0 1 45181 4 2 45174 8 0 1 45191 1 45180 1 45191 2 11 45187 1 45191 3 45180 1 0 1 45191 4 11 27300 5 0 1 45197 1 45195 1 45197 2 2 45196 1 45197 3 45195 5 0 1 45197 4 2 31103 4 0 1 45233 1 45230 1 45233 2 3 45227 1 45233 3 45230 7 0 1 45233 4 3 30727 1 0 1 45247 1 45242 1 45247 2 5 45246 1 45247 3 45242 1 0 1 45247 4 5 38021 3 0 1 45259 1 45256 1 45259 2 3 45254 1 45259 3 45256 11 0 1 45259 4 3 41101 3 0 1 45263 1 45258 1 45263 2 5 45261 1 45263 3 45258 6 0 1 45263 4 5 45259 3 0 1 45281 1 45278 1 45281 2 3 45276 1 45281 3 45278 3 0 1 45281 4 3 44980 2 0 1 45289 1 45275 1 45289 2 14 45284 1 45289 3 45275 4 0 1 45289 4 14 34625 12 0 1 45293 1 45291 1 45293 2 2 45292 1 45293 3 45291 2 0 1 45293 4 2 29347 3 0 1 45307 1 45305 1 45307 2 2 45306 1 45307 3 45305 6 0 1 45307 4 2 45300 8 0 1 45317 1 45315 1 45317 2 2 45316 1 45317 3 45315 2 0 1 45317 4 2 27826 3 0 1 45319 1 45316 1 45319 2 3 45317 1 45319 3 45316 1 0 1 45319 4 3 45315 4 0 1 45329 1 45326 1 45329 2 3 45315 1 45329 3 45326 5 0 1 45329 4 3 26229 2 0 1 45337 1 45332 1 45337 2 5 45336 1 45337 3 45332 1 0 1 45337 4 5 32816 6 0 1 45341 1 45339 1 45341 2 2 45329 1 45341 3 45339 2 0 1 45341 4 2 42292 1 0 1 45343 1 45337 1 45343 2 6 45342 1 45343 3 45337 6 0 1 45343 4 6 34743 3 0 1 45361 1 45350 1 45361 2 11 45360 1 45361 3 45350 1 0 1 45361 4 11 44156 12 0 1 45377 1 45374 1 45377 2 3 45372 1 45377 3 45374 3 0 1 45377 4 3 37182 0 0 1 45389 1 45387 1 45389 2 2 45379 1 45389 3 45387 2 0 1 45389 4 2 30421 0 0 1 45403 1 45400 1 45403 2 3 45402 1 45403 3 45400 1 0 1 45403 4 3 27129 2 0 1 45413 1 45411 1 45413 2 2 45406 1 45413 3 45411 5 0 1 45413 4 2 42709 4 0 1 45427 1 45424 1 45427 2 3 45426 1 45427 3 45424 6 0 1 45427 4 3 23344 5 0 1 45433 1 45426 1 45433 2 7 45426 1 45433 3 45426 1 0 1 45433 4 7 26654 12 0 1 45439 1 45436 1 45439 2 3 45433 1 45439 3 45436 4 0 1 45439 4 3 36560 7 0 1 45481 1 45468 1 45481 2 13 45480 1 45481 3 45468 1 0 1 45481 4 13 35722 18 0 1 45491 1 45489 1 45491 2 2 45487 1 45491 3 45489 3 0 1 45491 4 2 35717 7 0 1 45497 1 45494 1 45497 2 3 45491 1 45497 3 45494 1 0 1 45497 4 3 33499 27 0 1 45503 1 45498 1 45503 2 5 45501 1 45503 3 45498 1 0 1 45503 4 5 45499 3 0 1 45523 1 45521 1 45523 2 2 45519 1 45523 3 45521 4 0 1 45523 4 2 30815 8 0 1 45533 1 45531 1 45533 2 2 45532 1 45533 3 45531 4 0 1 45533 4 2 41057 9 0 1 45541 1 45531 1 45541 2 10 45540 1 45541 3 45531 3 0 1 45541 4 10 26200 14 0 1 45553 1 45548 1 45553 2 5 45552 1 45553 3 45548 3 0 1 45553 4 5 44878 6 0 1 45557 1 45554 1 45557 2 3 45556 1 45557 3 45554 3 0 1 45557 4 3 44882 6 0 1 45569 1 45566 1 45569 2 3 45568 1 45569 3 45566 1 0 1 45569 4 3 40897 4 0 1 45587 1 45585 1 45587 2 2 45586 1 45587 3 45585 10 0 1 45587 4 2 31949 13 0 1 45589 1 45587 1 45589 2 2 45588 1 45589 3 45587 5 0 1 45589 4 2 28142 9 0 1 45599 1 45592 1 45599 2 7 45595 1 45599 3 45592 4 0 1 45599 4 7 44995 6 0 1 45613 1 45611 1 45613 2 2 45609 1 45613 3 45611 6 0 1 45613 4 2 29096 12 0 1 45631 1 45619 1 45631 2 12 45630 1 45631 3 45619 3 0 1 45631 4 12 26884 2 0 1 45641 1 45630 1 45641 2 11 45632 1 45641 3 45630 1 0 1 45641 4 11 36166 15 0 1 45659 1 45657 1 45659 2 2 45650 1 45659 3 45657 5 0 1 45659 4 2 41259 1 0 1 45667 1 45665 1 45667 2 2 45663 1 45667 3 45665 2 0 1 45667 4 2 29332 11 0 1 45673 1 45668 1 45673 2 5 45668 1 45673 3 45668 5 0 1 45673 4 5 32101 10 0 1 45677 1 45675 1 45677 2 2 45673 1 45677 3 45675 3 0 1 45677 4 2 37666 12 0 1 45691 1 45684 1 45691 2 7 45689 1 45691 3 45684 5 0 1 45691 4 7 25859 6 0 1 45697 1 45687 1 45697 2 10 45696 1 45697 3 45687 6 0 1 45697 4 10 38298 6 0 1 45707 1 45705 1 45707 2 2 45702 1 45707 3 45705 5 0 1 45707 4 2 25083 3 0 1 45737 1 45734 1 45737 2 3 45730 1 45737 3 45734 5 0 1 45737 4 3 38513 0 0 1 45751 1 45748 1 45751 2 3 45750 1 45751 3 45748 4 0 1 45751 4 3 30312 2 0 1 45757 1 45755 1 45757 2 2 45756 1 45757 3 45755 6 0 1 45757 4 2 40134 7 0 1 45763 1 45758 1 45763 2 5 45761 1 45763 3 45758 6 0 1 45763 4 5 45755 6 0 1 45767 1 45762 1 45767 2 5 45766 1 45767 3 45762 2 0 1 45767 4 5 26371 5 0 1 45779 1 45777 1 45779 2 2 45767 1 45779 3 45777 4 0 1 45779 4 2 24414 6 0 1 45817 1 45812 1 45817 2 5 45816 1 45817 3 45812 7 0 1 45817 4 5 43698 6 0 1 45821 1 45819 1 45821 2 2 45817 1 45821 3 45819 3 0 1 45821 4 2 27262 1 0 1 45823 1 45820 1 45823 2 3 45822 1 45823 3 45820 1 0 1 45823 4 3 30323 2 0 1 45827 1 45825 1 45827 2 2 45826 1 45827 3 45825 3 0 1 45827 4 2 40257 4 0 1 45833 1 45828 1 45833 2 5 45825 1 45833 3 45828 5 0 1 45833 4 5 44852 11 0 1 45841 1 45834 1 45841 2 7 45838 1 45841 3 45834 3 0 1 45841 4 7 31158 17 0 1 45853 1 45848 1 45853 2 5 45848 1 45853 3 45848 1 0 1 45853 4 5 27311 11 0 1 45863 1 45853 1 45863 2 10 45862 1 45863 3 45853 2 0 1 45863 4 10 24212 3 0 1 45869 1 45867 1 45869 2 2 45868 1 45869 3 45867 4 0 1 45869 4 2 26797 3 0 1 45887 1 45882 1 45887 2 5 45886 1 45887 3 45882 9 0 1 45887 4 5 39288 3 0 1 45893 1 45891 1 45893 2 2 45889 1 45893 3 45891 3 0 1 45893 4 2 39520 26 0 1 45943 1 45937 1 45943 2 6 45940 1 45943 3 45937 6 0 1 45943 4 6 30371 5 0 1 45949 1 45947 1 45949 2 2 45945 1 45949 3 45947 2 0 1 45949 4 2 33945 10 0 1 45953 1 45950 1 45953 2 3 45952 1 45953 3 45950 9 0 1 45953 4 3 37935 8 0 1 45959 1 45952 1 45959 2 7 45958 1 45959 3 45952 3 0 1 45959 4 7 32873 7 0 1 45971 1 45969 1 45971 2 2 45967 1 45971 3 45969 2 0 1 45971 4 2 44216 8 0 1 45979 1 45977 1 45979 2 2 45978 1 45979 3 45977 5 0 1 45979 4 2 28690 7 0 1 45989 1 45987 1 45989 2 2 45988 1 45989 3 45987 3 0 1 45989 4 2 35560 9 0 1 46021 1 46019 1 46021 2 2 46020 1 46021 3 46019 6 0 1 46021 4 2 31211 3 0 1 46027 1 46025 1 46027 2 2 46023 1 46027 3 46025 6 0 1 46027 4 2 30373 8 0 1 46049 1 46046 1 46049 2 3 46038 1 46049 3 46046 5 0 1 46049 4 3 26786 8 0 1 46051 1 46048 1 46051 2 3 46046 1 46051 3 46048 1 0 1 46051 4 3 25364 3 0 1 46061 1 46059 1 46061 2 2 46057 1 46061 3 46059 2 0 1 46061 4 2 38464 7 0 1 46073 1 46068 1 46073 2 5 46068 1 46073 3 46068 6 0 1 46073 4 5 33248 2 0 1 46091 1 46089 1 46091 2 2 46087 1 46091 3 46089 3 0 1 46091 4 2 38291 19 0 1 46093 1 46091 1 46093 2 2 46092 1 46093 3 46091 2 0 1 46093 4 2 32682 6 0 1 46099 1 46097 1 46099 2 2 46095 1 46099 3 46097 4 0 1 46099 4 2 39615 8 0 1 46103 1 46093 1 46103 2 10 46101 1 46103 3 46093 4 0 1 46103 4 10 46085 11 0 1 46133 1 46131 1 46133 2 2 46132 1 46133 3 46131 9 0 1 46133 4 2 28930 3 0 1 46141 1 46131 1 46141 2 10 46138 1 46141 3 46131 11 0 1 46141 4 10 39758 9 0 1 46147 1 46145 1 46147 2 2 46146 1 46147 3 46145 5 0 1 46147 4 2 25219 2 0 1 46153 1 46148 1 46153 2 5 46152 1 46153 3 46148 7 0 1 46153 4 5 35048 12 0 1 46171 1 46168 1 46171 2 3 46166 1 46171 3 46168 4 0 1 46171 4 3 27178 3 0 1 46181 1 46179 1 46181 2 2 46177 1 46181 3 46179 3 0 1 46181 4 2 35131 12 0 1 46183 1 46180 1 46183 2 3 46181 1 46183 3 46180 8 0 1 46183 4 3 46179 4 0 1 46187 1 46185 1 46187 2 2 46177 1 46187 3 46185 8 0 1 46187 4 2 36061 2 0 1 46199 1 46182 1 46199 2 17 46197 1 46199 3 46182 7 0 1 46199 4 17 46191 3 0 1 46219 1 46216 1 46219 2 3 46218 1 46219 3 46216 1 0 1 46219 4 3 43375 2 0 1 46229 1 46227 1 46229 2 2 46224 1 46229 3 46227 2 0 1 46229 4 2 44536 2 0 1 46237 1 46235 1 46237 2 2 46233 1 46237 3 46235 4 0 1 46237 4 2 41915 12 0 1 46261 1 46259 1 46261 2 2 46260 1 46261 3 46259 5 0 1 46261 4 2 23371 3 0 1 46271 1 46264 1 46271 2 7 46269 1 46271 3 46264 3 0 1 46271 4 7 38257 4 0 1 46273 1 46268 1 46273 2 5 46272 1 46273 3 46268 5 0 1 46273 4 5 34133 6 0 1 46279 1 46276 1 46279 2 3 46278 1 46279 3 46276 3 0 1 46279 4 3 39624 3 0 1 46301 1 46299 1 46301 2 2 46297 1 46301 3 46299 3 0 1 46301 4 2 29134 1 0 1 46307 1 46305 1 46307 2 2 46303 1 46307 3 46305 9 0 1 46307 4 2 28139 13 0 1 46309 1 46307 1 46309 2 2 46305 1 46309 3 46307 4 0 1 46309 4 2 25582 12 0 1 46327 1 46324 1 46327 2 3 46326 1 46327 3 46324 8 0 1 46327 4 3 32791 2 0 1 46337 1 46334 1 46337 2 3 46332 1 46337 3 46334 1 0 1 46337 4 3 44575 0 0 1 46349 1 46347 1 46349 2 2 46342 1 46349 3 46347 5 0 1 46349 4 2 42092 17 0 1 46351 1 46348 1 46351 2 3 46350 1 46351 3 46348 6 0 1 46351 4 3 39860 3 0 1 46381 1 46374 1 46381 2 7 46378 1 46381 3 46374 2 0 1 46381 4 7 35780 5 0 1 46399 1 46396 1 46399 2 3 46397 1 46399 3 46396 4 0 1 46399 4 3 46395 4 0 1 46411 1 46408 1 46411 2 3 46410 1 46411 3 46408 4 0 1 46411 4 3 39497 7 0 1 46439 1 46432 1 46439 2 7 46437 1 46439 3 46432 1 0 1 46439 4 7 42373 5 0 1 46441 1 46434 1 46441 2 7 46434 1 46441 3 46434 2 0 1 46441 4 7 27654 18 0 1 46447 1 46444 1 46447 2 3 46445 1 46447 3 46444 5 0 1 46447 4 3 46443 4 0 1 46451 1 46445 1 46451 2 6 46449 1 46451 3 46445 2 0 1 46451 4 6 41734 5 0 1 46457 1 46454 1 46457 2 3 46452 1 46457 3 46454 1 0 1 46457 4 3 43174 0 0 1 46471 1 46468 1 46471 2 3 46470 1 46471 3 46468 1 0 1 46471 4 3 41420 3 0 1 46477 1 46475 1 46477 2 2 46473 1 46477 3 46475 5 0 1 46477 4 2 26312 10 0 1 46489 1 46460 1 46489 2 29 46486 1 46489 3 46460 3 0 1 46489 4 29 44904 20 0 1 46499 1 46497 1 46499 2 2 46495 1 46499 3 46497 3 0 1 46499 4 2 24692 7 0 1 46507 1 46505 1 46507 2 2 46503 1 46507 3 46505 2 0 1 46507 4 2 30550 1 0 1 46511 1 46500 1 46511 2 11 46507 1 46511 3 46500 2 0 1 46511 4 11 45147 6 0 1 46523 1 46518 1 46523 2 5 46521 1 46523 3 46518 6 0 1 46523 4 5 43829 5 0 1 46549 1 46547 1 46549 2 2 46545 1 46549 3 46547 5 0 1 46549 4 2 36157 6 0 1 46559 1 46552 1 46559 2 7 46558 1 46559 3 46552 9 0 1 46559 4 7 24905 2 0 1 46567 1 46564 1 46567 2 3 46565 1 46567 3 46564 1 0 1 46567 4 3 30664 6 0 1 46573 1 46571 1 46573 2 2 46569 1 46573 3 46571 9 0 1 46573 4 2 42450 6 0 1 46589 1 46587 1 46589 2 2 46582 1 46589 3 46587 2 0 1 46589 4 2 42838 4 0 1 46591 1 46585 1 46591 2 6 46587 1 46591 3 46585 2 0 1 46591 4 6 23581 1 0 1 46601 1 46598 1 46601 2 3 46594 1 46601 3 46598 5 0 1 46601 4 3 37174 1 0 1 46619 1 46613 1 46619 2 6 46617 1 46619 3 46613 3 0 1 46619 4 6 44101 9 0 1 46633 1 46628 1 46633 2 5 46628 1 46633 3 46628 3 0 1 46633 4 5 41892 10 0 1 46639 1 46633 1 46639 2 6 46637 1 46639 3 46633 3 0 1 46639 4 6 34453 3 0 1 46643 1 46641 1 46643 2 2 46637 1 46643 3 46641 4 0 1 46643 4 2 37192 4 0 1 46649 1 46634 1 46649 2 15 46648 1 46649 3 46634 1 0 1 46649 4 15 26508 4 0 1 46663 1 46658 1 46663 2 5 46662 1 46663 3 46658 1 0 1 46663 4 5 38255 2 0 1 46679 1 46662 1 46679 2 17 46677 1 46679 3 46662 3 0 1 46679 4 17 45842 8 0 1 46681 1 46670 1 46681 2 11 46680 1 46681 3 46670 2 0 1 46681 4 11 38568 14 0 1 46687 1 46684 1 46687 2 3 46685 1 46687 3 46684 1 0 1 46687 4 3 46683 4 0 1 46691 1 46689 1 46691 2 2 46687 1 46691 3 46689 3 0 1 46691 4 2 39580 8 0 1 46703 1 46698 1 46703 2 5 46700 1 46703 3 46698 1 0 1 46703 4 5 25022 9 0 1 46723 1 46721 1 46723 2 2 46722 1 46723 3 46721 2 0 1 46723 4 2 40260 2 0 1 46727 1 46722 1 46727 2 5 46725 1 46727 3 46722 2 0 1 46727 4 5 46715 11 0 1 46747 1 46745 1 46747 2 2 46743 1 46747 3 46745 6 0 1 46747 4 2 23732 8 0 1 46751 1 46740 1 46751 2 11 46749 1 46751 3 46740 1 0 1 46751 4 11 38211 3 0 1 46757 1 46755 1 46757 2 2 46753 1 46757 3 46755 3 0 1 46757 4 2 33210 6 0 1 46769 1 46766 1 46769 2 3 46763 1 46769 3 46766 1 0 1 46769 4 3 46757 0 0 1 46771 1 46769 1 46771 2 2 46767 1 46771 3 46769 2 0 1 46771 4 2 33203 8 0 1 46807 1 46804 1 46807 2 3 46806 1 46807 3 46804 1 0 1 46807 4 3 24365 5 0 1 46811 1 46809 1 46811 2 2 46805 1 46811 3 46809 2 0 1 46811 4 2 41529 0 0 1 46817 1 46814 1 46817 2 3 46811 1 46817 3 46814 1 0 1 46817 4 3 41548 11 0 1 46819 1 46817 1 46819 2 2 46812 1 46819 3 46817 6 0 1 46819 4 2 24486 5 0 1 46829 1 46827 1 46829 2 2 46828 1 46829 3 46827 3 0 1 46829 4 2 29540 3 0 1 46831 1 46828 1 46831 2 3 46829 1 46831 3 46828 4 0 1 46831 4 3 29341 3 0 1 46853 1 46851 1 46853 2 2 46845 1 46853 3 46851 7 0 1 46853 4 2 25849 5 0 1 46861 1 46855 1 46861 2 6 46860 1 46861 3 46855 7 0 1 46861 4 6 35569 22 0 1 46867 1 46865 1 46867 2 2 46863 1 46867 3 46865 5 0 1 46867 4 2 26956 8 0 1 46877 1 46875 1 46877 2 2 46873 1 46877 3 46875 2 0 1 46877 4 2 34515 1 0 1 46889 1 46886 1 46889 2 3 46884 1 46889 3 46886 3 0 1 46889 4 3 33650 2 0 1 46901 1 46890 1 46901 2 11 46899 1 46901 3 46890 4 0 1 46901 4 11 26924 0 0 1 46919 1 46908 1 46919 2 11 46917 1 46919 3 46908 1 0 1 46919 4 11 37138 5 0 1 46933 1 46931 1 46933 2 2 46932 1 46933 3 46931 2 0 1 46933 4 2 36682 3 0 1 46957 1 46952 1 46957 2 5 46956 1 46957 3 46952 1 0 1 46957 4 5 37504 3 0 1 46993 1 46988 1 46993 2 5 46988 1 46993 3 46988 6 0 1 46993 4 5 32806 15 0 1 46997 1 46995 1 46997 2 2 46996 1 46997 3 46995 2 0 1 46997 4 2 40850 4 0 1 47017 1 47010 1 47017 2 7 47010 1 47017 3 47010 3 0 1 47017 4 7 31573 12 0 1 47041 1 47012 1 47041 2 29 47038 1 47041 3 47012 2 0 1 47041 4 29 26628 16 0 1 47051 1 47049 1 47051 2 2 47046 1 47051 3 47049 2 0 1 47051 4 2 40653 3 0 1 47057 1 47054 1 47057 2 3 47056 1 47057 3 47054 4 0 1 47057 4 3 35069 7 0 1 47059 1 47057 1 47059 2 2 47058 1 47059 3 47057 6 0 1 47059 4 2 31564 2 0 1 47087 1 47082 1 47087 2 5 47085 1 47087 3 47082 6 0 1 47087 4 5 47083 3 0 1 47093 1 47091 1 47093 2 2 47089 1 47093 3 47091 3 0 1 47093 4 2 46659 6 0 1 47111 1 47104 1 47111 2 7 47107 1 47111 3 47104 2 0 1 47111 4 7 46497 13 0 1 47119 1 47116 1 47119 2 3 47117 1 47119 3 47116 1 0 1 47119 4 3 45329 3 0 1 47123 1 47121 1 47123 2 2 47119 1 47123 3 47121 2 0 1 47123 4 2 30269 20 0 1 47129 1 47126 1 47129 2 3 47117 1 47129 3 47126 1 0 1 47129 4 3 37567 0 0 1 47137 1 47132 1 47137 2 5 47134 1 47137 3 47132 1 0 1 47137 4 5 41132 23 0 1 47143 1 47137 1 47143 2 6 47140 1 47143 3 47137 1 0 1 47143 4 6 36780 4 0 1 47147 1 47145 1 47147 2 2 47143 1 47147 3 47145 3 0 1 47147 4 2 30463 8 0 1 47149 1 47147 1 47149 2 2 47141 1 47149 3 47147 2 0 1 47149 4 2 43332 0 0 1 47161 1 47144 1 47161 2 17 47156 1 47161 3 47144 2 0 1 47161 4 17 26737 22 0 1 47189 1 47187 1 47189 2 2 47181 1 47189 3 47187 2 0 1 47189 4 2 45094 0 0 1 47207 1 47202 1 47207 2 5 47204 1 47207 3 47202 2 0 1 47207 4 5 35549 4 0 1 47221 1 47215 1 47221 2 6 47217 1 47221 3 47215 7 0 1 47221 4 6 40587 2 0 1 47237 1 47235 1 47237 2 2 47233 1 47237 3 47235 3 0 1 47237 4 2 44006 6 0 1 47251 1 47241 1 47251 2 10 47249 1 47251 3 47241 5 0 1 47251 4 10 31356 0 0 1 47269 1 47263 1 47269 2 6 47261 1 47269 3 47263 2 0 1 47269 4 6 34884 0 0 1 47279 1 47272 1 47279 2 7 47277 1 47279 3 47272 2 0 1 47279 4 7 31867 4 0 1 47287 1 47282 1 47287 2 5 47286 1 47287 3 47282 1 0 1 47287 4 5 30338 5 0 1 47293 1 47287 1 47293 2 6 47292 1 47293 3 47287 2 0 1 47293 4 6 29331 27 0 1 47297 1 47294 1 47297 2 3 47291 1 47297 3 47294 1 0 1 47297 4 3 31326 1 0 1 47303 1 47298 1 47303 2 5 47302 1 47303 3 47298 1 0 1 47303 4 5 24970 4 0 1 47309 1 47307 1 47309 2 2 47300 1 47309 3 47307 5 0 1 47309 4 2 36347 1 0 1 47317 1 47311 1 47317 2 6 47315 1 47317 3 47311 4 0 1 47317 4 6 36456 4 0 1 47339 1 47337 1 47339 2 2 47338 1 47339 3 47337 4 0 1 47339 4 2 47332 8 0 1 47351 1 47338 1 47351 2 13 47349 1 47351 3 47338 1 0 1 47351 4 13 24355 3 0 1 47353 1 47348 1 47353 2 5 47348 1 47353 3 47348 1 0 1 47353 4 5 42696 10 0 1 47363 1 47361 1 47363 2 2 47359 1 47363 3 47361 3 0 1 47363 4 2 36657 7 0 1 47381 1 47379 1 47381 2 2 47380 1 47381 3 47379 5 0 1 47381 4 2 29852 9 0 1 47387 1 47385 1 47387 2 2 47383 1 47387 3 47385 3 0 1 47387 4 2 47010 8 0 1 47389 1 47387 1 47389 2 2 47388 1 47389 3 47387 5 0 1 47389 4 2 23938 9 0 1 47407 1 47404 1 47407 2 3 47406 1 47407 3 47404 3 0 1 47407 4 3 41033 8 0 1 47417 1 47414 1 47417 2 3 47416 1 47417 3 47414 1 0 1 47417 4 3 30547 7 0 1 47419 1 47417 1 47419 2 2 47415 1 47419 3 47417 6 0 1 47419 4 2 23898 8 0 1 47431 1 47419 1 47431 2 12 47428 1 47431 3 47419 6 0 1 47431 4 12 36693 0 0 1 47441 1 47438 1 47441 2 3 47435 1 47441 3 47438 1 0 1 47441 4 3 47429 0 0 1 47459 1 47457 1 47459 2 2 47458 1 47459 3 47457 15 0 1 47459 4 2 24336 6 0 1 47491 1 47489 1 47491 2 2 47490 1 47491 3 47489 5 0 1 47491 4 2 44244 2 0 1 47497 1 47492 1 47497 2 5 47494 1 47497 3 47492 1 0 1 47497 4 5 26516 18 0 1 47501 1 47498 1 47501 2 3 47499 1 47501 3 47498 4 0 1 47501 4 3 47497 4 0 1 47507 1 47505 1 47507 2 2 47503 1 47507 3 47505 2 0 1 47507 4 2 38252 16 0 1 47513 1 47510 1 47513 2 3 47508 1 47513 3 47510 3 0 1 47513 4 3 31881 0 0 1 47521 1 47504 1 47521 2 17 47520 1 47521 3 47504 3 0 1 47521 4 17 29097 20 0 1 47527 1 47524 1 47527 2 3 47526 1 47527 3 47524 3 0 1 47527 4 3 35241 5 0 1 47533 1 47531 1 47533 2 2 47532 1 47533 3 47531 2 0 1 47533 4 2 34111 3 0 1 47543 1 47538 1 47543 2 5 47535 1 47543 3 47538 1 0 1 47543 4 5 24194 3 0 1 47563 1 47561 1 47563 2 2 47562 1 47563 3 47561 2 0 1 47563 4 2 30316 2 0 1 47569 1 47552 1 47569 2 17 47568 1 47569 3 47552 6 0 1 47569 4 17 44979 14 0 1 47581 1 47579 1 47581 2 2 47577 1 47581 3 47579 2 0 1 47581 4 2 29004 12 0 1 47591 1 47580 1 47591 2 11 47590 1 47591 3 47580 8 0 1 47591 4 11 25303 3 0 1 47599 1 47596 1 47599 2 3 47598 1 47599 3 47596 4 0 1 47599 4 3 42246 2 0 1 47609 1 47603 1 47609 2 6 47608 1 47609 3 47603 4 0 1 47609 4 6 42600 7 0 1 47623 1 47620 1 47623 2 3 47621 1 47623 3 47620 1 0 1 47623 4 3 47619 4 0 1 47629 1 47619 1 47629 2 10 47626 1 47629 3 47619 2 0 1 47629 4 10 36643 13 0 1 47639 1 47632 1 47639 2 7 47638 1 47639 3 47632 8 0 1 47639 4 7 26912 2 0 1 47653 1 47640 1 47653 2 13 47642 1 47653 3 47640 3 0 1 47653 4 13 40519 3 0 1 47657 1 47654 1 47657 2 3 47651 1 47657 3 47654 1 0 1 47657 4 3 28471 9 0 1 47659 1 47657 1 47659 2 2 47658 1 47659 3 47657 6 0 1 47659 4 2 29906 7 0 1 47681 1 47678 1 47681 2 3 47680 1 47681 3 47678 11 0 1 47681 4 3 26764 4 0 1 47699 1 47697 1 47699 2 2 47694 1 47699 3 47697 2 0 1 47699 4 2 35869 3 0 1 47701 1 47699 1 47701 2 2 47700 1 47701 3 47699 6 0 1 47701 4 2 40941 7 0 1 47711 1 47700 1 47711 2 11 47709 1 47711 3 47700 2 0 1 47711 4 11 28539 3 0 1 47713 1 47703 1 47713 2 10 47708 1 47713 3 47703 4 0 1 47713 4 10 31546 10 0 1 47717 1 47715 1 47717 2 2 47716 1 47717 3 47715 2 0 1 47717 4 2 43442 3 0 1 47737 1 47732 1 47737 2 5 47734 1 47737 3 47732 2 0 1 47737 4 5 37040 23 0 1 47741 1 47738 1 47741 2 3 47733 1 47741 3 47738 1 0 1 47741 4 3 28355 11 0 1 47743 1 47740 1 47743 2 3 47741 1 47743 3 47740 1 0 1 47743 4 3 47739 4 0 1 47777 1 47774 1 47777 2 3 47769 1 47777 3 47774 3 0 1 47777 4 3 46327 2 0 1 47779 1 47776 1 47779 2 3 47778 1 47779 3 47776 3 0 1 47779 4 3 44214 2 0 1 47791 1 47784 1 47791 2 7 47778 1 47791 3 47784 3 0 1 47791 4 7 25128 1 0 1 47797 1 47792 1 47797 2 5 47796 1 47797 3 47792 2 0 1 47797 4 5 38175 6 0 1 47807 1 47802 1 47807 2 5 47806 1 47807 3 47802 5 0 1 47807 4 5 32752 3 0 1 47809 1 47802 1 47809 2 7 47800 1 47809 3 47802 4 0 1 47809 4 7 36600 16 0 1 47819 1 47817 1 47819 2 2 47813 1 47819 3 47817 2 0 1 47819 4 2 29004 0 0 1 47837 1 47835 1 47837 2 2 47831 1 47837 3 47835 2 0 1 47837 4 2 26959 1 0 1 47843 1 47841 1 47843 2 2 47842 1 47843 3 47841 2 0 1 47843 4 2 35977 2 0 1 47857 1 47850 1 47857 2 7 47854 1 47857 3 47850 2 0 1 47857 4 7 24323 8 0 1 47869 1 47867 1 47869 2 2 47868 1 47869 3 47867 6 0 1 47869 4 2 36099 3 0 1 47881 1 47852 1 47881 2 29 47876 1 47881 3 47852 2 0 1 47881 4 29 46952 18 0 1 47903 1 47896 1 47903 2 7 47902 1 47903 3 47896 2 0 1 47903 4 7 36964 2 0 1 47911 1 47908 1 47911 2 3 47910 1 47911 3 47908 1 0 1 47911 4 3 44831 3 0 1 47917 1 47912 1 47917 2 5 47916 1 47917 3 47912 2 0 1 47917 4 5 41117 6 0 1 47933 1 47931 1 47933 2 2 47929 1 47933 3 47931 3 0 1 47933 4 2 46754 6 0 1 47939 1 47937 1 47939 2 2 47938 1 47939 3 47937 3 0 1 47939 4 2 38673 2 0 1 47947 1 47945 1 47947 2 2 47943 1 47947 3 47945 5 0 1 47947 4 2 38585 13 0 1 47951 1 47944 1 47951 2 7 47949 1 47951 3 47944 5 0 1 47951 4 7 35366 5 0 1 47963 1 47961 1 47963 2 2 47962 1 47963 3 47961 2 0 1 47963 4 2 28626 4 0 1 47969 1 47966 1 47969 2 3 47963 1 47969 3 47966 5 0 1 47969 4 3 47957 0 0 1 47977 1 47970 1 47977 2 7 47970 1 47977 3 47970 1 0 1 47977 4 7 35515 12 0 1 47981 1 47979 1 47981 2 2 47974 1 47981 3 47979 3 0 1 47981 4 2 27256 14 0 1 48017 1 48014 1 48017 2 3 48016 1 48017 3 48014 3 0 1 48017 4 3 39230 4 0 1 48023 1 48018 1 48023 2 5 48006 1 48023 3 48018 5 0 1 48023 4 5 39800 12 0 1 48029 1 48027 1 48029 2 2 48021 1 48029 3 48027 11 0 1 48029 4 2 40222 0 0 1 48049 1 48032 1 48049 2 17 48046 1 48049 3 48032 1 0 1 48049 4 17 30905 20 0 1 48073 1 48068 1 48073 2 5 48072 1 48073 3 48068 3 0 1 48073 4 5 31604 6 0 1 48079 1 48073 1 48079 2 6 48077 1 48079 3 48073 3 0 1 48079 4 6 31403 4 0 1 48091 1 48084 1 48091 2 7 48089 1 48091 3 48084 1 0 1 48091 4 7 30351 6 0 1 48109 1 48107 1 48109 2 2 48105 1 48109 3 48107 6 0 1 48109 4 2 41128 11 0 1 48119 1 48112 1 48119 2 7 48117 1 48119 3 48112 3 0 1 48119 4 7 41509 4 0 1 48121 1 48108 1 48121 2 13 48120 1 48121 3 48108 8 0 1 48121 4 13 28355 8 0 1 48131 1 48125 1 48131 2 6 48129 1 48131 3 48125 3 0 1 48131 4 6 38135 5 0 1 48157 1 48152 1 48157 2 5 48154 1 48157 3 48152 2 0 1 48157 4 5 41490 1 0 1 48163 1 48160 1 48163 2 3 48158 1 48163 3 48160 8 0 1 48163 4 3 34731 3 0 1 48179 1 48173 1 48179 2 6 48177 1 48179 3 48173 3 0 1 48179 4 6 44807 9 0 1 48187 1 48185 1 48187 2 2 48186 1 48187 3 48185 6 0 1 48187 4 2 40059 2 0 1 48193 1 48186 1 48193 2 7 48186 1 48193 3 48186 1 0 1 48193 4 7 30606 12 0 1 48197 1 48195 1 48197 2 2 48193 1 48197 3 48195 3 0 1 48197 4 2 34515 7 0 1 48221 1 48219 1 48221 2 2 48215 1 48221 3 48219 9 0 1 48221 4 2 47059 4 0 1 48239 1 48232 1 48239 2 7 48232 1 48239 3 48232 2 0 1 48239 4 7 33840 8 0 1 48247 1 48244 1 48247 2 3 48245 1 48247 3 48244 1 0 1 48247 4 3 32980 6 0 1 48259 1 48257 1 48259 2 2 48255 1 48259 3 48257 2 0 1 48259 4 2 38080 8 0 1 48271 1 48265 1 48271 2 6 48270 1 48271 3 48265 2 0 1 48271 4 6 40466 2 0 1 48281 1 48278 1 48281 2 3 48280 1 48281 3 48278 12 0 1 48281 4 3 43232 4 0 1 48299 1 48297 1 48299 2 2 48295 1 48299 3 48297 3 0 1 48299 4 2 42653 7 0 1 48311 1 48304 1 48311 2 7 48310 1 48311 3 48304 1 0 1 48311 4 7 48302 4 0 1 48313 1 48308 1 48313 2 5 48312 1 48313 3 48308 1 0 1 48313 4 5 48002 6 0 1 48337 1 48327 1 48337 2 10 48332 1 48337 3 48327 3 0 1 48337 4 10 34674 10 0 1 48341 1 48338 1 48341 2 3 48340 1 48341 3 48338 3 0 1 48341 4 3 29790 3 0 1 48353 1 48350 1 48353 2 3 48352 1 48353 3 48350 3 0 1 48353 4 3 25766 7 0 1 48371 1 48369 1 48371 2 2 48366 1 48371 3 48369 7 0 1 48371 4 2 33067 3 0 1 48383 1 48378 1 48383 2 5 48381 1 48383 3 48378 7 0 1 48383 4 5 48379 3 0 1 48397 1 48392 1 48397 2 5 48394 1 48397 3 48392 2 0 1 48397 4 5 39035 10 0 1 48407 1 48402 1 48407 2 5 48406 1 48407 3 48402 1 0 1 48407 4 5 26131 2 0 1 48409 1 48392 1 48409 2 17 48398 1 48409 3 48392 1 0 1 48409 4 17 39919 28 0 1 48413 1 48411 1 48413 2 2 48409 1 48413 3 48411 3 0 1 48413 4 2 46445 6 0 1 48437 1 48435 1 48437 2 2 48433 1 48437 3 48435 7 0 1 48437 4 2 29367 16 0 1 48449 1 48446 1 48449 2 3 48444 1 48449 3 48446 3 0 1 48449 4 3 46270 2 0 1 48463 1 48458 1 48463 2 5 48462 1 48463 3 48458 5 0 1 48463 4 5 44000 5 0 1 48473 1 48470 1 48473 2 3 48472 1 48473 3 48470 7 0 1 48473 4 3 42834 4 0 1 48479 1 48472 1 48479 2 7 48478 1 48479 3 48472 9 0 1 48479 4 7 29312 2 0 1 48481 1 48464 1 48481 2 17 48478 1 48481 3 48464 2 0 1 48481 4 17 33727 17 0 1 48487 1 48482 1 48487 2 5 48486 1 48487 3 48482 1 0 1 48487 4 5 47077 8 0 1 48491 1 48489 1 48491 2 2 48487 1 48491 3 48489 3 0 1 48491 4 2 34981 7 0 1 48497 1 48494 1 48497 2 3 48492 1 48497 3 48494 3 0 1 48497 4 3 44812 0 0 1 48523 1 48520 1 48523 2 3 48522 1 48523 3 48520 4 0 1 48523 4 3 40596 5 0 1 48527 1 48522 1 48527 2 5 48525 1 48527 3 48522 3 0 1 48527 4 5 34075 8 0 1 48533 1 48531 1 48533 2 2 48529 1 48533 3 48531 7 0 1 48533 4 2 31450 9 0 1 48539 1 48537 1 48539 2 2 48535 1 48539 3 48537 2 0 1 48539 4 2 42777 8 0 1 48541 1 48539 1 48541 2 2 48540 1 48541 3 48539 5 0 1 48541 4 2 37897 7 0 1 48563 1 48561 1 48563 2 2 48557 1 48563 3 48561 5 0 1 48563 4 2 47832 0 0 1 48571 1 48569 1 48571 2 2 48570 1 48571 3 48569 6 0 1 48571 4 2 36188 7 0 1 48589 1 48579 1 48589 2 10 48588 1 48589 3 48579 10 0 1 48589 4 10 44652 3 0 1 48593 1 48590 1 48593 2 3 48587 1 48593 3 48590 4 0 1 48593 4 3 45796 17 0 1 48611 1 48609 1 48611 2 2 48610 1 48611 3 48609 7 0 1 48611 4 2 32878 12 0 1 48619 1 48617 1 48619 2 2 48613 1 48619 3 48617 4 0 1 48619 4 2 26111 3 0 1 48623 1 48618 1 48623 2 5 48615 1 48623 3 48618 3 0 1 48623 4 5 47859 3 0 1 48647 1 48642 1 48647 2 5 48642 1 48647 3 48642 6 0 1 48647 4 5 46056 6 0 1 48649 1 48642 1 48649 2 7 48640 1 48649 3 48642 2 0 1 48649 4 7 37237 2 0 1 48661 1 48659 1 48661 2 2 48657 1 48661 3 48659 7 0 1 48661 4 2 36619 6 0 1 48673 1 48658 1 48673 2 15 48668 1 48673 3 48658 2 0 1 48673 4 15 31069 0 0 1 48677 1 48675 1 48677 2 2 48676 1 48677 3 48675 3 0 1 48677 4 2 40064 4 0 1 48679 1 48676 1 48679 2 3 48677 1 48679 3 48676 4 0 1 48679 4 3 43172 6 0 1 48731 1 48725 1 48731 2 6 48730 1 48731 3 48725 1 0 1 48731 4 6 30965 4 0 1 48733 1 48731 1 48733 2 2 48729 1 48733 3 48731 6 0 1 48733 4 2 38665 6 0 1 48751 1 48748 1 48751 2 3 48749 1 48751 3 48748 1 0 1 48751 4 3 48747 4 0 1 48757 1 48755 1 48757 2 2 48753 1 48757 3 48755 5 0 1 48757 4 2 45082 12 0 1 48761 1 48758 1 48761 2 3 48756 1 48761 3 48758 4 0 1 48761 4 3 30253 2 0 1 48767 1 48762 1 48767 2 5 48766 1 48767 3 48762 3 0 1 48767 4 5 38128 7 0 1 48779 1 48777 1 48779 2 2 48775 1 48779 3 48777 11 0 1 48779 4 2 41865 7 0 1 48781 1 48775 1 48781 2 6 48780 1 48781 3 48775 1 0 1 48781 4 6 43730 7 0 1 48787 1 48785 1 48787 2 2 48783 1 48787 3 48785 5 0 1 48787 4 2 33906 8 0 1 48799 1 48796 1 48799 2 3 48797 1 48799 3 48796 6 0 1 48799 4 3 37818 6 0 1 48809 1 48806 1 48809 2 3 48803 1 48809 3 48806 3 0 1 48809 4 3 48797 0 0 1 48817 1 48812 1 48817 2 5 48814 1 48817 3 48812 1 0 1 48817 4 5 45035 16 0 1 48821 1 48819 1 48821 2 2 48820 1 48821 3 48819 5 0 1 48821 4 2 37862 4 0 1 48823 1 48818 1 48823 2 5 48822 1 48823 3 48818 2 0 1 48823 4 5 43255 2 0 1 48847 1 48844 1 48847 2 3 48846 1 48847 3 48844 4 0 1 48847 4 3 29183 5 0 1 48857 1 48854 1 48857 2 3 48851 1 48857 3 48854 5 0 1 48857 4 3 32875 9 0 1 48859 1 48857 1 48859 2 2 48855 1 48859 3 48857 4 0 1 48859 4 2 44505 1 0 1 48869 1 48867 1 48869 2 2 48864 1 48869 3 48867 7 0 1 48869 4 2 42699 8 0 1 48871 1 48868 1 48871 2 3 48869 1 48871 3 48868 6 0 1 48871 4 3 24728 6 0 1 48883 1 48881 1 48883 2 2 48879 1 48883 3 48881 4 0 1 48883 4 2 38356 8 0 1 48889 1 48855 1 48889 2 34 48872 1 48889 3 48855 2 0 1 48889 4 34 46792 34 0 1 48907 1 48905 1 48907 2 2 48906 1 48907 3 48905 2 0 1 48907 4 2 46136 7 0 1 48947 1 48945 1 48947 2 2 48946 1 48947 3 48945 2 0 1 48947 4 2 48940 8 0 1 48953 1 48950 1 48953 2 3 48948 1 48953 3 48950 4 0 1 48953 4 3 40344 2 0 1 48973 1 48968 1 48973 2 5 48972 1 48973 3 48968 8 0 1 48973 4 5 45963 6 0 1 48989 1 48987 1 48989 2 2 48988 1 48989 3 48987 3 0 1 48989 4 2 38762 3 0 1 48991 1 48985 1 48991 2 6 48989 1 48991 3 48985 3 0 1 48991 4 6 38716 3 0 1 49003 1 48990 1 49003 2 13 49000 1 49003 3 48990 2 0 1 49003 4 13 40738 4 0 1 49009 1 48990 1 49009 2 19 48996 1 49009 3 48990 6 0 1 49009 4 19 25010 32 0 1 49019 1 49017 1 49019 2 2 49015 1 49019 3 49017 3 0 1 49019 4 2 45449 9 0 1 49031 1 49018 1 49031 2 13 49022 1 49031 3 49018 2 0 1 49031 4 13 46127 13 0 1 49033 1 49023 1 49033 2 10 49030 1 49033 3 49023 5 0 1 49033 4 10 40636 8 0 1 49037 1 49035 1 49037 2 2 49033 1 49037 3 49035 3 0 1 49037 4 2 44789 18 0 1 49043 1 49041 1 49043 2 2 49039 1 49043 3 49041 3 0 1 49043 4 2 43188 8 0 1 49057 1 49052 1 49057 2 5 49056 1 49057 3 49052 1 0 1 49057 4 5 39309 6 0 1 49069 1 49067 1 49069 2 2 49068 1 49069 3 49067 4 0 1 49069 4 2 32044 7 0 1 49081 1 49070 1 49081 2 11 49080 1 49081 3 49070 2 0 1 49081 4 11 34628 12 0 1 49103 1 49098 1 49103 2 5 49098 1 49103 3 49098 9 0 1 49103 4 5 37207 11 0 1 49109 1 49107 1 49109 2 2 49105 1 49109 3 49107 5 0 1 49109 4 2 33641 7 0 1 49117 1 49115 1 49117 2 2 49116 1 49117 3 49115 6 0 1 49117 4 2 25424 9 0 1 49121 1 49118 1 49121 2 3 49120 1 49121 3 49118 3 0 1 49121 4 3 43733 4 0 1 49123 1 49121 1 49123 2 2 49119 1 49123 3 49121 4 0 1 49123 4 2 37322 17 0 1 49139 1 49137 1 49139 2 2 49138 1 49139 3 49137 3 0 1 49139 4 2 38377 4 0 1 49157 1 49155 1 49157 2 2 49152 1 49157 3 49155 7 0 1 49157 4 2 34802 12 0 1 49169 1 49166 1 49169 2 3 49168 1 49169 3 49166 1 0 1 49169 4 3 35300 4 0 1 49171 1 49169 1 49171 2 2 49170 1 49171 3 49169 4 0 1 49171 4 2 33733 2 0 1 49177 1 49172 1 49177 2 5 49174 1 49177 3 49172 1 0 1 49177 4 5 47757 16 0 1 49193 1 49190 1 49193 2 3 49186 1 49193 3 49190 12 0 1 49193 4 3 46513 1 0 1 49199 1 49186 1 49199 2 13 49196 1 49199 3 49186 2 0 1 49199 4 13 45713 4 0 1 49201 1 49194 1 49201 2 7 49198 1 49201 3 49194 3 0 1 49201 4 7 33068 24 0 1 49207 1 49204 1 49207 2 3 49205 1 49207 3 49204 5 0 1 49207 4 3 45887 6 0 1 49211 1 49209 1 49211 2 2 49207 1 49211 3 49209 3 0 1 49211 4 2 32254 7 0 1 49223 1 49218 1 49223 2 5 49222 1 49223 3 49218 3 0 1 49223 4 5 38606 2 0 1 49253 1 49251 1 49253 2 2 49249 1 49253 3 49251 3 0 1 49253 4 2 43835 12 0 1 49261 1 49259 1 49261 2 2 49257 1 49261 3 49259 2 0 1 49261 4 2 46480 6 0 1 49277 1 49275 1 49277 2 2 49273 1 49277 3 49275 3 0 1 49277 4 2 26712 6 0 1 49279 1 49276 1 49279 2 3 49272 1 49279 3 49276 3 0 1 49279 4 3 43012 9 0 1 49297 1 49292 1 49297 2 5 49294 1 49297 3 49292 1 0 1 49297 4 5 36111 10 0 1 49307 1 49305 1 49307 2 2 49293 1 49307 3 49305 3 0 1 49307 4 2 45416 0 0 1 49331 1 49329 1 49331 2 2 49327 1 49331 3 49329 2 0 1 49331 4 2 39900 8 0 1 49333 1 49331 1 49333 2 2 49329 1 49333 3 49331 6 0 1 49333 4 2 28444 12 0 1 49339 1 49328 1 49339 2 11 49330 1 49339 3 49328 1 0 1 49339 4 11 43354 6 0 1 49363 1 49361 1 49363 2 2 49362 1 49363 3 49361 2 0 1 49363 4 2 44925 2 0 1 49367 1 49362 1 49367 2 5 49365 1 49367 3 49362 6 0 1 49367 4 5 39079 8 0 1 49369 1 49356 1 49369 2 13 49366 1 49369 3 49356 1 0 1 49369 4 13 44953 10 0 1 49391 1 49380 1 49391 2 11 49390 1 49391 3 49380 1 0 1 49391 4 11 28511 2 0 1 49393 1 49388 1 49393 2 5 49392 1 49393 3 49388 2 0 1 49393 4 5 25335 11 0 1 49409 1 49406 1 49409 2 3 49403 1 49409 3 49406 1 0 1 49409 4 3 49397 0 0 1 49411 1 49409 1 49411 2 2 49410 1 49411 3 49409 4 0 1 49411 4 2 43356 10 0 1 49417 1 49412 1 49417 2 5 49412 1 49417 3 49412 1 0 1 49417 4 5 38659 15 0 1 49429 1 49427 1 49429 2 2 49425 1 49429 3 49427 4 0 1 49429 4 2 27773 6 0 1 49433 1 49430 1 49433 2 3 49427 1 49433 3 49430 1 0 1 49433 4 3 26127 13 0 1 49451 1 49441 1 49451 2 10 49450 1 49451 3 49441 5 0 1 49451 4 10 28037 8 0 1 49459 1 49456 1 49459 2 3 49451 1 49459 3 49456 5 0 1 49459 4 3 30359 0 0 1 49463 1 49458 1 49463 2 5 49461 1 49463 3 49458 3 0 1 49463 4 5 32467 8 0 1 49477 1 49466 1 49477 2 11 49476 1 49477 3 49466 1 0 1 49477 4 11 33940 3 0 1 49481 1 49478 1 49481 2 3 49475 1 49481 3 49478 1 0 1 49481 4 3 49469 0 0 1 49499 1 49497 1 49499 2 2 49495 1 49499 3 49497 3 0 1 49499 4 2 27389 7 0 1 49523 1 49521 1 49523 2 2 49522 1 49523 3 49521 2 0 1 49523 4 2 44113 2 0 1 49529 1 49526 1 49529 2 3 49528 1 49529 3 49526 5 0 1 49529 4 3 44829 7 0 1 49531 1 49521 1 49531 2 10 49529 1 49531 3 49521 5 0 1 49531 4 10 49513 11 0 1 49537 1 49527 1 49537 2 10 49536 1 49537 3 49527 2 0 1 49537 4 10 31783 16 0 1 49547 1 49545 1 49547 2 2 49543 1 49547 3 49545 3 0 1 49547 4 2 27116 7 0 1 49549 1 49543 1 49549 2 6 49548 1 49549 3 49543 4 0 1 49549 4 6 48251 7 0 1 49559 1 49548 1 49559 2 11 49557 1 49559 3 49548 7 0 1 49559 4 11 33849 9 0 1 49597 1 49592 1 49597 2 5 49592 1 49597 3 49592 2 0 1 49597 4 5 40614 11 0 1 49603 1 49600 1 49603 2 3 49598 1 49603 3 49600 1 0 1 49603 4 3 29825 3 0 1 49613 1 49611 1 49613 2 2 49609 1 49613 3 49611 3 0 1 49613 4 2 48353 6 0 1 49627 1 49624 1 49627 2 3 49626 1 49627 3 49624 4 0 1 49627 4 3 30852 5 0 1 49633 1 49628 1 49633 2 5 49628 1 49633 3 49628 5 0 1 49633 4 5 27663 10 0 1 49639 1 49636 1 49639 2 3 49637 1 49639 3 49636 13 0 1 49639 4 3 32045 6 0 1 49663 1 49660 1 49663 2 3 49661 1 49663 3 49660 1 0 1 49663 4 3 49659 4 0 1 49667 1 49665 1 49667 2 2 49663 1 49667 3 49665 3 0 1 49667 4 2 35014 8 0 1 49669 1 49667 1 49669 2 2 49665 1 49669 3 49667 2 0 1 49669 4 2 40306 6 0 1 49681 1 49664 1 49681 2 17 49680 1 49681 3 49664 2 0 1 49681 4 17 26405 14 0 1 49697 1 49694 1 49697 2 3 49692 1 49697 3 49694 4 0 1 49697 4 3 32921 0 0 1 49711 1 49704 1 49711 2 7 49702 1 49711 3 49704 1 0 1 49711 4 7 28138 10 0 1 49727 1 49722 1 49727 2 5 49725 1 49727 3 49722 1 0 1 49727 4 5 49723 3 0 1 49739 1 49737 1 49739 2 2 49732 1 49739 3 49737 3 0 1 49739 4 2 44053 1 0 1 49741 1 49739 1 49741 2 2 49740 1 49741 3 49739 5 0 1 49741 4 2 48212 3 0 1 49747 1 49744 1 49747 2 3 49740 1 49747 3 49744 4 0 1 49747 4 3 34505 5 0 1 49757 1 49755 1 49757 2 2 49753 1 49757 3 49755 3 0 1 49757 4 2 29424 7 0 1 49783 1 49780 1 49783 2 3 49782 1 49783 3 49780 13 0 1 49783 4 3 40233 5 0 1 49787 1 49785 1 49787 2 2 49783 1 49787 3 49785 2 0 1 49787 4 2 45577 13 0 1 49789 1 49783 1 49789 2 6 49788 1 49789 3 49783 8 0 1 49789 4 6 25766 11 0 1 49801 1 49788 1 49801 2 13 49798 1 49801 3 49788 1 0 1 49801 4 13 31480 10 0 1 49807 1 49804 1 49807 2 3 49806 1 49807 3 49804 4 0 1 49807 4 3 32124 14 0 1 49811 1 49805 1 49811 2 6 49809 1 49811 3 49805 1 0 1 49811 4 6 34569 5 0 1 49823 1 49818 1 49823 2 5 49818 1 49823 3 49818 1 0 1 49823 4 5 28121 8 0 1 49831 1 49819 1 49831 2 12 49830 1 49831 3 49819 1 0 1 49831 4 12 28689 3 0 1 49843 1 49841 1 49843 2 2 49842 1 49843 3 49841 6 0 1 49843 4 2 26448 7 0 1 49853 1 49851 1 49853 2 2 49852 1 49853 3 49851 2 0 1 49853 4 2 27228 4 0 1 49871 1 49854 1 49871 2 17 49869 1 49871 3 49854 1 0 1 49871 4 17 49863 3 0 1 49877 1 49875 1 49877 2 2 49873 1 49877 3 49875 7 0 1 49877 4 2 37283 7 0 1 49891 1 49889 1 49891 2 2 49887 1 49891 3 49889 2 0 1 49891 4 2 38705 8 0 1 49919 1 49912 1 49919 2 7 49918 1 49919 3 49912 1 0 1 49919 4 7 38692 3 0 1 49921 1 49898 1 49921 2 23 49917 1 49921 3 49898 2 0 1 49921 4 23 49883 23 0 1 49927 1 49924 1 49927 2 3 49925 1 49927 3 49924 1 0 1 49927 4 3 49919 10 0 1 49937 1 49934 1 49937 2 3 49931 1 49937 3 49934 1 0 1 49937 4 3 39765 1 0 1 49939 1 49932 1 49939 2 7 49937 1 49939 3 49932 3 0 1 49939 4 7 45043 6 0 1 49943 1 49938 1 49943 2 5 49941 1 49943 3 49938 7 0 1 49943 4 5 49939 3 0 1 49957 1 49952 1 49957 2 5 49954 1 49957 3 49952 2 0 1 49957 4 5 38964 9 0 1 49991 1 49984 1 49991 2 7 49990 1 49991 3 49984 11 0 1 49991 4 7 34536 2 0 1 49993 1 49988 1 49993 2 5 49988 1 49993 3 49988 1 0 1 49993 4 5 36062 18 0 1 49999 1 49996 1 49999 2 3 49993 1 49999 3 49996 5 0 1 49999 4 3 36978 13 0 1 50021 1 50019 1 50021 2 2 50020 1 50021 3 50019 5 0 1 50021 4 2 50014 8 0 1 50023 1 50020 1 50023 2 3 50022 1 50023 3 50020 3 0 1 50023 4 3 39725 5 0 1 50033 1 50028 1 50033 2 5 50026 1 50033 3 50028 3 0 1 50033 4 5 35784 4 0 1 50047 1 50041 1 50047 2 6 50046 1 50047 3 50041 4 0 1 50047 4 6 39163 10 0 1 50051 1 50049 1 50051 2 2 50046 1 50051 3 50049 2 0 1 50051 4 2 27862 3 0 1 50053 1 50051 1 50053 2 2 50052 1 50053 3 50051 2 0 1 50053 4 2 37338 6 0 1 50069 1 50067 1 50069 2 2 50068 1 50069 3 50067 3 0 1 50069 4 2 34473 3 0 1 50077 1 50075 1 50077 2 2 50076 1 50077 3 50075 6 0 1 50077 4 2 45399 6 0 1 50087 1 50082 1 50087 2 5 50086 1 50087 3 50082 5 0 1 50087 4 5 40006 3 0 1 50093 1 50091 1 50093 2 2 50088 1 50093 3 50091 3 0 1 50093 4 2 33148 8 0 1 50101 1 50099 1 50101 2 2 50097 1 50101 3 50099 4 0 1 50101 4 2 49294 12 0 1 50111 1 50094 1 50111 2 17 50109 1 50111 3 50094 4 0 1 50111 4 17 50103 3 0 1 50119 1 50116 1 50119 2 3 50117 1 50119 3 50116 1 0 1 50119 4 3 50115 4 0 1 50123 1 50121 1 50123 2 2 50122 1 50123 3 50121 4 0 1 50123 4 2 29841 10 0 1 50129 1 50126 1 50129 2 3 50128 1 50129 3 50126 1 0 1 50129 4 3 43702 4 0 1 50131 1 50129 1 50131 2 2 50127 1 50131 3 50129 2 0 1 50131 4 2 32113 8 0 1 50147 1 50145 1 50147 2 2 50146 1 50147 3 50145 10 0 1 50147 4 2 29812 10 0 1 50153 1 50150 1 50153 2 3 50147 1 50153 3 50150 11 0 1 50153 4 3 39996 9 0 1 50159 1 50152 1 50159 2 7 50158 1 50159 3 50152 1 0 1 50159 4 7 45366 2 0 1 50177 1 50174 1 50177 2 3 50176 1 50177 3 50174 4 0 1 50177 4 3 26300 6 0 1 50207 1 50202 1 50207 2 5 50205 1 50207 3 50202 1 0 1 50207 4 5 37343 16 0 1 50221 1 50208 1 50221 2 13 50220 1 50221 3 50208 3 0 1 50221 4 13 45023 7 0 1 50227 1 50225 1 50227 2 2 50223 1 50227 3 50225 6 0 1 50227 4 2 37029 8 0 1 50231 1 50220 1 50231 2 11 50228 1 50231 3 50220 2 0 1 50231 4 11 27812 8 0 1 50261 1 50258 1 50261 2 3 50259 1 50261 3 50258 7 0 1 50261 4 3 50253 10 0 1 50263 1 50260 1 50263 2 3 50261 1 50263 3 50260 1 0 1 50263 4 3 48726 3 0 1 50273 1 50270 1 50273 2 3 50267 1 50273 3 50270 3 0 1 50273 4 3 41061 1 0 1 50287 1 50284 1 50287 2 3 50286 1 50287 3 50284 3 0 1 50287 4 3 45318 5 0 1 50291 1 50289 1 50291 2 2 50290 1 50291 3 50289 3 0 1 50291 4 2 43956 2 0 1 50311 1 50308 1 50311 2 3 50310 1 50311 3 50308 3 0 1 50311 4 3 25819 2 0 1 50321 1 50315 1 50321 2 6 50312 1 50321 3 50315 2 0 1 50321 4 6 49819 2 0 1 50329 1 50322 1 50329 2 7 50322 1 50329 3 50322 7 0 1 50329 4 7 47892 0 0 1 50333 1 50331 1 50333 2 2 50332 1 50333 3 50331 3 0 1 50333 4 2 31976 3 0 1 50341 1 50339 1 50341 2 2 50337 1 50341 3 50339 2 0 1 50341 4 2 42673 12 0 1 50359 1 50356 1 50359 2 3 50357 1 50359 3 50356 1 0 1 50359 4 3 50355 4 0 1 50363 1 50361 1 50363 2 2 50362 1 50363 3 50361 2 0 1 50363 4 2 34649 2 0 1 50377 1 50372 1 50377 2 5 50376 1 50377 3 50372 1 0 1 50377 4 5 44870 6 0 1 50383 1 50380 1 50383 2 3 50381 1 50383 3 50380 1 0 1 50383 4 3 32021 3 0 1 50387 1 50385 1 50387 2 2 50381 1 50387 3 50385 4 0 1 50387 4 2 30105 4 0 1 50411 1 50409 1 50411 2 2 50406 1 50411 3 50409 4 0 1 50411 4 2 49861 3 0 1 50417 1 50414 1 50417 2 3 50411 1 50417 3 50414 5 0 1 50417 4 3 47117 9 0 1 50423 1 50418 1 50423 2 5 50421 1 50423 3 50418 2 0 1 50423 4 5 37270 8 0 1 50441 1 50435 1 50441 2 6 50431 1 50441 3 50435 2 0 1 50441 4 6 25866 3 0 1 50459 1 50457 1 50459 2 2 50458 1 50459 3 50457 3 0 1 50459 4 2 42533 4 0 1 50461 1 50454 1 50461 2 7 50459 1 50461 3 50454 1 0 1 50461 4 7 41484 15 0 1 50497 1 50492 1 50497 2 5 50496 1 50497 3 50492 2 0 1 50497 4 5 36424 6 0 1 50503 1 50498 1 50503 2 5 50501 1 50503 3 50498 2 0 1 50503 4 5 34429 10 0 1 50513 1 50510 1 50513 2 3 50508 1 50513 3 50510 3 0 1 50513 4 3 30427 0 0 1 50527 1 50524 1 50527 2 3 50525 1 50527 3 50524 1 0 1 50527 4 3 50519 10 0 1 50539 1 50537 1 50539 2 2 50535 1 50539 3 50537 5 0 1 50539 4 2 38391 1 0 1 50543 1 50538 1 50543 2 5 50542 1 50543 3 50538 5 0 1 50543 4 5 35497 2 0 1 50549 1 50547 1 50549 2 2 50541 1 50549 3 50547 8 0 1 50549 4 2 27326 0 0 1 50551 1 50548 1 50551 2 3 50550 1 50551 3 50548 4 0 1 50551 4 3 50233 3 0 1 50581 1 50579 1 50581 2 2 50580 1 50581 3 50579 4 0 1 50581 4 2 39499 9 0 1 50587 1 50573 1 50587 2 14 50586 1 50587 3 50573 6 0 1 50587 4 14 41596 2 0 1 50591 1 50584 1 50591 2 7 50589 1 50591 3 50584 1 0 1 50591 4 7 34087 5 0 1 50593 1 50588 1 50593 2 5 50592 1 50593 3 50588 5 0 1 50593 4 5 26449 11 0 1 50599 1 50596 1 50599 2 3 50598 1 50599 3 50596 3 0 1 50599 4 3 41000 3 0 1 50627 1 50625 1 50627 2 2 50623 1 50627 3 50625 2 0 1 50627 4 2 25979 16 0 1 50647 1 50644 1 50647 2 3 50645 1 50647 3 50644 5 0 1 50647 4 3 26551 3 0 1 50651 1 50649 1 50651 2 2 50650 1 50651 3 50649 3 0 1 50651 4 2 41952 2 0 1 50671 1 50660 1 50671 2 11 50669 1 50671 3 50660 1 0 1 50671 4 11 26891 3 0 1 50683 1 50681 1 50683 2 2 50682 1 50683 3 50681 2 0 1 50683 4 2 50676 8 0 1 50707 1 50704 1 50707 2 3 50706 1 50707 3 50704 1 0 1 50707 4 3 45182 2 0 1 50723 1 50721 1 50723 2 2 50718 1 50723 3 50721 5 0 1 50723 4 2 49068 6 0 1 50741 1 50739 1 50741 2 2 50740 1 50741 3 50739 7 0 1 50741 4 2 28510 4 0 1 50753 1 50750 1 50753 2 3 50752 1 50753 3 50750 1 0 1 50753 4 3 39774 7 0 1 50767 1 50762 1 50767 2 5 50766 1 50767 3 50762 10 0 1 50767 4 5 38749 12 0 1 50773 1 50762 1 50773 2 11 50772 1 50773 3 50762 1 0 1 50773 4 11 27150 3 0 1 50777 1 50774 1 50777 2 3 50771 1 50777 3 50774 5 0 1 50777 4 3 36989 12 0 1 50789 1 50787 1 50789 2 2 50785 1 50789 3 50787 2 0 1 50789 4 2 40054 6 0 1 50821 1 50819 1 50821 2 2 50817 1 50821 3 50819 4 0 1 50821 4 2 41439 10 0 1 50833 1 50826 1 50833 2 7 50826 1 50833 3 50826 7 0 1 50833 4 7 30908 12 0 1 50839 1 50836 1 50839 2 3 50838 1 50839 3 50836 3 0 1 50839 4 3 30653 2 0 1 50849 1 50846 1 50849 2 3 50844 1 50849 3 50846 7 0 1 50849 4 3 48200 2 0 1 50857 1 50838 1 50857 2 19 50853 1 50857 3 50838 7 0 1 50857 4 19 32990 9 0 1 50867 1 50865 1 50867 2 2 50866 1 50867 3 50865 2 0 1 50867 4 2 40928 2 0 1 50873 1 50870 1 50873 2 3 50866 1 50873 3 50870 5 0 1 50873 4 3 29597 1 0 1 50891 1 50889 1 50891 2 2 50885 1 50891 3 50889 9 0 1 50891 4 2 47150 4 0 1 50893 1 50891 1 50893 2 2 50892 1 50893 3 50891 2 0 1 50893 4 2 43160 3 0 1 50909 1 50907 1 50909 2 2 50908 1 50909 3 50907 3 0 1 50909 4 2 50902 8 0 1 50923 1 50921 1 50923 2 2 50922 1 50923 3 50921 2 0 1 50923 4 2 31950 7 0 1 50929 1 50918 1 50929 2 11 50920 1 50929 3 50918 2 0 1 50929 4 11 42833 20 0 1 50951 1 50928 1 50951 2 23 50947 1 50951 3 50928 1 0 1 50951 4 23 44911 13 0 1 50957 1 50955 1 50957 2 2 50953 1 50957 3 50955 3 0 1 50957 4 2 44272 12 0 1 50969 1 50966 1 50969 2 3 50963 1 50969 3 50966 1 0 1 50969 4 3 50957 0 0 1 50971 1 50969 1 50971 2 2 50967 1 50971 3 50969 2 0 1 50971 4 2 50580 8 0 1 50989 1 50987 1 50989 2 2 50985 1 50989 3 50987 5 0 1 50989 4 2 41764 6 0 1 50993 1 50990 1 50993 2 3 50992 1 50993 3 50990 3 0 1 50993 4 3 29297 4 0 1 51001 1 50994 1 51001 2 7 50994 1 51001 3 50994 3 0 1 51001 4 7 30917 0 0 1 51031 1 51028 1 51031 2 3 51030 1 51031 3 51028 4 0 1 51031 4 3 29818 2 0 1 51043 1 51041 1 51043 2 2 51042 1 51043 3 51041 2 0 1 51043 4 2 30270 2 0 1 51047 1 51042 1 51047 2 5 51046 1 51047 3 51042 18 0 1 51047 4 5 43008 2 0 1 51059 1 51057 1 51059 2 2 51055 1 51059 3 51057 3 0 1 51059 4 2 43363 7 0 1 51061 1 51059 1 51061 2 2 51060 1 51061 3 51059 5 0 1 51061 4 2 42845 3 0 1 51071 1 51060 1 51071 2 11 51070 1 51071 3 51060 4 0 1 51071 4 11 33195 4 0 1 51109 1 51099 1 51109 2 10 51108 1 51109 3 51099 3 0 1 51109 4 10 39597 14 0 1 51131 1 51125 1 51131 2 6 51129 1 51131 3 51125 3 0 1 51131 4 6 31172 5 0 1 51133 1 51131 1 51133 2 2 51132 1 51133 3 51131 2 0 1 51133 4 2 36778 6 0 1 51137 1 51134 1 51137 2 3 51129 1 51137 3 51134 3 0 1 51137 4 3 35927 2 0 1 51151 1 51148 1 51151 2 3 51149 1 51151 3 51148 3 0 1 51151 4 3 36445 3 0 1 51157 1 51152 1 51157 2 5 51154 1 51157 3 51152 3 0 1 51157 4 5 47246 1 0 1 51169 1 51155 1 51169 2 14 51166 1 51169 3 51155 1 0 1 51169 4 14 43076 10 0 1 51193 1 51188 1 51193 2 5 51190 1 51193 3 51188 2 0 1 51193 4 5 47089 32 0 1 51197 1 51195 1 51197 2 2 51187 1 51197 3 51195 8 0 1 51197 4 2 30959 3 0 1 51199 1 51187 1 51199 2 12 51189 1 51199 3 51187 3 0 1 51199 4 12 33515 3 0 1 51203 1 51201 1 51203 2 2 51199 1 51203 3 51201 2 0 1 51203 4 2 50563 7 0 1 51217 1 51212 1 51217 2 5 51216 1 51217 3 51212 11 0 1 51217 4 5 38869 6 0 1 51229 1 51227 1 51229 2 2 51228 1 51229 3 51227 6 0 1 51229 4 2 36253 3 0 1 51239 1 51216 1 51239 2 23 51233 1 51239 3 51216 1 0 1 51239 4 23 37381 13 0 1 51241 1 51224 1 51241 2 17 51240 1 51241 3 51224 1 0 1 51241 4 17 41348 18 0 1 51257 1 51254 1 51257 2 3 51256 1 51257 3 51254 3 0 1 51257 4 3 30626 4 0 1 51263 1 51258 1 51263 2 5 51261 1 51263 3 51258 1 0 1 51263 4 5 34676 5 0 1 51283 1 51281 1 51283 2 2 51279 1 51283 3 51281 5 0 1 51283 4 2 46692 8 0 1 51287 1 51282 1 51287 2 5 51285 1 51287 3 51282 1 0 1 51287 4 5 51283 3 0 1 51307 1 51302 1 51307 2 5 51305 1 51307 3 51302 6 0 1 51307 4 5 51303 3 0 1 51329 1 51326 1 51329 2 3 51324 1 51329 3 51326 1 0 1 51329 4 3 28338 2 0 1 51341 1 51339 1 51341 2 2 51340 1 51341 3 51339 3 0 1 51341 4 2 51334 8 0 1 51343 1 51338 1 51343 2 5 51341 1 51343 3 51338 3 0 1 51343 4 5 51331 11 0 1 51347 1 51345 1 51347 2 2 51343 1 51347 3 51345 3 0 1 51347 4 2 37882 8 0 1 51349 1 51339 1 51349 2 10 51346 1 51349 3 51339 6 0 1 51349 4 10 29555 9 0 1 51361 1 51324 1 51361 2 37 51358 1 51361 3 51324 1 0 1 51361 4 37 36924 32 0 1 51383 1 51378 1 51383 2 5 51381 1 51383 3 51378 2 0 1 51383 4 5 51379 3 0 1 51407 1 51402 1 51407 2 5 51406 1 51407 3 51402 2 0 1 51407 4 5 50690 2 0 1 51413 1 51411 1 51413 2 2 51412 1 51413 3 51411 4 0 1 51413 4 2 47171 3 0 1 51419 1 51417 1 51419 2 2 51415 1 51419 3 51417 2 0 1 51419 4 2 48935 7 0 1 51421 1 51419 1 51421 2 2 51420 1 51421 3 51419 4 0 1 51421 4 2 46584 3 0 1 51427 1 51425 1 51427 2 2 51426 1 51427 3 51425 2 0 1 51427 4 2 33403 32 0 1 51431 1 51424 1 51431 2 7 51430 1 51431 3 51424 2 0 1 51431 4 7 47569 3 0 1 51437 1 51435 1 51437 2 2 51432 1 51437 3 51435 4 0 1 51437 4 2 50502 17 0 1 51439 1 51436 1 51439 2 3 51433 1 51439 3 51436 6 0 1 51439 4 3 30174 7 0 1 51449 1 51446 1 51449 2 3 51444 1 51449 3 51446 3 0 1 51449 4 3 30638 2 0 1 51461 1 51459 1 51461 2 2 51457 1 51461 3 51459 3 0 1 51461 4 2 37625 7 0 1 51473 1 51470 1 51473 2 3 51467 1 51473 3 51470 3 0 1 51473 4 3 35766 16 0 1 51479 1 51472 1 51479 2 7 51477 1 51479 3 51472 1 0 1 51479 4 7 28324 12 0 1 51481 1 51464 1 51481 2 17 51478 1 51481 3 51464 6 0 1 51481 4 17 36296 17 0 1 51487 1 51484 1 51487 2 3 51486 1 51487 3 51484 8 0 1 51487 4 3 39036 5 0 1 51503 1 51498 1 51503 2 5 51502 1 51503 3 51498 1 0 1 51503 4 5 27446 3 0 1 51511 1 51505 1 51511 2 6 51510 1 51511 3 51505 3 0 1 51511 4 6 34580 3 0 1 51517 1 51511 1 51517 2 6 51516 1 51517 3 51511 3 0 1 51517 4 6 45268 6 0 1 51521 1 51518 1 51521 2 3 51520 1 51521 3 51518 1 0 1 51521 4 3 45198 4 0 1 51539 1 51537 1 51539 2 2 51538 1 51539 3 51537 3 0 1 51539 4 2 42061 2 0 1 51551 1 51540 1 51551 2 11 51549 1 51551 3 51540 1 0 1 51551 4 11 36288 7 0 1 51563 1 51561 1 51563 2 2 51559 1 51563 3 51561 3 0 1 51563 4 2 33015 8 0 1 51577 1 51567 1 51577 2 10 51576 1 51577 3 51567 5 0 1 51577 4 10 47092 6 0 1 51581 1 51579 1 51581 2 2 51577 1 51581 3 51579 3 0 1 51581 4 2 44285 1 0 1 51593 1 51590 1 51593 2 3 51586 1 51593 3 51590 4 0 1 51593 4 3 27603 2 0 1 51599 1 51592 1 51599 2 7 51598 1 51599 3 51592 7 0 1 51599 4 7 44072 2 0 1 51607 1 51604 1 51607 2 3 51606 1 51607 3 51604 3 0 1 51607 4 3 32990 8 0 1 51613 1 51611 1 51613 2 2 51609 1 51613 3 51611 6 0 1 51613 4 2 26327 10 0 1 51631 1 51616 1 51631 2 15 51629 1 51631 3 51616 7 0 1 51631 4 15 39763 3 0 1 51637 1 51632 1 51637 2 5 51636 1 51637 3 51632 7 0 1 51637 4 5 50571 19 0 1 51647 1 51640 1 51647 2 7 51645 1 51647 3 51640 1 0 1 51647 4 7 30770 6 0 1 51659 1 51657 1 51659 2 2 51649 1 51659 3 51657 10 0 1 51659 4 2 35307 0 0 1 51673 1 51666 1 51673 2 7 51670 1 51673 3 51666 1 0 1 51673 4 7 39291 10 0 1 51679 1 51673 1 51679 2 6 51678 1 51679 3 51673 3 0 1 51679 4 6 30497 3 0 1 51683 1 51681 1 51683 2 2 51679 1 51683 3 51681 3 0 1 51683 4 2 41425 7 0 1 51691 1 51681 1 51691 2 10 51689 1 51691 3 51681 5 0 1 51691 4 10 34612 0 0 1 51713 1 51710 1 51713 2 3 51706 1 51713 3 51710 12 0 1 51713 4 3 42691 1 0 1 51719 1 51706 1 51719 2 13 51717 1 51719 3 51706 3 0 1 51719 4 13 35614 7 0 1 51721 1 51714 1 51721 2 7 51718 1 51721 3 51714 3 0 1 51721 4 7 47016 26 0 1 51749 1 51747 1 51749 2 2 51745 1 51749 3 51747 3 0 1 51749 4 2 33772 1 0 1 51767 1 51762 1 51767 2 5 51762 1 51767 3 51762 3 0 1 51767 4 5 39984 6 0 1 51769 1 51750 1 51769 2 19 51766 1 51769 3 51750 1 0 1 51769 4 19 28683 26 0 1 51787 1 51784 1 51787 2 3 51786 1 51787 3 51784 5 0 1 51787 4 3 41309 5 0 1 51797 1 51794 1 51797 2 3 51795 1 51797 3 51794 1 0 1 51797 4 3 34746 7 0 1 51803 1 51801 1 51803 2 2 51802 1 51803 3 51801 3 0 1 51803 4 2 41067 4 0 1 51817 1 51807 1 51817 2 10 51812 1 51817 3 51807 4 0 1 51817 4 10 29040 0 0 1 51827 1 51825 1 51827 2 2 51823 1 51827 3 51825 3 0 1 51827 4 2 34212 7 0 1 51829 1 51827 1 51829 2 2 51825 1 51829 3 51827 2 0 1 51829 4 2 51320 12 0 1 51839 1 51832 1 51839 2 7 51838 1 51839 3 51832 1 0 1 51839 4 7 27888 2 0 1 51853 1 51842 1 51853 2 11 51850 1 51853 3 51842 8 0 1 51853 4 11 45646 5 0 1 51859 1 51856 1 51859 2 3 51851 1 51859 3 51856 1 0 1 51859 4 3 41790 0 0 1 51869 1 51867 1 51869 2 2 51857 1 51869 3 51867 8 0 1 51869 4 2 44581 4 0 1 51871 1 51864 1 51871 2 7 51859 1 51871 3 51864 2 0 1 51871 4 7 35005 0 0 1 51893 1 51891 1 51893 2 2 51886 1 51893 3 51891 18 0 1 51893 4 2 31509 2 0 1 51899 1 51897 1 51899 2 2 51895 1 51899 3 51897 3 0 1 51899 4 2 43375 7 0 1 51907 1 51896 1 51907 2 11 51905 1 51907 3 51896 1 0 1 51907 4 11 42771 3 0 1 51913 1 51903 1 51913 2 10 51908 1 51913 3 51903 3 0 1 51913 4 10 34965 10 0 1 51929 1 51926 1 51929 2 3 51921 1 51929 3 51926 1 0 1 51929 4 3 45104 2 0 1 51941 1 51938 1 51941 2 3 51936 1 51941 3 51938 1 0 1 51941 4 3 33200 2 0 1 51949 1 51947 1 51949 2 2 51945 1 51949 3 51947 5 0 1 51949 4 2 40496 6 0 1 51971 1 51969 1 51971 2 2 51970 1 51971 3 51969 13 0 1 51971 4 2 39077 2 0 1 51973 1 51971 1 51973 2 2 51972 1 51973 3 51971 2 0 1 51973 4 2 51151 6 0 1 51977 1 51974 1 51977 2 3 51976 1 51977 3 51974 4 0 1 51977 4 3 33537 7 0 1 51991 1 51984 1 51991 2 7 51982 1 51991 3 51984 8 0 1 51991 4 7 35432 10 0 1 52009 1 51992 1 52009 2 17 52006 1 52009 3 51992 12 0 1 52009 4 17 44665 20 0 1 52021 1 52019 1 52021 2 2 52017 1 52021 3 52019 5 0 1 52021 4 2 39143 12 0 1 52027 1 52025 1 52027 2 2 52026 1 52027 3 52025 6 0 1 52027 4 2 35108 2 0 1 52051 1 52049 1 52051 2 2 52047 1 52051 3 52049 5 0 1 52051 4 2 40756 1 0 1 52057 1 52050 1 52057 2 7 52050 1 52057 3 52050 3 0 1 52057 4 7 49013 17 0 1 52067 1 52065 1 52067 2 2 52063 1 52067 3 52065 3 0 1 52067 4 2 42954 16 0 1 52069 1 52067 1 52069 2 2 52068 1 52069 3 52067 6 0 1 52069 4 2 41826 3 0 1 52081 1 52064 1 52081 2 17 52078 1 52081 3 52064 3 0 1 52081 4 17 41781 20 0 1 52103 1 52098 1 52103 2 5 52101 1 52103 3 52098 2 0 1 52103 4 5 52099 3 0 1 52121 1 52118 1 52121 2 3 52115 1 52121 3 52118 1 0 1 52121 4 3 52109 0 0 1 52127 1 52122 1 52127 2 5 52126 1 52127 3 52122 2 0 1 52127 4 5 49124 3 0 1 52147 1 52145 1 52147 2 2 52143 1 52147 3 52145 4 0 1 52147 4 2 44306 8 0 1 52153 1 52148 1 52153 2 5 52150 1 52153 3 52148 6 0 1 52153 4 5 40698 10 0 1 52163 1 52161 1 52163 2 2 52162 1 52163 3 52161 2 0 1 52163 4 2 39023 11 0 1 52177 1 52172 1 52177 2 5 52176 1 52177 3 52172 3 0 1 52177 4 5 28122 6 0 1 52181 1 52178 1 52181 2 3 52180 1 52181 3 52178 6 0 1 52181 4 3 28647 3 0 1 52183 1 52180 1 52183 2 3 52182 1 52183 3 52180 1 0 1 52183 4 3 44586 2 0 1 52189 1 52176 1 52189 2 13 52180 1 52189 3 52176 5 0 1 52189 4 13 40268 23 0 1 52201 1 52184 1 52201 2 17 52200 1 52201 3 52184 7 0 1 52201 4 17 46708 14 0 1 52223 1 52218 1 52223 2 5 52221 1 52223 3 52218 5 0 1 52223 4 5 34293 9 0 1 52237 1 52231 1 52237 2 6 52235 1 52237 3 52231 3 0 1 52237 4 6 48847 0 0 1 52249 1 52236 1 52249 2 13 52236 1 52249 3 52236 5 0 1 52249 4 13 52210 0 0 1 52253 1 52251 1 52253 2 2 52252 1 52253 3 52251 4 0 1 52253 4 2 46552 6 0 1 52259 1 52257 1 52259 2 2 52245 1 52259 3 52257 2 0 1 52259 4 2 43253 3 0 1 52267 1 52265 1 52267 2 2 52266 1 52267 3 52265 4 0 1 52267 4 2 52260 8 0 1 52289 1 52286 1 52289 2 3 52288 1 52289 3 52286 8 0 1 52289 4 3 43330 7 0 1 52291 1 52284 1 52291 2 7 52289 1 52291 3 52284 9 0 1 52291 4 7 42016 6 0 1 52301 1 52299 1 52301 2 2 52294 1 52301 3 52299 2 0 1 52301 4 2 51696 9 0 1 52313 1 52310 1 52313 2 3 52307 1 52313 3 52310 1 0 1 52313 4 3 30146 11 0 1 52321 1 52304 1 52321 2 17 52320 1 52321 3 52304 1 0 1 52321 4 17 47622 18 0 1 52361 1 52355 1 52361 2 6 52358 1 52361 3 52355 2 0 1 52361 4 6 28483 0 0 1 52363 1 52358 1 52363 2 5 52362 1 52363 3 52358 1 0 1 52363 4 5 52344 20 0 1 52369 1 52356 1 52369 2 13 52358 1 52369 3 52356 5 0 1 52369 4 13 50272 34 0 1 52379 1 52377 1 52379 2 2 52378 1 52379 3 52377 4 0 1 52379 4 2 49810 2 0 1 52387 1 52385 1 52387 2 2 52386 1 52387 3 52385 2 0 1 52387 4 2 45789 2 0 1 52391 1 52380 1 52391 2 11 52388 1 52391 3 52380 4 0 1 52391 4 11 40163 5 0 1 52433 1 52430 1 52433 2 3 52432 1 52433 3 52430 4 0 1 52433 4 3 31887 4 0 1 52453 1 52451 1 52453 2 2 52449 1 52453 3 52451 5 0 1 52453 4 2 51995 10 0 1 52457 1 52454 1 52457 2 3 52451 1 52457 3 52454 3 0 1 52457 4 3 49747 1 0 1 52489 1 52482 1 52489 2 7 52482 1 52489 3 52482 8 0 1 52489 4 7 39696 0 0 1 52501 1 52491 1 52501 2 10 52500 1 52501 3 52491 3 0 1 52501 4 10 27307 15 0 1 52511 1 52504 1 52511 2 7 52510 1 52511 3 52504 1 0 1 52511 4 7 28612 3 0 1 52517 1 52515 1 52517 2 2 52511 1 52517 3 52515 9 0 1 52517 4 2 32464 1 0 1 52529 1 52526 1 52529 2 3 52523 1 52529 3 52526 17 0 1 52529 4 3 52517 0 0 1 52541 1 52539 1 52541 2 2 52540 1 52541 3 52539 3 0 1 52541 4 2 45653 4 0 1 52543 1 52540 1 52543 2 3 52542 1 52543 3 52540 9 0 1 52543 4 3 30071 2 0 1 52553 1 52550 1 52553 2 3 52548 1 52553 3 52550 1 0 1 52553 4 3 49860 10 0 1 52561 1 52554 1 52561 2 7 52554 1 52561 3 52554 3 0 1 52561 4 7 50303 0 0 1 52567 1 52564 1 52567 2 3 52565 1 52567 3 52564 1 0 1 52567 4 3 52563 4 0 1 52571 1 52569 1 52571 2 2 52566 1 52571 3 52569 3 0 1 52571 4 2 42415 3 0 1 52579 1 52577 1 52579 2 2 52572 1 52579 3 52577 6 0 1 52579 4 2 49320 4 0 1 52583 1 52578 1 52583 2 5 52582 1 52583 3 52578 2 0 1 52583 4 5 44395 2 0 1 52609 1 52598 1 52609 2 11 52608 1 52609 3 52598 2 0 1 52609 4 11 28702 12 0 1 52627 1 52624 1 52627 2 3 52620 1 52627 3 52624 1 0 1 52627 4 3 51978 2 0 1 52631 1 52618 1 52631 2 13 52630 1 52631 3 52618 5 0 1 52631 4 13 41479 2 0 1 52639 1 52636 1 52639 2 3 52637 1 52639 3 52636 8 0 1 52639 4 3 52635 4 0 1 52667 1 52665 1 52667 2 2 52663 1 52667 3 52665 2 0 1 52667 4 2 32868 14 0 1 52673 1 52670 1 52673 2 3 52666 1 52673 3 52670 1 0 1 52673 4 3 50520 2 0 1 52691 1 52689 1 52691 2 2 52687 1 52691 3 52689 2 0 1 52691 4 2 31262 7 0 1 52697 1 52694 1 52697 2 3 52696 1 52697 3 52694 5 0 1 52697 4 3 30819 4 0 1 52709 1 52707 1 52709 2 2 52708 1 52709 3 52707 3 0 1 52709 4 2 45603 3 0 1 52711 1 52688 1 52711 2 23 52709 1 52711 3 52688 6 0 1 52711 4 23 27839 3 0 1 52721 1 52718 1 52721 2 3 52716 1 52721 3 52718 3 0 1 52721 4 3 28804 2 0 1 52727 1 52722 1 52727 2 5 52722 1 52727 3 52722 14 0 1 52727 4 5 28078 9 0 1 52733 1 52731 1 52733 2 2 52729 1 52733 3 52731 3 0 1 52733 4 2 37759 9 0 1 52747 1 52744 1 52747 2 3 52746 1 52747 3 52744 6 0 1 52747 4 3 30461 5 0 1 52757 1 52755 1 52757 2 2 52753 1 52757 3 52755 2 0 1 52757 4 2 34759 1 0 1 52769 1 52766 1 52769 2 3 52761 1 52769 3 52766 3 0 1 52769 4 3 51298 2 0 1 52783 1 52778 1 52783 2 5 52781 1 52783 3 52778 1 0 1 52783 4 5 52779 3 0 1 52807 1 52802 1 52807 2 5 52804 1 52807 3 52802 1 0 1 52807 4 5 49469 0 0 1 52813 1 52811 1 52813 2 2 52812 1 52813 3 52811 2 0 1 52813 4 2 39817 7 0 1 52817 1 52814 1 52817 2 3 52816 1 52817 3 52814 11 0 1 52817 4 3 44518 4 0 1 52837 1 52835 1 52837 2 2 52833 1 52837 3 52835 6 0 1 52837 4 2 39891 10 0 1 52859 1 52853 1 52859 2 6 52858 1 52859 3 52853 1 0 1 52859 4 6 30636 5 0 1 52861 1 52850 1 52861 2 11 52859 1 52861 3 52850 1 0 1 52861 4 11 38349 0 0 1 52879 1 52876 1 52879 2 3 52878 1 52879 3 52876 1 0 1 52879 4 3 30897 3 0 1 52883 1 52881 1 52883 2 2 52879 1 52883 3 52881 2 0 1 52883 4 2 38001 14 0 1 52889 1 52886 1 52889 2 3 52880 1 52889 3 52886 1 0 1 52889 4 3 29129 3 0 1 52901 1 52898 1 52901 2 3 52899 1 52901 3 52898 5 0 1 52901 4 3 52897 4 0 1 52903 1 52900 1 52903 2 3 52901 1 52903 3 52900 4 0 1 52903 4 3 38242 6 0 1 52919 1 52908 1 52919 2 11 52918 1 52919 3 52908 2 0 1 52919 4 11 34050 4 0 1 52937 1 52932 1 52937 2 5 52936 1 52937 3 52932 3 0 1 52937 4 5 29372 6 0 1 52951 1 52948 1 52951 2 3 52950 1 52951 3 52948 4 0 1 52951 4 3 29695 3 0 1 52957 1 52952 1 52957 2 5 52952 1 52957 3 52952 2 0 1 52957 4 5 41398 11 0 1 52963 1 52960 1 52963 2 3 52954 1 52963 3 52960 3 0 1 52963 4 3 45941 10 0 1 52967 1 52962 1 52967 2 5 52965 1 52967 3 52962 1 0 1 52967 4 5 52963 3 0 1 52973 1 52971 1 52973 2 2 52969 1 52973 3 52971 3 0 1 52973 4 2 46099 9 0 1 52981 1 52979 1 52981 2 2 52980 1 52981 3 52979 4 0 1 52981 4 2 51763 9 0 1 52999 1 52996 1 52999 2 3 52994 1 52999 3 52996 1 0 1 52999 4 3 40493 6 0 1 53003 1 53001 1 53003 2 2 52999 1 53003 3 53001 3 0 1 53003 4 2 44042 7 0 1 53017 1 53012 1 53017 2 5 53014 1 53017 3 53012 1 0 1 53017 4 5 35010 10 0 1 53047 1 53044 1 53047 2 3 53045 1 53047 3 53044 1 0 1 53047 4 3 27313 3 0 1 53051 1 53045 1 53051 2 6 53048 1 53051 3 53045 3 0 1 53051 4 6 35622 4 0 1 53069 1 53067 1 53069 2 2 53065 1 53069 3 53067 3 0 1 53069 4 2 48916 6 0 1 53077 1 53075 1 53077 2 2 53076 1 53077 3 53075 2 0 1 53077 4 2 50322 3 0 1 53087 1 53082 1 53087 2 5 53085 1 53087 3 53082 1 0 1 53087 4 5 53083 3 0 1 53089 1 53058 1 53089 2 31 53088 1 53089 3 53058 3 0 1 53089 4 31 34721 24 0 1 53093 1 53091 1 53093 2 2 53092 1 53093 3 53091 2 0 1 53093 4 2 50859 3 0 1 53101 1 53099 1 53101 2 2 53100 1 53101 3 53099 5 0 1 53101 4 2 32404 7 0 1 53113 1 53108 1 53113 2 5 53112 1 53113 3 53108 1 0 1 53113 4 5 47333 18 0 1 53117 1 53115 1 53117 2 2 53113 1 53117 3 53115 3 0 1 53117 4 2 28531 12 0 1 53129 1 53126 1 53129 2 3 53128 1 53129 3 53126 3 0 1 53129 4 3 38670 7 0 1 53147 1 53145 1 53147 2 2 53146 1 53147 3 53145 3 0 1 53147 4 2 30289 2 0 1 53149 1 53143 1 53149 2 6 53148 1 53149 3 53143 7 0 1 53149 4 6 35954 7 0 1 53161 1 53147 1 53161 2 14 53156 1 53161 3 53147 2 0 1 53161 4 14 46763 19 0 1 53171 1 53169 1 53171 2 2 53170 1 53171 3 53169 3 0 1 53171 4 2 48565 2 0 1 53173 1 53155 1 53173 2 18 53171 1 53173 3 53155 1 0 1 53173 4 18 49287 0 0 1 53189 1 53187 1 53189 2 2 53188 1 53189 3 53187 3 0 1 53189 4 2 46605 4 0 1 53197 1 53195 1 53197 2 2 53193 1 53197 3 53195 4 0 1 53197 4 2 31752 9 0 1 53201 1 53198 1 53201 2 3 53195 1 53201 3 53198 4 0 1 53201 4 3 53189 0 0 1 53231 1 53208 1 53231 2 23 53230 1 53231 3 53208 1 0 1 53231 4 23 37258 7 0 1 53233 1 53228 1 53233 2 5 53232 1 53233 3 53228 8 0 1 53233 4 5 34161 6 0 1 53239 1 53236 1 53239 2 3 53238 1 53239 3 53236 1 0 1 53239 4 3 45917 2 0 1 53267 1 53265 1 53267 2 2 53263 1 53267 3 53265 3 0 1 53267 4 2 46483 8 0 1 53269 1 53262 1 53269 2 7 53266 1 53269 3 53262 4 0 1 53269 4 7 50668 5 0 1 53279 1 53272 1 53279 2 7 53278 1 53279 3 53272 1 0 1 53279 4 7 41917 2 0 1 53281 1 53270 1 53281 2 11 53270 1 53281 3 53270 1 0 1 53281 4 11 34812 24 0 1 53299 1 53297 1 53299 2 2 53295 1 53299 3 53297 4 0 1 53299 4 2 38727 8 0 1 53309 1 53307 1 53309 2 2 53301 1 53309 3 53307 2 0 1 53309 4 2 27768 0 0 1 53323 1 53321 1 53323 2 2 53319 1 53323 3 53321 6 0 1 53323 4 2 30154 14 0 1 53327 1 53322 1 53327 2 5 53324 1 53327 3 53322 2 0 1 53327 4 5 42727 4 0 1 53353 1 53346 1 53353 2 7 53346 1 53353 3 53346 1 0 1 53353 4 7 38054 17 0 1 53359 1 53356 1 53359 2 3 53357 1 53359 3 53356 5 0 1 53359 4 3 52435 6 0 1 53377 1 53372 1 53377 2 5 53372 1 53377 3 53372 2 0 1 53377 4 5 39744 10 0 1 53381 1 53379 1 53381 2 2 53380 1 53381 3 53379 8 0 1 53381 4 2 29714 9 0 1 53401 1 53394 1 53401 2 7 53394 1 53401 3 53394 2 0 1 53401 4 7 39557 0 0 1 53407 1 53402 1 53407 2 5 53405 1 53407 3 53402 2 0 1 53407 4 5 53403 3 0 1 53411 1 53409 1 53411 2 2 53407 1 53411 3 53409 2 0 1 53411 4 2 42544 8 0 1 53419 1 53417 1 53419 2 2 53415 1 53419 3 53417 6 0 1 53419 4 2 30159 8 0 1 53437 1 53435 1 53437 2 2 53436 1 53437 3 53435 6 0 1 53437 4 2 30309 3 0 1 53441 1 53438 1 53441 2 3 53436 1 53441 3 53438 1 0 1 53441 4 3 32629 2 0 1 53453 1 53451 1 53453 2 2 53449 1 53453 3 53451 3 0 1 53453 4 2 36781 6 0 1 53479 1 53476 1 53479 2 3 53478 1 53479 3 53476 5 0 1 53479 4 3 51225 2 0 1 53503 1 53500 1 53503 2 3 53501 1 53503 3 53500 4 0 1 53503 4 3 34581 3 0 1 53507 1 53505 1 53507 2 2 53506 1 53507 3 53505 2 0 1 53507 4 2 47738 2 0 1 53527 1 53524 1 53527 2 3 53525 1 53527 3 53524 7 0 1 53527 4 3 53523 4 0 1 53549 1 53547 1 53549 2 2 53548 1 53549 3 53547 4 0 1 53549 4 2 42415 4 0 1 53551 1 53548 1 53551 2 3 53549 1 53551 3 53548 1 0 1 53551 4 3 33763 6 0 1 53569 1 53550 1 53569 2 19 53550 1 53569 3 53550 5 0 1 53569 4 19 30483 0 0 1 53591 1 53578 1 53591 2 13 53589 1 53591 3 53578 4 0 1 53591 4 13 33693 4 0 1 53593 1 53588 1 53593 2 5 53592 1 53593 3 53588 10 0 1 53593 4 5 32222 6 0 1 53597 1 53595 1 53597 2 2 53593 1 53597 3 53595 3 0 1 53597 4 2 52044 11 0 1 53609 1 53606 1 53609 2 3 53608 1 53609 3 53606 6 0 1 53609 4 3 47985 7 0 1 53611 1 53601 1 53611 2 10 53609 1 53611 3 53601 8 0 1 53611 4 10 27407 0 0 1 53617 1 53612 1 53617 2 5 53616 1 53617 3 53612 2 0 1 53617 4 5 31561 6 0 1 53623 1 53620 1 53623 2 3 53621 1 53623 3 53620 4 0 1 53623 4 3 53619 4 0 1 53629 1 53623 1 53629 2 6 53621 1 53629 3 53623 9 0 1 53629 4 6 30991 0 0 1 53633 1 53630 1 53633 2 3 53632 1 53633 3 53630 1 0 1 53633 4 3 27294 7 0 1 53639 1 53628 1 53639 2 11 53638 1 53639 3 53628 4 0 1 53639 4 11 47011 2 0 1 53653 1 53651 1 53653 2 2 53652 1 53653 3 53651 2 0 1 53653 4 2 47442 3 0 1 53657 1 53654 1 53657 2 3 53652 1 53657 3 53654 6 0 1 53657 4 3 31526 0 0 1 53681 1 53678 1 53681 2 3 53675 1 53681 3 53678 6 0 1 53681 4 3 53669 0 0 1 53693 1 53691 1 53693 2 2 53692 1 53693 3 53691 3 0 1 53693 4 2 33623 3 0 1 53699 1 53697 1 53699 2 2 53695 1 53699 3 53697 9 0 1 53699 4 2 28092 9 0 1 53717 1 53715 1 53717 2 2 53716 1 53717 3 53715 2 0 1 53717 4 2 36983 6 0 1 53719 1 53713 1 53719 2 6 53718 1 53719 3 53713 2 0 1 53719 4 6 28206 3 0 1 53731 1 53719 1 53731 2 12 53729 1 53731 3 53719 1 0 1 53731 4 12 29169 6 0 1 53759 1 53742 1 53759 2 17 53757 1 53759 3 53742 2 0 1 53759 4 17 53751 3 0 1 53773 1 53771 1 53773 2 2 53772 1 53773 3 53771 2 0 1 53773 4 2 34710 6 0 1 53777 1 53774 1 53777 2 3 53771 1 53777 3 53774 1 0 1 53777 4 3 42831 16 0 1 53783 1 53778 1 53783 2 5 53782 1 53783 3 53778 9 0 1 53783 4 5 32552 3 0 1 53791 1 53785 1 53791 2 6 53790 1 53791 3 53785 3 0 1 53791 4 6 27401 2 0 1 53813 1 53811 1 53813 2 2 53805 1 53813 3 53811 8 0 1 53813 4 2 28837 3 0 1 53819 1 53817 1 53819 2 2 53814 1 53819 3 53817 7 0 1 53819 4 2 48668 3 0 1 53831 1 53824 1 53831 2 7 53827 1 53831 3 53824 4 0 1 53831 4 7 40011 5 0 1 53849 1 53846 1 53849 2 3 53843 1 53849 3 53846 8 0 1 53849 4 3 53837 0 0 1 53857 1 53852 1 53857 2 5 53852 1 53857 3 53852 3 0 1 53857 4 5 49534 15 0 1 53861 1 53859 1 53861 2 2 53860 1 53861 3 53859 5 0 1 53861 4 2 53342 9 0 1 53881 1 53850 1 53881 2 31 53880 1 53881 3 53850 1 0 1 53881 4 31 43513 24 0 1 53887 1 53884 1 53887 2 3 53885 1 53887 3 53884 8 0 1 53887 4 3 41551 3 0 1 53891 1 53889 1 53891 2 2 53883 1 53891 3 53889 4 0 1 53891 4 2 42377 2 0 1 53897 1 53894 1 53897 2 3 53896 1 53897 3 53894 4 0 1 53897 4 3 53127 4 0 1 53899 1 53897 1 53899 2 2 53895 1 53899 3 53897 5 0 1 53899 4 2 37119 1 0 1 53917 1 53915 1 53917 2 2 53916 1 53917 3 53915 2 0 1 53917 4 2 34912 7 0 1 53923 1 53918 1 53923 2 5 53921 1 53923 3 53918 5 0 1 53923 4 5 53915 6 0 1 53927 1 53922 1 53927 2 5 53925 1 53927 3 53922 1 0 1 53927 4 5 53923 3 0 1 53939 1 53937 1 53939 2 2 53933 1 53939 3 53937 2 0 1 53939 4 2 43058 4 0 1 53951 1 53944 1 53951 2 7 53950 1 53951 3 53944 3 0 1 53951 4 7 53942 4 0 1 53959 1 53956 1 53959 2 3 53957 1 53959 3 53956 4 0 1 53959 4 3 47291 3 0 1 53987 1 53985 1 53987 2 2 53986 1 53987 3 53985 2 0 1 53987 4 2 51795 4 0 1 53993 1 53990 1 53993 2 3 53984 1 53993 3 53990 4 0 1 53993 4 3 32327 3 0 1 54001 1 53990 1 54001 2 11 53998 1 54001 3 53990 4 0 1 54001 4 11 38898 14 0 1 54011 1 54009 1 54011 2 2 54004 1 54011 3 54009 5 0 1 54011 4 2 47801 1 0 1 54013 1 54008 1 54013 2 5 54012 1 54013 3 54008 1 0 1 54013 4 5 53278 6 0 1 54037 1 54035 1 54037 2 2 54033 1 54037 3 54035 4 0 1 54037 4 2 33218 6 0 1 54049 1 54038 1 54049 2 11 54044 1 54049 3 54038 2 0 1 54049 4 11 34837 22 0 1 54059 1 54057 1 54059 2 2 54058 1 54059 3 54057 3 0 1 54059 4 2 35508 2 0 1 54083 1 54081 1 54083 2 2 54079 1 54083 3 54081 3 0 1 54083 4 2 33127 7 0 1 54091 1 54088 1 54091 2 3 54086 1 54091 3 54088 8 0 1 54091 4 3 31288 3 0 1 54101 1 54098 1 54101 2 3 54099 1 54101 3 54098 1 0 1 54101 4 3 54097 4 0 1 54121 1 54108 1 54121 2 13 54120 1 54121 3 54108 9 0 1 54121 4 13 41494 14 0 1 54133 1 54128 1 54133 2 5 54132 1 54133 3 54128 5 0 1 54133 4 5 31507 6 0 1 54139 1 54137 1 54139 2 2 54135 1 54139 3 54137 6 0 1 54139 4 2 53333 8 0 1 54151 1 54145 1 54151 2 6 54149 1 54151 3 54145 3 0 1 54151 4 6 39340 3 0 1 54163 1 54161 1 54163 2 2 54159 1 54163 3 54161 6 0 1 54163 4 2 49878 8 0 1 54167 1 54162 1 54167 2 5 54165 1 54167 3 54162 2 0 1 54167 4 5 39230 8 0 1 54181 1 54179 1 54181 2 2 54177 1 54181 3 54179 2 0 1 54181 4 2 29314 12 0 1 54193 1 54183 1 54193 2 10 54188 1 54193 3 54183 2 0 1 54193 4 10 53577 12 0 1 54217 1 54212 1 54217 2 5 54216 1 54217 3 54212 1 0 1 54217 4 5 41596 6 0 1 54251 1 54249 1 54251 2 2 54247 1 54251 3 54249 3 0 1 54251 4 2 35571 8 0 1 54269 1 54267 1 54269 2 2 54264 1 54269 3 54267 4 0 1 54269 4 2 52348 8 0 1 54277 1 54272 1 54277 2 5 54276 1 54277 3 54272 2 0 1 54277 4 5 46093 3 0 1 54287 1 54282 1 54287 2 5 54285 1 54287 3 54282 5 0 1 54287 4 5 54283 3 0 1 54293 1 54291 1 54293 2 2 54288 1 54293 3 54291 5 0 1 54293 4 2 52801 2 0 1 54311 1 54300 1 54311 2 11 54310 1 54311 3 54300 2 0 1 54311 4 11 35318 10 0 1 54319 1 54316 1 54319 2 3 54317 1 54319 3 54316 4 0 1 54319 4 3 46010 6 0 1 54323 1 54321 1 54323 2 2 54319 1 54323 3 54321 2 0 1 54323 4 2 53550 7 0 1 54331 1 54329 1 54331 2 2 54327 1 54331 3 54329 2 0 1 54331 4 2 48975 8 0 1 54347 1 54345 1 54347 2 2 54343 1 54347 3 54345 2 0 1 54347 4 2 36691 11 0 1 54361 1 54354 1 54361 2 7 54358 1 54361 3 54354 1 0 1 54361 4 7 51839 16 0 1 54367 1 54362 1 54367 2 5 54366 1 54367 3 54362 10 0 1 54367 4 5 43976 2 0 1 54371 1 54365 1 54371 2 6 54370 1 54371 3 54365 10 0 1 54371 4 6 51692 4 0 1 54377 1 54372 1 54377 2 5 54370 1 54377 3 54372 9 0 1 54377 4 5 51708 1 0 1 54401 1 54398 1 54401 2 3 54400 1 54401 3 54398 1 0 1 54401 4 3 32412 4 0 1 54403 1 54401 1 54403 2 2 54399 1 54403 3 54401 2 0 1 54403 4 2 42818 1 0 1 54409 1 54402 1 54409 2 7 54406 1 54409 3 54402 7 0 1 54409 4 7 40433 17 0 1 54413 1 54411 1 54413 2 2 54406 1 54413 3 54411 10 0 1 54413 4 2 37262 4 0 1 54419 1 54417 1 54419 2 2 54415 1 54419 3 54417 2 0 1 54419 4 2 44995 8 0 1 54421 1 54419 1 54421 2 2 54420 1 54421 3 54419 6 0 1 54421 4 2 54414 8 0 1 54437 1 54435 1 54437 2 2 54432 1 54437 3 54435 2 0 1 54437 4 2 40155 0 0 1 54443 1 54441 1 54443 2 2 54439 1 54443 3 54441 3 0 1 54443 4 2 27730 8 0 1 54449 1 54446 1 54449 2 3 54442 1 54449 3 54446 3 0 1 54449 4 3 36474 0 0 1 54469 1 54467 1 54469 2 2 54465 1 54469 3 54467 2 0 1 54469 4 2 28084 12 0 1 54493 1 54491 1 54493 2 2 54492 1 54493 3 54491 6 0 1 54493 4 2 28709 9 0 1 54497 1 54494 1 54497 2 3 54483 1 54497 3 54494 1 0 1 54497 4 3 52734 4 0 1 54499 1 54496 1 54499 2 3 54492 1 54499 3 54496 1 0 1 54499 4 3 37260 5 0 1 54503 1 54496 1 54503 2 7 54501 1 54503 3 54496 10 0 1 54503 4 7 47550 4 0 1 54517 1 54512 1 54517 2 5 54512 1 54517 3 54512 6 0 1 54517 4 5 41098 23 0 1 54521 1 54518 1 54521 2 3 54514 1 54521 3 54518 4 0 1 54521 4 3 31723 4 0 1 54539 1 54537 1 54539 2 2 54533 1 54539 3 54537 7 0 1 54539 4 2 31098 4 0 1 54541 1 54539 1 54541 2 2 54537 1 54541 3 54539 2 0 1 54541 4 2 45092 6 0 1 54547 1 54544 1 54547 2 3 54538 1 54547 3 54544 1 0 1 54547 4 3 52356 4 0 1 54559 1 54556 1 54559 2 3 54558 1 54559 3 54556 1 0 1 54559 4 3 53941 2 0 1 54563 1 54561 1 54563 2 2 54559 1 54563 3 54561 2 0 1 54563 4 2 52815 7 0 1 54577 1 54572 1 54577 2 5 54574 1 54577 3 54572 1 0 1 54577 4 5 54566 14 0 1 54581 1 54571 1 54581 2 10 54578 1 54581 3 54571 8 0 1 54581 4 10 52377 0 0 1 54583 1 54578 1 54583 2 5 54582 1 54583 3 54578 2 0 1 54583 4 5 41655 3 0 1 54601 1 54579 1 54601 2 22 54598 1 54601 3 54579 2 0 1 54601 4 22 52577 22 0 1 54617 1 54614 1 54617 2 3 54616 1 54617 3 54614 4 0 1 54617 4 3 49252 7 0 1 54623 1 54618 1 54623 2 5 54620 1 54623 3 54618 1 0 1 54623 4 5 35656 4 0 1 54629 1 54626 1 54629 2 3 54627 1 54629 3 54626 7 0 1 54629 4 3 38672 12 0 1 54631 1 54625 1 54631 2 6 54629 1 54631 3 54625 2 0 1 54631 4 6 32685 3 0 1 54647 1 54642 1 54647 2 5 54642 1 54647 3 54642 3 0 1 54647 4 5 48318 7 0 1 54667 1 54665 1 54667 2 2 54663 1 54667 3 54665 6 0 1 54667 4 2 30127 13 0 1 54673 1 54668 1 54673 2 5 54672 1 54673 3 54668 2 0 1 54673 4 5 48898 6 0 1 54679 1 54672 1 54679 2 7 54667 1 54679 3 54672 1 0 1 54679 4 7 48374 0 0 1 54709 1 54707 1 54709 2 2 54705 1 54709 3 54707 2 0 1 54709 4 2 54186 6 0 1 54713 1 54708 1 54713 2 5 54712 1 54713 3 54708 3 0 1 54713 4 5 44310 6 0 1 54721 1 54710 1 54721 2 11 54712 1 54721 3 54710 1 0 1 54721 4 11 45297 20 0 1 54727 1 54724 1 54727 2 3 54726 1 54727 3 54724 1 0 1 54727 4 3 51959 5 0 1 54751 1 54745 1 54751 2 6 54749 1 54751 3 54745 3 0 1 54751 4 6 54741 7 0 1 54767 1 54762 1 54767 2 5 54765 1 54767 3 54762 1 0 1 54767 4 5 36070 5 0 1 54773 1 54771 1 54773 2 2 54766 1 54773 3 54771 2 0 1 54773 4 2 49710 2 0 1 54779 1 54777 1 54779 2 2 54775 1 54779 3 54777 2 0 1 54779 4 2 37806 8 0 1 54787 1 54785 1 54787 2 2 54786 1 54787 3 54785 6 0 1 54787 4 2 40532 7 0 1 54799 1 54796 1 54799 2 3 54798 1 54799 3 54796 3 0 1 54799 4 3 31708 2 0 1 54829 1 54827 1 54829 2 2 54828 1 54829 3 54827 4 0 1 54829 4 2 54822 8 0 1 54833 1 54830 1 54833 2 3 54827 1 54833 3 54830 11 0 1 54833 4 3 51648 1 0 1 54851 1 54845 1 54851 2 6 54849 1 54851 3 54845 3 0 1 54851 4 6 44707 15 0 1 54869 1 54867 1 54869 2 2 54868 1 54869 3 54867 3 0 1 54869 4 2 49807 4 0 1 54877 1 54875 1 54877 2 2 54873 1 54877 3 54875 4 0 1 54877 4 2 49718 12 0 1 54881 1 54878 1 54881 2 3 54880 1 54881 3 54878 9 0 1 54881 4 3 47900 4 0 1 54907 1 54905 1 54907 2 2 54906 1 54907 3 54905 2 0 1 54907 4 2 38476 7 0 1 54917 1 54915 1 54917 2 2 54909 1 54917 3 54915 8 0 1 54917 4 2 41903 5 0 1 54919 1 54916 1 54919 2 3 54918 1 54919 3 54916 4 0 1 54919 4 3 42837 3 0 1 54941 1 54939 1 54941 2 2 54940 1 54941 3 54939 5 0 1 54941 4 2 50581 3 0 1 54949 1 54947 1 54949 2 2 54948 1 54949 3 54947 4 0 1 54949 4 2 54942 8 0 1 54959 1 54952 1 54959 2 7 54958 1 54959 3 54952 1 0 1 54959 4 7 31117 2 0 1 54973 1 54959 1 54973 2 14 54970 1 54973 3 54959 5 0 1 54973 4 14 30370 1 0 1 54979 1 54976 1 54979 2 3 54974 1 54979 3 54976 1 0 1 54979 4 3 42920 3 0 1 54983 1 54978 1 54983 2 5 54978 1 54983 3 54978 2 0 1 54983 4 5 48837 6 0 1 55001 1 54998 1 55001 2 3 54996 1 55001 3 54998 4 0 1 55001 4 3 40914 8 0 1 55009 1 55002 1 55009 2 7 54998 1 55009 3 55002 11 0 1 55009 4 7 38608 24 0 1 55021 1 55015 1 55021 2 6 55020 1 55021 3 55015 2 0 1 55021 4 6 28224 7 0 1 55049 1 55043 1 55049 2 6 55048 1 55049 3 55043 2 0 1 55049 4 6 45962 4 0 1 55051 1 55049 1 55051 2 2 55050 1 55051 3 55049 6 0 1 55051 4 2 35693 2 0 1 55057 1 55047 1 55057 2 10 55056 1 55057 3 55047 5 0 1 55057 4 10 38627 12 0 1 55061 1 55059 1 55061 2 2 55060 1 55061 3 55059 4 0 1 55061 4 2 33619 3 0 1 55073 1 55070 1 55073 2 3 55072 1 55073 3 55070 3 0 1 55073 4 3 38454 7 0 1 55079 1 55066 1 55079 2 13 55078 1 55079 3 55066 1 0 1 55079 4 13 37766 2 0 1 55103 1 55098 1 55103 2 5 55102 1 55103 3 55098 1 0 1 55103 4 5 48476 3 0 1 55109 1 55107 1 55109 2 2 55098 1 55109 3 55107 4 0 1 55109 4 2 35765 9 0 1 55117 1 55112 1 55117 2 5 55114 1 55117 3 55112 10 0 1 55117 4 5 40725 1 0 1 55127 1 55122 1 55127 2 5 55125 1 55127 3 55122 1 0 1 55127 4 5 40534 5 0 1 55147 1 55142 1 55147 2 5 55145 1 55147 3 55142 2 0 1 55147 4 5 55143 3 0 1 55163 1 55161 1 55163 2 2 55162 1 55163 3 55161 3 0 1 55163 4 2 49605 13 0 1 55171 1 55161 1 55171 2 10 55169 1 55171 3 55161 2 0 1 55171 4 10 38724 13 0 1 55201 1 55194 1 55201 2 7 55194 1 55201 3 55194 1 0 1 55201 4 7 51398 0 0 1 55207 1 55202 1 55207 2 5 55206 1 55207 3 55202 1 0 1 55207 4 5 44099 2 0 1 55213 1 55211 1 55213 2 2 55209 1 55213 3 55211 5 0 1 55213 4 2 48748 6 0 1 55217 1 55214 1 55217 2 3 55216 1 55217 3 55214 1 0 1 55217 4 3 50697 11 0 1 55219 1 55217 1 55219 2 2 55218 1 55219 3 55217 4 0 1 55219 4 2 28415 2 0 1 55229 1 55227 1 55229 2 2 55223 1 55229 3 55227 4 0 1 55229 4 2 38844 4 0 1 55243 1 55241 1 55243 2 2 55242 1 55243 3 55241 2 0 1 55243 4 2 50554 2 0 1 55249 1 55238 1 55249 2 11 55248 1 55249 3 55238 2 0 1 55249 4 11 51344 8 0 1 55259 1 55253 1 55259 2 6 55249 1 55259 3 55253 2 0 1 55259 4 6 46182 0 0 1 55291 1 55280 1 55291 2 11 55288 1 55291 3 55280 1 0 1 55291 4 11 29304 0 0 1 55313 1 55310 1 55313 2 3 55308 1 55313 3 55310 4 0 1 55313 4 3 52824 0 0 1 55331 1 55329 1 55331 2 2 55330 1 55331 3 55329 7 0 1 55331 4 2 47533 6 0 1 55333 1 55327 1 55333 2 6 55331 1 55333 3 55327 2 0 1 55333 4 6 37793 8 0 1 55337 1 55334 1 55337 2 3 55336 1 55337 3 55334 1 0 1 55337 4 3 38163 7 0 1 55339 1 55337 1 55339 2 2 55335 1 55339 3 55337 2 0 1 55339 4 2 31052 8 0 1 55343 1 55336 1 55343 2 7 55339 1 55343 3 55336 1 0 1 55343 4 7 55331 16 0 1 55351 1 55344 1 55351 2 7 55342 1 55351 3 55344 13 0 1 55351 4 7 46608 3 0 1 55373 1 55371 1 55373 2 2 55372 1 55373 3 55371 2 0 1 55373 4 2 45800 3 0 1 55381 1 55375 1 55381 2 6 55380 1 55381 3 55375 2 0 1 55381 4 6 41076 11 0 1 55399 1 55393 1 55399 2 6 55398 1 55399 3 55393 2 0 1 55399 4 6 44143 2 0 1 55411 1 55409 1 55411 2 2 55410 1 55411 3 55409 4 0 1 55411 4 2 46072 2 0 1 55439 1 55426 1 55439 2 13 55437 1 55439 3 55426 2 0 1 55439 4 13 42340 4 0 1 55441 1 55403 1 55441 2 38 55440 1 55441 3 55403 1 0 1 55441 4 38 47380 20 0 1 55457 1 55454 1 55457 2 3 55451 1 55457 3 55454 10 0 1 55457 4 3 51566 1 0 1 55469 1 55467 1 55469 2 2 55460 1 55469 3 55467 2 0 1 55469 4 2 34598 1 0 1 55487 1 55482 1 55487 2 5 55482 1 55487 3 55482 2 0 1 55487 4 5 47865 6 0 1 55501 1 55495 1 55501 2 6 55497 1 55501 3 55495 1 0 1 55501 4 6 55497 6 0 1 55511 1 55500 1 55511 2 11 55509 1 55511 3 55500 6 0 1 55511 4 11 45652 5 0 1 55529 1 55526 1 55529 2 3 55524 1 55529 3 55526 3 0 1 55529 4 3 42741 2 0 1 55541 1 55539 1 55541 2 2 55535 1 55541 3 55539 9 0 1 55541 4 2 44080 4 0 1 55547 1 55545 1 55547 2 2 55541 1 55547 3 55545 9 0 1 55547 4 2 29580 4 0 1 55579 1 55577 1 55579 2 2 55578 1 55579 3 55577 6 0 1 55579 4 2 45669 2 0 1 55589 1 55587 1 55589 2 2 55585 1 55589 3 55587 3 0 1 55589 4 2 39396 12 0 1 55603 1 55601 1 55603 2 2 55599 1 55603 3 55601 6 0 1 55603 4 2 32874 8 0 1 55609 1 55596 1 55609 2 13 55596 1 55609 3 55596 1 0 1 55609 4 13 55570 0 0 1 55619 1 55617 1 55619 2 2 55615 1 55619 3 55617 2 0 1 55619 4 2 34176 7 0 1 55621 1 55619 1 55621 2 2 55620 1 55621 3 55619 4 0 1 55621 4 2 39788 7 0 1 55631 1 55624 1 55631 2 7 55629 1 55631 3 55624 1 0 1 55631 4 7 38577 4 0 1 55633 1 55628 1 55633 2 5 55630 1 55633 3 55628 5 0 1 55633 4 5 35265 16 0 1 55639 1 55636 1 55639 2 3 55637 1 55639 3 55636 6 0 1 55639 4 3 46470 6 0 1 55661 1 55659 1 55661 2 2 55657 1 55661 3 55659 5 0 1 55661 4 2 37283 12 0 1 55663 1 55660 1 55663 2 3 55661 1 55663 3 55660 3 0 1 55663 4 3 28880 3 0 1 55667 1 55665 1 55667 2 2 55663 1 55667 3 55665 2 0 1 55667 4 2 51291 13 0 1 55673 1 55670 1 55673 2 3 55672 1 55673 3 55670 1 0 1 55673 4 3 41377 4 0 1 55681 1 55670 1 55681 2 11 55680 1 55681 3 55670 5 0 1 55681 4 11 30307 12 0 1 55691 1 55689 1 55691 2 2 55690 1 55691 3 55689 3 0 1 55691 4 2 44290 2 0 1 55697 1 55694 1 55697 2 3 55692 1 55697 3 55694 1 0 1 55697 4 3 35089 2 0 1 55711 1 55708 1 55711 2 3 55710 1 55711 3 55708 5 0 1 55711 4 3 54042 2 0 1 55717 1 55715 1 55717 2 2 55713 1 55717 3 55715 6 0 1 55717 4 2 45647 9 0 1 55721 1 55718 1 55721 2 3 55720 1 55721 3 55718 13 0 1 55721 4 3 35341 7 0 1 55733 1 55731 1 55733 2 2 55727 1 55733 3 55731 7 0 1 55733 4 2 41119 1 0 1 55763 1 55761 1 55763 2 2 55757 1 55763 3 55761 8 0 1 55763 4 2 32202 4 0 1 55787 1 55785 1 55787 2 2 55782 1 55787 3 55785 5 0 1 55787 4 2 44917 3 0 1 55793 1 55790 1 55793 2 3 55787 1 55793 3 55790 1 0 1 55793 4 3 29668 12 0 1 55799 1 55792 1 55799 2 7 55797 1 55799 3 55792 19 0 1 55799 4 7 28837 5 0 1 55807 1 55804 1 55807 2 3 55805 1 55807 3 55804 5 0 1 55807 4 3 28470 6 0 1 55813 1 55811 1 55813 2 2 55809 1 55813 3 55811 4 0 1 55813 4 2 31826 10 0 1 55817 1 55814 1 55817 2 3 55805 1 55817 3 55814 1 0 1 55817 4 3 48937 0 0 1 55819 1 55817 1 55819 2 2 55815 1 55819 3 55817 2 0 1 55819 4 2 33154 8 0 1 55823 1 55818 1 55823 2 5 55821 1 55823 3 55818 3 0 1 55823 4 5 45481 8 0 1 55829 1 55827 1 55829 2 2 55825 1 55829 3 55827 2 0 1 55829 4 2 33851 7 0 1 55837 1 55832 1 55837 2 5 55836 1 55837 3 55832 14 0 1 55837 4 5 49246 6 0 1 55843 1 55841 1 55843 2 2 55839 1 55843 3 55841 6 0 1 55843 4 2 42336 8 0 1 55849 1 55835 1 55849 2 14 55846 1 55849 3 55835 1 0 1 55849 4 14 46684 10 0 1 55871 1 55864 1 55871 2 7 55870 1 55871 3 55864 4 0 1 55871 4 7 37071 3 0 1 55889 1 55886 1 55889 2 3 55883 1 55889 3 55886 1 0 1 55889 4 3 55877 0 0 1 55897 1 55892 1 55897 2 5 55896 1 55897 3 55892 1 0 1 55897 4 5 41446 12 0 1 55901 1 55899 1 55901 2 2 55900 1 55901 3 55899 3 0 1 55901 4 2 49020 3 0 1 55903 1 55892 1 55903 2 11 55902 1 55903 3 55892 4 0 1 55903 4 11 43803 2 0 1 55921 1 55900 1 55921 2 21 55920 1 55921 3 55900 4 0 1 55921 4 21 43101 8 0 1 55927 1 55924 1 55927 2 3 55925 1 55927 3 55924 4 0 1 55927 4 3 35633 3 0 1 55931 1 55925 1 55931 2 6 55929 1 55931 3 55925 1 0 1 55931 4 6 52723 0 0 1 55933 1 55931 1 55933 2 2 55932 1 55933 3 55931 2 0 1 55933 4 2 48082 6 0 1 55949 1 55947 1 55949 2 2 55945 1 55949 3 55947 3 0 1 55949 4 2 28239 1 0 1 55967 1 55962 1 55967 2 5 55966 1 55967 3 55962 1 0 1 55967 4 5 42501 5 0 1 55987 1 55985 1 55987 2 2 55983 1 55987 3 55985 6 0 1 55987 4 2 36179 8 0 1 55997 1 55995 1 55997 2 2 55993 1 55997 3 55995 3 0 1 55997 4 2 37684 12 0 1 56003 1 56001 1 56003 2 2 56002 1 56003 3 56001 2 0 1 56003 4 2 43720 2 0 1 56009 1 56006 1 56009 2 3 56001 1 56009 3 56006 3 0 1 56009 4 3 43639 2 0 1 56039 1 56032 1 56039 2 7 56038 1 56039 3 56032 3 0 1 56039 4 7 56030 4 0 1 56041 1 56034 1 56041 2 7 56034 1 56041 3 56034 5 0 1 56041 4 7 40523 0 0 1 56053 1 56051 1 56053 2 2 56049 1 56053 3 56051 6 0 1 56053 4 2 49665 9 0 1 56081 1 56078 1 56081 2 3 56069 1 56081 3 56078 6 0 1 56081 4 3 49974 0 0 1 56087 1 56082 1 56087 2 5 56085 1 56087 3 56082 1 0 1 56087 4 5 54608 5 0 1 56093 1 56091 1 56093 2 2 56089 1 56093 3 56091 3 0 1 56093 4 2 50569 6 0 1 56099 1 56097 1 56099 2 2 56093 1 56099 3 56097 2 0 1 56099 4 2 42982 4 0 1 56101 1 56094 1 56101 2 7 56099 1 56101 3 56094 4 0 1 56101 4 7 44663 15 0 1 56113 1 56108 1 56113 2 5 56110 1 56113 3 56108 8 0 1 56113 4 5 51606 16 0 1 56123 1 56121 1 56123 2 2 56119 1 56123 3 56121 3 0 1 56123 4 2 43350 8 0 1 56131 1 56129 1 56131 2 2 56130 1 56131 3 56129 6 0 1 56131 4 2 54390 2 0 1 56149 1 56143 1 56149 2 6 56141 1 56149 3 56143 4 0 1 56149 4 6 55201 0 0 1 56167 1 56164 1 56167 2 3 56165 1 56167 3 56164 4 0 1 56167 4 3 55693 3 0 1 56171 1 56169 1 56171 2 2 56170 1 56171 3 56169 4 0 1 56171 4 2 29334 2 0 1 56179 1 56176 1 56179 2 3 56174 1 56179 3 56176 1 0 1 56179 4 3 54503 3 0 1 56197 1 56184 1 56197 2 13 56196 1 56197 3 56184 2 0 1 56197 4 13 52594 3 0 1 56207 1 56202 1 56207 2 5 56205 1 56207 3 56202 1 0 1 56207 4 5 56203 3 0 1 56209 1 56202 1 56209 2 7 56202 1 56209 3 56202 3 0 1 56209 4 7 54847 0 0 1 56237 1 56235 1 56237 2 2 56236 1 56237 3 56235 3 0 1 56237 4 2 51506 6 0 1 56239 1 56236 1 56239 2 3 56237 1 56239 3 56236 3 0 1 56239 4 3 42826 3 0 1 56249 1 56246 1 56249 2 3 56244 1 56249 3 56246 3 0 1 56249 4 3 51793 2 0 1 56263 1 56260 1 56263 2 3 56261 1 56263 3 56260 1 0 1 56263 4 3 56259 4 0 1 56267 1 56265 1 56267 2 2 56263 1 56267 3 56265 3 0 1 56267 4 2 47807 7 0 1 56269 1 56267 1 56269 2 2 56268 1 56269 3 56267 6 0 1 56269 4 2 40885 7 0 1 56299 1 56289 1 56299 2 10 56297 1 56299 3 56289 6 0 1 56299 4 10 47088 0 0 1 56311 1 56305 1 56311 2 6 56310 1 56311 3 56305 3 0 1 56311 4 6 48710 6 0 1 56333 1 56331 1 56333 2 2 56328 1 56333 3 56331 13 0 1 56333 4 2 44573 0 0 1 56359 1 56356 1 56359 2 3 56358 1 56359 3 56356 3 0 1 56359 4 3 41399 2 0 1 56369 1 56366 1 56369 2 3 56363 1 56369 3 56366 4 0 1 56369 4 3 56357 0 0 1 56377 1 56372 1 56377 2 5 56374 1 56377 3 56372 1 0 1 56377 4 5 53649 23 0 1 56383 1 56380 1 56383 2 3 56382 1 56383 3 56380 1 0 1 56383 4 3 43205 5 0 1 56393 1 56390 1 56393 2 3 56392 1 56393 3 56390 4 0 1 56393 4 3 48024 6 0 1 56401 1 56388 1 56401 2 13 56400 1 56401 3 56388 6 0 1 56401 4 13 31874 14 0 1 56417 1 56414 1 56417 2 3 56411 1 56417 3 56414 1 0 1 56417 4 3 37285 9 0 1 56431 1 56428 1 56431 2 3 56429 1 56431 3 56428 13 0 1 56431 4 3 30540 6 0 1 56437 1 56435 1 56437 2 2 56436 1 56437 3 56435 2 0 1 56437 4 2 43979 3 0 1 56443 1 56438 1 56443 2 5 56442 1 56443 3 56438 3 0 1 56443 4 5 41908 5 0 1 56453 1 56451 1 56453 2 2 56447 1 56453 3 56451 2 0 1 56453 4 2 28655 1 0 1 56467 1 56465 1 56467 2 2 56466 1 56467 3 56465 4 0 1 56467 4 2 32208 2 0 1 56473 1 56468 1 56473 2 5 56470 1 56473 3 56468 2 0 1 56473 4 5 41277 32 0 1 56477 1 56475 1 56477 2 2 56473 1 56477 3 56475 3 0 1 56477 4 2 28783 7 0 1 56479 1 56473 1 56479 2 6 56478 1 56479 3 56473 8 0 1 56479 4 6 31461 3 0 1 56489 1 56486 1 56489 2 3 56480 1 56489 3 56486 10 0 1 56489 4 3 30320 3 0 1 56501 1 56498 1 56501 2 3 56499 1 56501 3 56498 6 0 1 56501 4 3 56497 4 0 1 56503 1 56500 1 56503 2 3 56502 1 56503 3 56500 4 0 1 56503 4 3 35604 2 0 1 56509 1 56507 1 56509 2 2 56508 1 56509 3 56507 4 0 1 56509 4 2 39742 3 0 1 56519 1 56506 1 56519 2 13 56510 1 56519 3 56506 2 0 1 56519 4 13 29316 11 0 1 56527 1 56524 1 56527 2 3 56525 1 56527 3 56524 3 0 1 56527 4 3 47508 3 0 1 56531 1 56529 1 56531 2 2 56527 1 56531 3 56529 3 0 1 56531 4 2 29045 15 0 1 56533 1 56528 1 56533 2 5 56532 1 56533 3 56528 1 0 1 56533 4 5 35775 3 0 1 56543 1 56538 1 56543 2 5 56541 1 56543 3 56538 1 0 1 56543 4 5 56539 3 0 1 56569 1 56558 1 56569 2 11 56558 1 56569 3 56558 1 0 1 56569 4 11 44961 33 0 1 56591 1 56572 1 56591 2 19 56590 1 56591 3 56572 15 0 1 56591 4 19 56576 4 0 1 56597 1 56595 1 56597 2 2 56590 1 56597 3 56595 5 0 1 56597 4 2 45525 5 0 1 56599 1 56596 1 56599 2 3 56597 1 56599 3 56596 3 0 1 56599 4 3 56595 4 0 1 56611 1 56585 1 56611 2 26 56609 1 56611 3 56585 1 0 1 56611 4 26 55822 0 0 1 56629 1 56627 1 56629 2 2 56628 1 56629 3 56627 6 0 1 56629 4 2 56622 8 0 1 56633 1 56630 1 56633 2 3 56628 1 56633 3 56630 1 0 1 56633 4 3 31538 0 0 1 56659 1 56657 1 56659 2 2 56655 1 56659 3 56657 6 0 1 56659 4 2 47043 8 0 1 56663 1 56658 1 56663 2 5 56661 1 56663 3 56658 1 0 1 56663 4 5 56659 3 0 1 56671 1 56668 1 56671 2 3 56670 1 56671 3 56668 3 0 1 56671 4 3 45827 2 0 1 56681 1 56678 1 56681 2 3 56675 1 56681 3 56678 4 0 1 56681 4 3 56669 0 0 1 56687 1 56682 1 56687 2 5 56686 1 56687 3 56682 3 0 1 56687 4 5 44288 4 0 1 56701 1 56699 1 56701 2 2 56697 1 56701 3 56699 2 0 1 56701 4 2 53689 6 0 1 56711 1 56704 1 56711 2 7 56710 1 56711 3 56704 1 0 1 56711 4 7 48465 2 0 1 56713 1 56708 1 56713 2 5 56710 1 56713 3 56708 6 0 1 56713 4 5 41674 10 0 1 56731 1 56729 1 56731 2 2 56730 1 56731 3 56729 6 0 1 56731 4 2 30326 6 0 1 56737 1 56727 1 56737 2 10 56736 1 56737 3 56727 10 0 1 56737 4 10 51769 12 0 1 56747 1 56745 1 56747 2 2 56743 1 56747 3 56745 3 0 1 56747 4 2 47524 7 0 1 56767 1 56764 1 56767 2 3 56766 1 56767 3 56764 3 0 1 56767 4 3 31734 17 0 1 56773 1 56771 1 56773 2 2 56772 1 56773 3 56771 4 0 1 56773 4 2 42713 3 0 1 56779 1 56777 1 56779 2 2 56775 1 56779 3 56777 2 0 1 56779 4 2 49583 8 0 1 56783 1 56778 1 56783 2 5 56781 1 56783 3 56778 5 0 1 56783 4 5 36408 9 0 1 56807 1 56802 1 56807 2 5 56802 1 56807 3 56802 2 0 1 56807 4 5 39806 8 0 1 56809 1 56792 1 56809 2 17 56802 1 56809 3 56792 1 0 1 56809 4 17 56790 26 0 1 56813 1 56810 1 56813 2 3 56811 1 56813 3 56810 6 0 1 56813 4 3 55747 14 0 1 56821 1 56815 1 56821 2 6 56820 1 56821 3 56815 4 0 1 56821 4 6 49900 7 0 1 56827 1 56825 1 56827 2 2 56823 1 56827 3 56825 4 0 1 56827 4 2 39738 8 0 1 56843 1 56841 1 56843 2 2 56839 1 56843 3 56841 2 0 1 56843 4 2 48461 7 0 1 56857 1 56850 1 56857 2 7 56850 1 56857 3 56850 1 0 1 56857 4 7 35829 12 0 1 56873 1 56870 1 56873 2 3 56868 1 56873 3 56870 3 0 1 56873 4 3 31446 0 0 1 56891 1 56889 1 56891 2 2 56887 1 56891 3 56889 2 0 1 56891 4 2 32887 8 0 1 56893 1 56891 1 56893 2 2 56889 1 56893 3 56891 8 0 1 56893 4 2 36782 6 0 1 56897 1 56892 1 56897 2 5 56892 1 56897 3 56892 6 0 1 56897 4 5 49662 8 0 1 56909 1 56907 1 56909 2 2 56908 1 56909 3 56907 4 0 1 56909 4 2 56902 8 0 1 56911 1 56908 1 56911 2 3 56910 1 56911 3 56908 1 0 1 56911 4 3 31894 3 0 1 56921 1 56918 1 56921 2 3 56920 1 56921 3 56918 13 0 1 56921 4 3 40471 7 0 1 56923 1 56920 1 56923 2 3 56914 1 56923 3 56920 3 0 1 56923 4 3 47329 4 0 1 56929 1 56915 1 56929 2 14 56924 1 56929 3 56915 1 0 1 56929 4 14 29755 12 0 1 56941 1 56939 1 56941 2 2 56940 1 56941 3 56939 6 0 1 56941 4 2 31538 9 0 1 56951 1 56938 1 56951 2 13 56950 1 56951 3 56938 1 0 1 56951 4 13 38438 2 0 1 56957 1 56955 1 56957 2 2 56953 1 56957 3 56955 2 0 1 56957 4 2 30493 1 0 1 56963 1 56961 1 56963 2 2 56951 1 56963 3 56961 4 0 1 56963 4 2 52095 6 0 1 56983 1 56980 1 56983 2 3 56981 1 56983 3 56980 8 0 1 56983 4 3 36515 3 0 1 56989 1 56983 1 56989 2 6 56985 1 56989 3 56983 2 0 1 56989 4 6 29829 2 0 1 56993 1 56990 1 56993 2 3 56987 1 56993 3 56990 6 0 1 56993 4 3 38637 1 0 1 56999 1 56986 1 56999 2 13 56995 1 56999 3 56986 1 0 1 56999 4 13 56981 13 0 1 57037 1 57032 1 57037 2 5 57034 1 57037 3 57032 1 0 1 57037 4 5 55996 1 0 1 57041 1 57030 1 57041 2 11 57038 1 57041 3 57030 12 0 1 57041 4 11 34827 6 0 1 57047 1 57040 1 57047 2 7 57046 1 57047 3 57040 1 0 1 57047 4 7 34431 3 0 1 57059 1 57057 1 57059 2 2 57054 1 57059 3 57057 2 0 1 57059 4 2 39457 3 0 1 57073 1 57068 1 57073 2 5 57068 1 57073 3 57068 3 0 1 57073 4 5 44036 10 0 1 57077 1 57075 1 57077 2 2 57076 1 57077 3 57075 3 0 1 57077 4 2 29715 6 0 1 57089 1 57086 1 57089 2 3 57088 1 57089 3 57086 1 0 1 57089 4 3 56751 7 0 1 57097 1 57090 1 57097 2 7 57094 1 57097 3 57090 1 0 1 57097 4 7 39494 13 0 1 57107 1 57105 1 57107 2 2 57103 1 57107 3 57105 3 0 1 57107 4 2 40016 7 0 1 57119 1 57100 1 57119 2 19 57117 1 57119 3 57100 5 0 1 57119 4 19 55685 3 0 1 57131 1 57129 1 57131 2 2 57127 1 57131 3 57129 7 0 1 57131 4 2 36157 7 0 1 57139 1 57137 1 57139 2 2 57138 1 57139 3 57137 6 0 1 57139 4 2 30322 6 0 1 57143 1 57138 1 57143 2 5 57135 1 57143 3 57138 9 0 1 57143 4 5 36287 3 0 1 57149 1 57147 1 57149 2 2 57141 1 57149 3 57147 4 0 1 57149 4 2 47915 0 0 1 57163 1 57161 1 57163 2 2 57159 1 57163 3 57161 6 0 1 57163 4 2 36804 8 0 1 57173 1 57171 1 57173 2 2 57169 1 57173 3 57171 4 0 1 57173 4 2 38644 7 0 1 57179 1 57177 1 57179 2 2 57178 1 57179 3 57177 4 0 1 57179 4 2 52261 2 0 1 57191 1 57184 1 57191 2 7 57189 1 57191 3 57184 4 0 1 57191 4 7 42241 5 0 1 57193 1 57188 1 57193 2 5 57192 1 57193 3 57188 2 0 1 57193 4 5 39799 15 0 1 57203 1 57201 1 57203 2 2 57202 1 57203 3 57201 2 0 1 57203 4 2 52152 10 0 1 57221 1 57219 1 57221 2 2 57215 1 57221 3 57219 4 0 1 57221 4 2 31351 3 0 1 57223 1 57220 1 57223 2 3 57221 1 57223 3 57220 7 0 1 57223 4 3 42759 3 0 1 57241 1 57230 1 57241 2 11 57240 1 57241 3 57230 3 0 1 57241 4 11 46815 20 0 1 57251 1 57249 1 57251 2 2 57246 1 57251 3 57249 7 0 1 57251 4 2 45427 3 0 1 57259 1 57257 1 57259 2 2 57258 1 57259 3 57257 4 0 1 57259 4 2 35735 2 0 1 57269 1 57267 1 57269 2 2 57265 1 57269 3 57267 2 0 1 57269 4 2 36576 12 0 1 57271 1 57268 1 57271 2 3 57269 1 57271 3 57268 7 0 1 57271 4 3 49860 6 0 1 57283 1 57281 1 57283 2 2 57279 1 57283 3 57281 6 0 1 57283 4 2 50812 8 0 1 57287 1 57282 1 57287 2 5 57286 1 57287 3 57282 1 0 1 57287 4 5 38078 7 0 1 57301 1 57295 1 57301 2 6 57297 1 57301 3 57295 2 0 1 57301 4 6 37913 2 0 1 57329 1 57326 1 57329 2 3 57323 1 57329 3 57326 1 0 1 57329 4 3 57317 0 0 1 57331 1 57329 1 57331 2 2 57327 1 57331 3 57329 4 0 1 57331 4 2 51427 8 0 1 57347 1 57345 1 57347 2 2 57346 1 57347 3 57345 2 0 1 57347 4 2 57340 8 0 1 57349 1 57347 1 57349 2 2 57343 1 57349 3 57347 6 0 1 57349 4 2 49578 8 0 1 57367 1 57364 1 57367 2 3 57366 1 57367 3 57364 6 0 1 57367 4 3 55950 5 0 1 57373 1 57371 1 57373 2 2 57369 1 57373 3 57371 5 0 1 57373 4 2 31513 15 0 1 57383 1 57378 1 57383 2 5 57382 1 57383 3 57378 15 0 1 57383 4 5 37502 4 0 1 57389 1 57387 1 57389 2 2 57388 1 57389 3 57387 3 0 1 57389 4 2 47299 3 0 1 57397 1 57395 1 57397 2 2 57393 1 57397 3 57395 6 0 1 57397 4 2 47519 6 0 1 57413 1 57411 1 57413 2 2 57407 1 57413 3 57411 4 0 1 57413 4 2 55753 14 0 1 57427 1 57425 1 57427 2 2 57426 1 57427 3 57425 4 0 1 57427 4 2 55666 10 0 1 57457 1 57452 1 57457 2 5 57452 1 57457 3 57452 13 0 1 57457 4 5 45768 10 0 1 57467 1 57465 1 57467 2 2 57463 1 57467 3 57465 3 0 1 57467 4 2 52560 7 0 1 57487 1 57481 1 57487 2 6 57486 1 57487 3 57481 8 0 1 57487 4 6 42883 3 0 1 57493 1 57488 1 57493 2 5 57492 1 57493 3 57488 5 0 1 57493 4 5 44338 6 0 1 57503 1 57498 1 57503 2 5 57501 1 57503 3 57498 2 0 1 57503 4 5 57491 11 0 1 57527 1 57522 1 57527 2 5 57526 1 57527 3 57522 1 0 1 57527 4 5 34433 2 0 1 57529 1 57522 1 57529 2 7 57518 1 57529 3 57522 1 0 1 57529 4 7 29315 0 0 1 57557 1 57555 1 57557 2 2 57553 1 57557 3 57555 2 0 1 57557 4 2 44691 1 0 1 57559 1 57553 1 57559 2 6 57550 1 57559 3 57553 3 0 1 57559 4 6 38120 11 0 1 57571 1 57558 1 57571 2 13 57568 1 57571 3 57558 2 0 1 57571 4 13 56016 4 0 1 57587 1 57585 1 57587 2 2 57586 1 57587 3 57585 2 0 1 57587 4 2 48928 2 0 1 57593 1 57590 1 57593 2 3 57587 1 57593 3 57590 1 0 1 57593 4 3 50111 9 0 1 57601 1 57594 1 57601 2 7 57598 1 57601 3 57594 5 0 1 57601 4 7 51952 16 0 1 57637 1 57635 1 57637 2 2 57633 1 57637 3 57635 2 0 1 57637 4 2 54068 6 0 1 57641 1 57638 1 57641 2 3 57629 1 57641 3 57638 10 0 1 57641 4 3 50846 0 0 1 57649 1 57636 1 57649 2 13 57640 1 57649 3 57636 2 0 1 57649 4 13 47197 28 0 1 57653 1 57651 1 57653 2 2 57649 1 57653 3 57651 3 0 1 57653 4 2 43843 7 0 1 57667 1 57664 1 57667 2 3 57650 1 57667 3 57664 3 0 1 57667 4 3 41653 6 0 1 57679 1 57676 1 57679 2 3 57678 1 57679 3 57676 1 0 1 57679 4 3 54439 3 0 1 57689 1 57686 1 57689 2 3 57683 1 57689 3 57686 5 0 1 57689 4 3 57677 0 0 1 57697 1 57692 1 57697 2 5 57696 1 57697 3 57692 2 0 1 57697 4 5 50189 6 0 1 57709 1 57707 1 57709 2 2 57705 1 57709 3 57707 2 0 1 57709 4 2 51030 6 0 1 57713 1 57710 1 57713 2 3 57712 1 57713 3 57710 1 0 1 57713 4 3 39774 4 0 1 57719 1 57712 1 57719 2 7 57717 1 57719 3 57712 10 0 1 57719 4 7 39353 7 0 1 57727 1 57724 1 57727 2 3 57726 1 57727 3 57724 4 0 1 57727 4 3 33496 5 0 1 57731 1 57729 1 57731 2 2 57724 1 57731 3 57729 2 0 1 57731 4 2 50693 1 0 1 57737 1 57734 1 57737 2 3 57731 1 57737 3 57734 5 0 1 57737 4 3 53953 11 0 1 57751 1 57745 1 57751 2 6 57750 1 57751 3 57745 2 0 1 57751 4 6 52885 3 0 1 57773 1 57770 1 57773 2 3 57771 1 57773 3 57770 11 0 1 57773 4 3 57769 4 0 1 57781 1 57775 1 57781 2 6 57780 1 57781 3 57775 1 0 1 57781 4 6 54988 19 0 1 57787 1 57785 1 57787 2 2 57783 1 57787 3 57785 6 0 1 57787 4 2 31258 8 0 1 57791 1 57765 1 57791 2 26 57784 1 57791 3 57765 2 0 1 57791 4 26 45332 8 0 1 57793 1 57788 1 57793 2 5 57792 1 57793 3 57788 2 0 1 57793 4 5 29330 6 0 1 57803 1 57801 1 57803 2 2 57799 1 57803 3 57801 3 0 1 57803 4 2 35996 8 0 1 57809 1 57806 1 57809 2 3 57804 1 57809 3 57806 3 0 1 57809 4 3 47249 2 0 1 57829 1 57819 1 57829 2 10 57828 1 57829 3 57819 7 0 1 57829 4 10 39378 3 0 1 57839 1 57828 1 57839 2 11 57837 1 57839 3 57828 4 0 1 57839 4 11 47367 3 0 1 57847 1 57844 1 57847 2 3 57845 1 57847 3 57844 6 0 1 57847 4 3 49112 6 0 1 57853 1 57848 1 57853 2 5 57848 1 57853 3 57848 1 0 1 57853 4 5 43173 10 0 1 57859 1 57857 1 57859 2 2 57855 1 57859 3 57857 6 0 1 57859 4 2 31091 8 0 1 57881 1 57878 1 57881 2 3 57876 1 57881 3 57878 4 0 1 57881 4 3 57343 2 0 1 57899 1 57897 1 57899 2 2 57895 1 57899 3 57897 11 0 1 57899 4 2 36940 8 0 1 57901 1 57899 1 57901 2 2 57897 1 57901 3 57899 2 0 1 57901 4 2 43209 12 0 1 57917 1 57915 1 57917 2 2 57911 1 57917 3 57915 2 0 1 57917 4 2 43655 1 0 1 57923 1 57921 1 57923 2 2 57922 1 57923 3 57921 3 0 1 57923 4 2 57916 8 0 1 57943 1 57938 1 57943 2 5 57942 1 57943 3 57938 3 0 1 57943 4 5 48885 5 0 1 57947 1 57942 1 57947 2 5 57935 1 57947 3 57942 6 0 1 57947 4 5 56021 5 0 1 57973 1 57968 1 57973 2 5 57968 1 57973 3 57968 6 0 1 57973 4 5 53894 7 0 1 57977 1 57974 1 57977 2 3 57976 1 57977 3 57974 5 0 1 57977 4 3 32248 6 0 1 57991 1 57985 1 57991 2 6 57989 1 57991 3 57985 3 0 1 57991 4 6 46233 3 0 1 58013 1 58011 1 58013 2 2 58009 1 58013 3 58011 3 0 1 58013 4 2 34641 7 0 1 58027 1 58025 1 58027 2 2 58023 1 58027 3 58025 6 0 1 58027 4 2 53939 8 0 1 58031 1 58024 1 58031 2 7 58029 1 58031 3 58024 2 0 1 58031 4 7 46714 5 0 1 58043 1 58041 1 58043 2 2 58042 1 58043 3 58041 2 0 1 58043 4 2 49155 4 0 1 58049 1 58046 1 58049 2 3 58043 1 58049 3 58046 1 0 1 58049 4 3 58037 0 0 1 58057 1 58050 1 58057 2 7 58050 1 58057 3 58050 7 0 1 58057 4 7 30538 14 0 1 58061 1 58058 1 58061 2 3 58054 1 58061 3 58058 1 0 1 58061 4 3 38376 4 0 1 58067 1 58065 1 58067 2 2 58063 1 58067 3 58065 3 0 1 58067 4 2 55226 8 0 1 58073 1 58068 1 58073 2 5 58068 1 58073 3 58068 3 0 1 58073 4 5 38829 2 0 1 58099 1 58089 1 58099 2 10 58098 1 58099 3 58089 3 0 1 58099 4 10 38520 2 0 1 58109 1 58107 1 58109 2 2 58104 1 58109 3 58107 3 0 1 58109 4 2 48748 8 0 1 58111 1 58099 1 58111 2 12 58110 1 58111 3 58099 3 0 1 58111 4 12 34656 5 0 1 58129 1 58116 1 58129 2 13 58116 1 58129 3 58116 2 0 1 58129 4 13 58090 0 0 1 58147 1 58144 1 58147 2 3 58142 1 58147 3 58144 4 0 1 58147 4 3 46811 3 0 1 58151 1 58144 1 58151 2 7 58150 1 58151 3 58144 1 0 1 58151 4 7 40891 2 0 1 58153 1 58143 1 58153 2 10 58148 1 58153 3 58143 5 0 1 58153 4 10 39832 0 0 1 58169 1 58163 1 58169 2 6 58163 1 58169 3 58163 4 0 1 58169 4 6 43378 0 0 1 58171 1 58169 1 58171 2 2 58167 1 58171 3 58169 2 0 1 58171 4 2 51474 8 0 1 58189 1 58183 1 58189 2 6 58188 1 58189 3 58183 1 0 1 58189 4 6 48887 8 0 1 58193 1 58190 1 58193 2 3 58186 1 58193 3 58190 1 0 1 58193 4 3 56340 1 0 1 58199 1 58192 1 58199 2 7 58197 1 58199 3 58192 2 0 1 58199 4 7 42928 4 0 1 58207 1 58202 1 58207 2 5 58206 1 58207 3 58202 3 0 1 58207 4 5 32800 2 0 1 58211 1 58209 1 58211 2 2 58207 1 58211 3 58209 3 0 1 58211 4 2 43921 15 0 1 58217 1 58214 1 58217 2 3 58211 1 58217 3 58214 1 0 1 58217 4 3 48348 1 0 1 58229 1 58227 1 58229 2 2 58225 1 58229 3 58227 3 0 1 58229 4 2 51018 1 0 1 58231 1 58225 1 58231 2 6 58229 1 58231 3 58225 1 0 1 58231 4 6 53033 3 0 1 58237 1 58222 1 58237 2 15 58235 1 58237 3 58222 3 0 1 58237 4 15 31925 0 0 1 58243 1 58241 1 58243 2 2 58242 1 58243 3 58241 2 0 1 58243 4 2 57340 2 0 1 58271 1 58260 1 58271 2 11 58267 1 58271 3 58260 2 0 1 58271 4 11 37635 5 0 1 58309 1 58303 1 58309 2 6 58305 1 58309 3 58303 4 0 1 58309 4 6 58301 12 0 1 58313 1 58310 1 58313 2 3 58308 1 58313 3 58310 1 0 1 58313 4 3 35319 0 0 1 58321 1 58310 1 58321 2 11 58316 1 58321 3 58310 2 0 1 58321 4 11 58302 24 0 1 58337 1 58334 1 58337 2 3 58332 1 58337 3 58334 3 0 1 58337 4 3 29604 0 0 1 58363 1 58361 1 58363 2 2 58359 1 58363 3 58361 5 0 1 58363 4 2 41459 8 0 1 58367 1 58360 1 58367 2 7 58365 1 58367 3 58360 2 0 1 58367 4 7 43398 4 0 1 58369 1 58362 1 58369 2 7 58362 1 58369 3 58362 1 0 1 58369 4 7 30188 0 0 1 58379 1 58377 1 58379 2 2 58378 1 58379 3 58377 7 0 1 58379 4 2 57542 4 0 1 58391 1 58380 1 58391 2 11 58389 1 58391 3 58380 11 0 1 58391 4 11 55344 3 0 1 58393 1 58388 1 58393 2 5 58388 1 58393 3 58388 2 0 1 58393 4 5 44634 10 0 1 58403 1 58401 1 58403 2 2 58399 1 58403 3 58401 3 0 1 58403 4 2 35770 7 0 1 58411 1 58409 1 58411 2 2 58410 1 58411 3 58409 4 0 1 58411 4 2 31595 6 0 1 58417 1 58412 1 58417 2 5 58414 1 58417 3 58412 6 0 1 58417 4 5 58406 14 0 1 58427 1 58425 1 58427 2 2 58423 1 58427 3 58425 3 0 1 58427 4 2 47674 7 0 1 58439 1 58422 1 58439 2 17 58435 1 58439 3 58422 2 0 1 58439 4 17 33992 7 0 1 58441 1 58428 1 58441 2 13 58440 1 58441 3 58428 1 0 1 58441 4 13 40655 14 0 1 58451 1 58441 1 58451 2 10 58449 1 58451 3 58441 3 0 1 58451 4 10 58433 11 0 1 58453 1 58451 1 58453 2 2 58452 1 58453 3 58451 2 0 1 58453 4 2 53853 3 0 1 58477 1 58472 1 58477 2 5 58476 1 58477 3 58472 1 0 1 58477 4 5 42959 3 0 1 58481 1 58475 1 58481 2 6 58480 1 58481 3 58475 2 0 1 58481 4 6 29511 4 0 1 58511 1 58498 1 58511 2 13 58506 1 58511 3 58498 13 0 1 58511 4 13 41376 6 0 1 58537 1 58530 1 58537 2 7 58530 1 58537 3 58530 3 0 1 58537 4 7 48187 17 0 1 58543 1 58537 1 58543 2 6 58540 1 58543 3 58537 2 0 1 58543 4 6 53814 4 0 1 58549 1 58547 1 58549 2 2 58545 1 58549 3 58547 2 0 1 58549 4 2 58008 12 0 1 58567 1 58561 1 58567 2 6 58564 1 58567 3 58561 1 0 1 58567 4 6 34218 7 0 1 58573 1 58571 1 58573 2 2 58569 1 58573 3 58571 6 0 1 58573 4 2 54611 19 0 1 58579 1 58577 1 58579 2 2 58578 1 58579 3 58577 5 0 1 58579 4 2 35266 2 0 1 58601 1 58598 1 58601 2 3 58595 1 58601 3 58598 6 0 1 58601 4 3 58589 0 0 1 58603 1 58601 1 58603 2 2 58602 1 58603 3 58601 2 0 1 58603 4 2 38029 2 0 1 58613 1 58611 1 58613 2 2 58606 1 58613 3 58611 4 0 1 58613 4 2 37260 5 0 1 58631 1 58612 1 58631 2 19 58627 1 58631 3 58612 1 0 1 58631 4 19 53136 5 0 1 58657 1 58652 1 58657 2 5 58652 1 58657 3 58652 2 0 1 58657 4 5 43645 15 0 1 58661 1 58659 1 58661 2 2 58657 1 58661 3 58659 2 0 1 58661 4 2 56239 6 0 1 58679 1 58668 1 58679 2 11 58678 1 58679 3 58668 14 0 1 58679 4 11 43631 2 0 1 58687 1 58681 1 58687 2 6 58686 1 58687 3 58681 2 0 1 58687 4 6 46188 10 0 1 58693 1 58691 1 58693 2 2 58692 1 58693 3 58691 2 0 1 58693 4 2 35548 3 0 1 58699 1 58697 1 58699 2 2 58693 1 58699 3 58697 5 0 1 58699 4 2 46234 7 0 1 58711 1 58705 1 58711 2 6 58710 1 58711 3 58705 1 0 1 58711 4 6 50134 3 0 1 58727 1 58722 1 58727 2 5 58725 1 58727 3 58722 3 0 1 58727 4 5 58723 3 0 1 58733 1 58731 1 58733 2 2 58732 1 58733 3 58731 3 0 1 58733 4 2 51995 6 0 1 58741 1 58739 1 58741 2 2 58737 1 58741 3 58739 6 0 1 58741 4 2 51466 6 0 1 58757 1 58755 1 58757 2 2 58756 1 58757 3 58755 2 0 1 58757 4 2 57521 3 0 1 58763 1 58761 1 58763 2 2 58762 1 58763 3 58761 3 0 1 58763 4 2 33436 4 0 1 58771 1 58760 1 58771 2 11 58770 1 58771 3 58760 1 0 1 58771 4 11 31439 2 0 1 58787 1 58785 1 58787 2 2 58783 1 58787 3 58785 3 0 1 58787 4 2 53034 13 0 1 58789 1 58787 1 58789 2 2 58788 1 58789 3 58787 5 0 1 58789 4 2 43414 9 0 1 58831 1 58820 1 58831 2 11 58830 1 58831 3 58820 1 0 1 58831 4 11 49291 2 0 1 58889 1 58886 1 58889 2 3 58888 1 58889 3 58886 5 0 1 58889 4 3 55753 4 0 1 58897 1 58892 1 58897 2 5 58892 1 58897 3 58892 6 0 1 58897 4 5 42970 15 0 1 58901 1 58899 1 58901 2 2 58900 1 58901 3 58899 9 0 1 58901 4 2 44936 3 0 1 58907 1 58905 1 58907 2 2 58901 1 58907 3 58905 4 0 1 58907 4 2 33592 7 0 1 58909 1 58907 1 58909 2 2 58905 1 58909 3 58907 2 0 1 58909 4 2 49635 12 0 1 58913 1 58910 1 58913 2 3 58912 1 58913 3 58910 5 0 1 58913 4 3 31211 7 0 1 58921 1 58908 1 58921 2 13 58908 1 58921 3 58908 15 0 1 58921 4 13 58882 0 0 1 58937 1 58934 1 58937 2 3 58936 1 58937 3 58934 1 0 1 58937 4 3 33022 11 0 1 58943 1 58938 1 58943 2 5 58938 1 58943 3 58938 2 0 1 58943 4 5 44689 6 0 1 58963 1 58960 1 58963 2 3 58958 1 58963 3 58960 6 0 1 58963 4 3 52617 6 0 1 58967 1 58962 1 58967 2 5 58966 1 58967 3 58962 3 0 1 58967 4 5 57572 7 0 1 58979 1 58977 1 58979 2 2 58975 1 58979 3 58977 3 0 1 58979 4 2 37095 7 0 1 58991 1 58984 1 58991 2 7 58990 1 58991 3 58984 8 0 1 58991 4 7 58982 4 0 1 58997 1 58994 1 58997 2 3 58995 1 58997 3 58994 5 0 1 58997 4 3 41475 14 0 1 59009 1 59006 1 59009 2 3 59002 1 59009 3 59006 1 0 1 59009 4 3 41755 4 0 1 59011 1 59009 1 59011 2 2 59007 1 59011 3 59009 4 0 1 59011 4 2 46242 8 0 1 59021 1 59019 1 59021 2 2 59017 1 59021 3 59019 2 0 1 59021 4 2 44130 6 0 1 59023 1 59018 1 59023 2 5 59021 1 59023 3 59018 6 0 1 59023 4 5 59007 18 0 1 59029 1 59027 1 59029 2 2 59028 1 59029 3 59027 5 0 1 59029 4 2 52110 7 0 1 59051 1 59041 1 59051 2 10 59049 1 59051 3 59041 5 0 1 59051 4 10 59039 6 0 1 59053 1 59038 1 59053 2 15 59051 1 59053 3 59038 4 0 1 59053 4 15 42434 7 0 1 59063 1 59058 1 59063 2 5 59061 1 59063 3 59058 2 0 1 59063 4 5 59059 3 0 1 59069 1 59067 1 59069 2 2 59065 1 59069 3 59067 3 0 1 59069 4 2 47659 1 0 1 59077 1 59072 1 59077 2 5 59074 1 59077 3 59072 1 0 1 59077 4 5 32079 1 0 1 59083 1 59081 1 59083 2 2 59082 1 59083 3 59081 5 0 1 59083 4 2 31074 2 0 1 59093 1 59090 1 59093 2 3 59091 1 59093 3 59090 1 0 1 59093 4 3 35731 14 0 1 59107 1 59105 1 59107 2 2 59103 1 59107 3 59105 2 0 1 59107 4 2 45262 1 0 1 59113 1 59106 1 59113 2 7 59106 1 59113 3 59106 1 0 1 59113 4 7 49406 20 0 1 59119 1 59116 1 59119 2 3 59114 1 59119 3 59116 1 0 1 59119 4 3 42179 7 0 1 59123 1 59121 1 59123 2 2 59118 1 59123 3 59121 4 0 1 59123 4 2 56145 3 0 1 59141 1 59138 1 59141 2 3 59139 1 59141 3 59138 4 0 1 59141 4 3 39886 14 0 1 59149 1 59147 1 59149 2 2 59148 1 59149 3 59147 5 0 1 59149 4 2 58239 3 0 1 59159 1 59152 1 59159 2 7 59158 1 59159 3 59152 2 0 1 59159 4 7 59150 4 0 1 59167 1 59164 1 59167 2 3 59165 1 59167 3 59164 3 0 1 59167 4 3 59163 4 0 1 59183 1 59178 1 59183 2 5 59178 1 59183 3 59178 1 0 1 59183 4 5 47171 7 0 1 59197 1 59195 1 59197 2 2 59196 1 59197 3 59195 2 0 1 59197 4 2 30666 3 0 1 59207 1 59202 1 59207 2 5 59206 1 59207 3 59202 2 0 1 59207 4 5 44946 5 0 1 59209 1 59198 1 59209 2 11 59206 1 59209 3 59198 1 0 1 59209 4 11 29877 10 0 1 59219 1 59217 1 59219 2 2 59207 1 59219 3 59217 3 0 1 59219 4 2 51679 2 0 1 59221 1 59219 1 59221 2 2 59217 1 59221 3 59219 2 0 1 59221 4 2 45722 6 0 1 59233 1 59228 1 59233 2 5 59232 1 59233 3 59228 1 0 1 59233 4 5 39196 6 0 1 59239 1 59236 1 59239 2 3 59234 1 59239 3 59236 5 0 1 59239 4 3 36481 6 0 1 59243 1 59241 1 59243 2 2 59239 1 59243 3 59241 3 0 1 59243 4 2 54074 8 0 1 59263 1 59260 1 59263 2 3 59262 1 59263 3 59260 3 0 1 59263 4 3 55226 5 0 1 59273 1 59270 1 59273 2 3 59267 1 59273 3 59270 1 0 1 59273 4 3 40628 11 0 1 59281 1 59274 1 59281 2 7 59274 1 59281 3 59274 10 0 1 59281 4 7 56883 0 0 1 59333 1 59331 1 59333 2 2 59329 1 59333 3 59331 4 0 1 59333 4 2 48426 6 0 1 59341 1 59327 1 59341 2 14 59340 1 59341 3 59327 7 0 1 59341 4 14 53520 7 0 1 59351 1 59338 1 59351 2 13 59347 1 59351 3 59338 1 0 1 59351 4 13 38445 6 0 1 59357 1 59355 1 59357 2 2 59353 1 59357 3 59355 3 0 1 59357 4 2 41315 7 0 1 59359 1 59353 1 59359 2 6 59358 1 59359 3 59353 3 0 1 59359 4 6 58297 2 0 1 59369 1 59366 1 59369 2 3 59368 1 59369 3 59366 1 0 1 59369 4 3 48940 4 0 1 59377 1 59372 1 59377 2 5 59376 1 59377 3 59372 1 0 1 59377 4 5 57603 6 0 1 59387 1 59385 1 59387 2 2 59383 1 59387 3 59385 2 0 1 59387 4 2 33537 7 0 1 59393 1 59388 1 59393 2 5 59388 1 59393 3 59388 1 0 1 59393 4 5 32290 8 0 1 59399 1 59392 1 59399 2 7 59398 1 59399 3 59392 2 0 1 59399 4 7 35888 2 0 1 59407 1 59404 1 59407 2 3 59406 1 59407 3 59404 4 0 1 59407 4 3 30026 5 0 1 59417 1 59414 1 59417 2 3 59416 1 59417 3 59414 9 0 1 59417 4 3 40071 4 0 1 59419 1 59417 1 59419 2 2 59418 1 59419 3 59417 6 0 1 59419 4 2 59412 8 0 1 59441 1 59438 1 59441 2 3 59440 1 59441 3 59438 3 0 1 59441 4 3 40468 4 0 1 59443 1 59441 1 59443 2 2 59442 1 59443 3 59441 2 0 1 59443 4 2 34764 10 0 1 59447 1 59442 1 59447 2 5 59445 1 59447 3 59442 1 0 1 59447 4 5 54195 8 0 1 59453 1 59451 1 59453 2 2 59449 1 59453 3 59451 3 0 1 59453 4 2 51754 9 0 1 59467 1 59465 1 59467 2 2 59463 1 59467 3 59465 6 0 1 59467 4 2 40603 8 0 1 59471 1 59460 1 59471 2 11 59469 1 59471 3 59460 1 0 1 59471 4 11 56163 7 0 1 59473 1 59463 1 59473 2 10 59472 1 59473 3 59463 7 0 1 59473 4 10 39154 6 0 1 59497 1 59482 1 59497 2 15 59494 1 59497 3 59482 3 0 1 59497 4 15 49261 32 0 1 59509 1 59499 1 59509 2 10 59505 1 59509 3 59499 2 0 1 59509 4 10 49122 2 0 1 59513 1 59510 1 59513 2 3 59507 1 59513 3 59510 1 0 1 59513 4 3 40979 1 0 1 59539 1 59537 1 59539 2 2 59534 1 59539 3 59537 4 0 1 59539 4 2 49508 2 0 1 59557 1 59555 1 59557 2 2 59553 1 59557 3 59555 4 0 1 59557 4 2 41602 6 0 1 59561 1 59558 1 59561 2 3 59560 1 59561 3 59558 1 0 1 59561 4 3 39592 7 0 1 59567 1 59562 1 59567 2 5 59566 1 59567 3 59562 1 0 1 59567 4 5 45015 2 0 1 59581 1 59575 1 59581 2 6 59580 1 59581 3 59575 6 0 1 59581 4 6 44209 7 0 1 59611 1 59609 1 59611 2 2 59610 1 59611 3 59609 4 0 1 59611 4 2 39105 7 0 1 59617 1 59610 1 59617 2 7 59614 1 59617 3 59610 7 0 1 59617 4 7 54965 10 0 1 59621 1 59618 1 59621 2 3 59614 1 59621 3 59618 16 0 1 59621 4 3 56091 4 0 1 59627 1 59625 1 59627 2 2 59623 1 59627 3 59625 3 0 1 59627 4 2 57389 7 0 1 59629 1 59627 1 59629 2 2 59625 1 59629 3 59627 4 0 1 59629 4 2 58314 6 0 1 59651 1 59649 1 59651 2 2 59642 1 59651 3 59649 2 0 1 59651 4 2 47557 1 0 1 59659 1 59656 1 59659 2 3 59652 1 59659 3 59656 1 0 1 59659 4 3 54020 5 0 1 59663 1 59658 1 59663 2 5 59661 1 59663 3 59658 13 0 1 59663 4 5 43156 10 0 1 59669 1 59667 1 59669 2 2 59665 1 59669 3 59667 3 0 1 59669 4 2 33597 12 0 1 59671 1 59659 1 59671 2 12 59669 1 59671 3 59659 5 0 1 59671 4 12 38104 3 0 1 59693 1 59691 1 59693 2 2 59688 1 59693 3 59691 12 0 1 59693 4 2 34867 2 0 1 59699 1 59697 1 59699 2 2 59698 1 59699 3 59697 16 0 1 59699 4 2 30989 2 0 1 59707 1 59704 1 59707 2 3 59706 1 59707 3 59704 13 0 1 59707 4 3 46798 5 0 1 59723 1 59721 1 59723 2 2 59716 1 59723 3 59721 7 0 1 59723 4 2 54408 1 0 1 59729 1 59726 1 59729 2 3 59724 1 59729 3 59726 1 0 1 59729 4 3 56858 2 0 1 59743 1 59740 1 59743 2 3 59742 1 59743 3 59740 5 0 1 59743 4 3 40344 5 0 1 59747 1 59745 1 59747 2 2 59737 1 59747 3 59745 7 0 1 59747 4 2 51354 2 0 1 59753 1 59748 1 59753 2 5 59742 1 59753 3 59748 1 0 1 59753 4 5 57333 5 0 1 59771 1 59769 1 59771 2 2 59770 1 59771 3 59769 7 0 1 59771 4 2 59764 8 0 1 59779 1 59769 1 59779 2 10 59778 1 59779 3 59769 2 0 1 59779 4 10 59132 5 0 1 59791 1 59788 1 59791 2 3 59790 1 59791 3 59788 1 0 1 59791 4 3 36138 3 0 1 59797 1 59795 1 59797 2 2 59796 1 59797 3 59795 6 0 1 59797 4 2 40340 7 0 1 59809 1 59792 1 59809 2 17 59808 1 59809 3 59792 2 0 1 59809 4 17 42116 30 0 1 59833 1 59828 1 59833 2 5 59832 1 59833 3 59828 1 0 1 59833 4 5 46665 11 0 1 59863 1 59858 1 59863 2 5 59862 1 59863 3 59858 3 0 1 59863 4 5 33091 16 0 1 59879 1 59865 1 59879 2 14 59878 1 59879 3 59865 1 0 1 59879 4 14 45363 2 0 1 59887 1 59884 1 59887 2 3 59885 1 59887 3 59884 7 0 1 59887 4 3 57869 3 0 1 59921 1 59918 1 59921 2 3 59914 1 59921 3 59918 10 0 1 59921 4 3 55013 1 0 1 59929 1 59910 1 59929 2 19 59926 1 59929 3 59910 7 0 1 59929 4 19 51620 22 0 1 59951 1 59940 1 59951 2 11 59948 1 59951 3 59940 4 0 1 59951 4 11 57454 6 0 1 59957 1 59955 1 59957 2 2 59950 1 59957 3 59955 4 0 1 59957 4 2 49111 5 0 1 59971 1 59968 1 59971 2 3 59970 1 59971 3 59968 4 0 1 59971 4 3 59088 7 0 1 59981 1 59979 1 59981 2 2 59976 1 59981 3 59979 8 0 1 59981 4 2 47505 12 0 1 59999 1 59992 1 59999 2 7 59998 1 59999 3 59992 3 0 1 59999 4 7 58199 3 0 1 60013 1 60007 1 60013 2 6 60011 1 60013 3 60007 7 0 1 60013 4 6 52216 4 0 1 60017 1 60014 1 60017 2 3 60006 1 60017 3 60014 4 0 1 60017 4 3 31524 1 0 1 60029 1 60027 1 60029 2 2 60025 1 60029 3 60027 2 0 1 60029 4 2 51903 7 0 1 60037 1 60035 1 60037 2 2 60036 1 60037 3 60035 2 0 1 60037 4 2 38532 3 0 1 60041 1 60038 1 60041 2 3 60036 1 60041 3 60038 6 0 1 60041 4 3 51746 2 0 1 60077 1 60075 1 60077 2 2 60076 1 60077 3 60075 3 0 1 60077 4 2 39408 3 0 1 60083 1 60081 1 60083 2 2 60078 1 60083 3 60081 4 0 1 60083 4 2 46956 0 0 1 60089 1 60086 1 60089 2 3 60088 1 60089 3 60086 1 0 1 60089 4 3 43037 4 0 1 60091 1 60089 1 60091 2 2 60090 1 60091 3 60089 4 0 1 60091 4 2 43323 6 0 1 60101 1 60098 1 60101 2 3 60099 1 60101 3 60098 3 0 1 60101 4 3 60097 4 0 1 60103 1 60098 1 60103 2 5 60101 1 60103 3 60098 9 0 1 60103 4 5 60091 11 0 1 60107 1 60105 1 60107 2 2 60106 1 60107 3 60105 2 0 1 60107 4 2 57860 4 0 1 60127 1 60124 1 60127 2 3 60125 1 60127 3 60124 5 0 1 60127 4 3 45764 6 0 1 60133 1 60127 1 60133 2 6 60132 1 60133 3 60127 1 0 1 60133 4 6 55618 7 0 1 60139 1 60136 1 60139 2 3 60138 1 60139 3 60136 4 0 1 60139 4 3 38015 6 0 1 60149 1 60147 1 60149 2 2 60148 1 60149 3 60147 3 0 1 60149 4 2 60142 8 0 1 60161 1 60158 1 60161 2 3 60155 1 60161 3 60158 1 0 1 60161 4 3 60149 0 0 1 60167 1 60162 1 60167 2 5 60166 1 60167 3 60162 5 0 1 60167 4 5 44146 2 0 1 60169 1 60158 1 60169 2 11 60168 1 60169 3 60158 5 0 1 60169 4 11 41275 14 0 1 60209 1 60206 1 60209 2 3 60208 1 60209 3 60206 13 0 1 60209 4 3 39868 4 0 1 60217 1 60212 1 60217 2 5 60212 1 60217 3 60212 3 0 1 60217 4 5 36215 12 0 1 60223 1 60220 1 60223 2 3 60221 1 60223 3 60220 1 0 1 60223 4 3 60215 10 0 1 60251 1 60245 1 60251 2 6 60250 1 60251 3 60245 1 0 1 60251 4 6 55705 2 0 1 60257 1 60254 1 60257 2 3 60256 1 60257 3 60254 3 0 1 60257 4 3 58724 7 0 1 60259 1 60256 1 60259 2 3 60250 1 60259 3 60256 3 0 1 60259 4 3 31861 6 0 1 60271 1 60268 1 60271 2 3 60270 1 60271 3 60268 3 0 1 60271 4 3 36772 10 0 1 60289 1 60282 1 60289 2 7 60286 1 60289 3 60282 1 0 1 60289 4 7 56173 16 0 1 60293 1 60291 1 60293 2 2 60288 1 60293 3 60291 4 0 1 60293 4 2 55589 0 0 1 60317 1 60315 1 60317 2 2 60316 1 60317 3 60315 2 0 1 60317 4 2 36105 4 0 1 60331 1 60319 1 60331 2 12 60330 1 60331 3 60319 1 0 1 60331 4 12 30701 5 0 1 60337 1 60332 1 60337 2 5 60336 1 60337 3 60332 5 0 1 60337 4 5 53239 12 0 1 60343 1 60340 1 60343 2 3 60342 1 60343 3 60340 9 0 1 60343 4 3 40662 5 0 1 60353 1 60350 1 60353 2 3 60352 1 60353 3 60350 5 0 1 60353 4 3 43662 4 0 1 60373 1 60371 1 60373 2 2 60372 1 60373 3 60371 5 0 1 60373 4 2 51163 6 0 1 60383 1 60378 1 60383 2 5 60378 1 60383 3 60378 1 0 1 60383 4 5 56436 6 0 1 60397 1 60392 1 60397 2 5 60396 1 60397 3 60392 5 0 1 60397 4 5 36324 7 0 1 60413 1 60411 1 60413 2 2 60412 1 60413 3 60411 3 0 1 60413 4 2 42023 19 0 1 60427 1 60424 1 60427 2 3 60420 1 60427 3 60424 9 0 1 60427 4 3 34137 5 0 1 60443 1 60441 1 60443 2 2 60442 1 60443 3 60441 2 0 1 60443 4 2 32304 4 0 1 60449 1 60446 1 60449 2 3 60435 1 60449 3 60446 4 0 1 60449 4 3 45079 2 0 1 60457 1 60444 1 60457 2 13 60456 1 60457 3 60444 6 0 1 60457 4 13 44255 11 0 1 60493 1 60491 1 60493 2 2 60492 1 60493 3 60491 6 0 1 60493 4 2 59943 6 0 1 60497 1 60494 1 60497 2 3 60496 1 60497 3 60494 5 0 1 60497 4 3 55621 6 0 1 60509 1 60507 1 60509 2 2 60505 1 60509 3 60507 2 0 1 60509 4 2 43962 6 0 1 60521 1 60518 1 60521 2 3 60520 1 60521 3 60518 4 0 1 60521 4 3 49677 4 0 1 60527 1 60522 1 60527 2 5 60526 1 60527 3 60522 2 0 1 60527 4 5 55656 4 0 1 60539 1 60537 1 60539 2 2 60535 1 60539 3 60537 3 0 1 60539 4 2 57889 7 0 1 60589 1 60587 1 60589 2 2 60579 1 60589 3 60587 2 0 1 60589 4 2 45582 2 0 1 60601 1 60590 1 60601 2 11 60596 1 60601 3 60590 4 0 1 60601 4 11 59044 16 0 1 60607 1 60604 1 60607 2 3 60606 1 60607 3 60604 1 0 1 60607 4 3 46733 5 0 1 60611 1 60601 1 60611 2 10 60608 1 60611 3 60601 2 0 1 60611 4 10 45565 4 0 1 60617 1 60614 1 60617 2 3 60612 1 60617 3 60614 7 0 1 60617 4 3 37458 0 0 1 60623 1 60618 1 60623 2 5 60622 1 60623 3 60618 8 0 1 60623 4 5 38247 2 0 1 60631 1 60625 1 60631 2 6 60629 1 60631 3 60625 6 0 1 60631 4 6 37775 4 0 1 60637 1 60635 1 60637 2 2 60636 1 60637 3 60635 2 0 1 60637 4 2 42535 9 0 1 60647 1 60642 1 60647 2 5 60642 1 60647 3 60642 3 0 1 60647 4 5 31472 9 0 1 60649 1 60638 1 60649 2 11 60648 1 60649 3 60638 1 0 1 60649 4 11 57391 24 0 1 60659 1 60657 1 60659 2 2 60655 1 60659 3 60657 2 0 1 60659 4 2 37394 8 0 1 60661 1 60659 1 60661 2 2 60660 1 60661 3 60659 5 0 1 60661 4 2 48780 3 0 1 60679 1 60676 1 60679 2 3 60677 1 60679 3 60676 1 0 1 60679 4 3 35802 3 0 1 60689 1 60686 1 60689 2 3 60688 1 60689 3 60686 1 0 1 60689 4 3 48859 7 0 1 60703 1 60700 1 60703 2 3 60701 1 60703 3 60700 6 0 1 60703 4 3 42426 17 0 1 60719 1 60712 1 60719 2 7 60715 1 60719 3 60712 1 0 1 60719 4 7 59617 6 0 1 60727 1 60722 1 60727 2 5 60726 1 60727 3 60722 3 0 1 60727 4 5 41599 12 0 1 60733 1 60731 1 60733 2 2 60729 1 60733 3 60731 4 0 1 60733 4 2 41358 10 0 1 60737 1 60734 1 60737 2 3 60736 1 60737 3 60734 4 0 1 60737 4 3 49217 6 0 1 60757 1 60755 1 60757 2 2 60753 1 60757 3 60755 6 0 1 60757 4 2 37347 9 0 1 60761 1 60755 1 60761 2 6 60758 1 60761 3 60755 1 0 1 60761 4 6 34826 0 0 1 60763 1 60760 1 60763 2 3 60762 1 60763 3 60760 4 0 1 60763 4 3 48750 5 0 1 60773 1 60771 1 60773 2 2 60769 1 60773 3 60771 2 0 1 60773 4 2 53959 1 0 1 60779 1 60777 1 60779 2 2 60778 1 60779 3 60777 3 0 1 60779 4 2 43256 4 0 1 60793 1 60788 1 60793 2 5 60792 1 60793 3 60788 1 0 1 60793 4 5 42116 6 0 1 60811 1 60809 1 60811 2 2 60807 1 60811 3 60809 4 0 1 60811 4 2 49132 8 0 1 60821 1 60819 1 60821 2 2 60820 1 60821 3 60819 3 0 1 60821 4 2 58097 3 0 1 60859 1 60856 1 60859 2 3 60854 1 60859 3 60856 8 0 1 60859 4 3 32881 3 0 1 60869 1 60867 1 60869 2 2 60865 1 60869 3 60867 2 0 1 60869 4 2 43138 7 0 1 60887 1 60880 1 60887 2 7 60885 1 60887 3 60880 2 0 1 60887 4 7 41522 10 0 1 60889 1 60868 1 60889 2 21 60888 1 60889 3 60868 6 0 1 60889 4 21 30890 8 0 1 60899 1 60897 1 60899 2 2 60890 1 60899 3 60897 3 0 1 60899 4 2 40968 1 0 1 60901 1 60899 1 60901 2 2 60897 1 60901 3 60899 2 0 1 60901 4 2 59505 6 0 1 60913 1 60908 1 60913 2 5 60912 1 60913 3 60908 2 0 1 60913 4 5 37275 6 0 1 60917 1 60915 1 60917 2 2 60916 1 60917 3 60915 2 0 1 60917 4 2 56743 3 0 1 60919 1 60916 1 60919 2 3 60917 1 60919 3 60916 1 0 1 60919 4 3 54223 6 0 1 60923 1 60921 1 60923 2 2 60918 1 60923 3 60921 10 0 1 60923 4 2 44157 3 0 1 60937 1 60927 1 60937 2 10 60936 1 60937 3 60927 5 0 1 60937 4 10 51187 21 0 1 60943 1 60938 1 60943 2 5 60942 1 60943 3 60938 1 0 1 60943 4 5 31353 2 0 1 60953 1 60950 1 60953 2 3 60952 1 60953 3 60950 5 0 1 60953 4 3 38273 4 0 1 60961 1 60954 1 60961 2 7 60954 1 60961 3 60954 3 0 1 60961 4 7 46153 0 0 1 61001 1 60998 1 61001 2 3 61000 1 61001 3 60998 3 0 1 61001 4 3 55315 7 0 1 61007 1 61002 1 61007 2 5 61005 1 61007 3 61002 1 0 1 61007 4 5 49699 14 0 1 61027 1 61025 1 61027 2 2 61023 1 61027 3 61025 6 0 1 61027 4 2 41014 8 0 1 61031 1 61009 1 61031 2 22 61028 1 61031 3 61009 4 0 1 61031 4 22 49802 8 0 1 61043 1 61041 1 61043 2 2 61042 1 61043 3 61041 3 0 1 61043 4 2 41886 20 0 1 61051 1 61048 1 61051 2 3 61040 1 61051 3 61048 9 0 1 61051 4 3 53312 1 0 1 61057 1 61052 1 61057 2 5 61056 1 61057 3 61052 5 0 1 61057 4 5 31428 6 0 1 61091 1 61089 1 61091 2 2 61087 1 61091 3 61089 2 0 1 61091 4 2 44076 7 0 1 61099 1 61097 1 61099 2 2 61098 1 61099 3 61097 5 0 1 61099 4 2 34487 6 0 1 61121 1 61118 1 61121 2 3 61116 1 61121 3 61118 9 0 1 61121 4 3 49149 2 0 1 61129 1 61122 1 61129 2 7 61120 1 61129 3 61122 2 0 1 61129 4 7 46243 2 0 1 61141 1 61135 1 61141 2 6 61140 1 61141 3 61135 8 0 1 61141 4 6 53310 7 0 1 61151 1 61120 1 61151 2 31 61150 1 61151 3 61120 1 0 1 61151 4 31 59965 2 0 1 61153 1 61143 1 61153 2 10 61150 1 61153 3 61143 3 0 1 61153 4 10 37800 8 0 1 61169 1 61166 1 61169 2 3 61163 1 61169 3 61166 4 0 1 61169 4 3 61157 0 0 1 61211 1 61209 1 61211 2 2 61203 1 61211 3 61209 4 0 1 61211 4 2 49876 2 0 1 61223 1 61218 1 61223 2 5 61221 1 61223 3 61218 1 0 1 61223 4 5 34750 5 0 1 61231 1 61224 1 61231 2 7 61228 1 61231 3 61224 1 0 1 61231 4 7 40021 0 0 1 61253 1 61251 1 61253 2 2 61249 1 61253 3 61251 3 0 1 61253 4 2 43674 22 0 1 61261 1 61259 1 61261 2 2 61257 1 61261 3 61259 2 0 1 61261 4 2 41485 10 0 1 61283 1 61281 1 61283 2 2 61282 1 61283 3 61281 3 0 1 61283 4 2 43068 10 0 1 61291 1 61288 1 61291 2 3 61290 1 61291 3 61288 1 0 1 61291 4 3 57988 2 0 1 61297 1 61290 1 61297 2 7 61294 1 61297 3 61290 2 0 1 61297 4 7 36957 8 0 1 61331 1 61329 1 61331 2 2 61327 1 61331 3 61329 2 0 1 61331 4 2 54672 8 0 1 61333 1 61331 1 61333 2 2 61332 1 61333 3 61331 2 0 1 61333 4 2 34465 3 0 1 61339 1 61337 1 61339 2 2 61338 1 61339 3 61337 4 0 1 61339 4 2 33990 6 0 1 61343 1 61338 1 61343 2 5 61341 1 61343 3 61338 3 0 1 61343 4 5 39504 8 0 1 61357 1 61351 1 61357 2 6 61355 1 61357 3 61351 2 0 1 61357 4 6 33171 10 0 1 61363 1 61360 1 61363 2 3 61356 1 61363 3 61360 3 0 1 61363 4 3 33832 2 0 1 61379 1 61377 1 61379 2 2 61378 1 61379 3 61377 3 0 1 61379 4 2 60825 4 0 1 61381 1 61375 1 61381 2 6 61380 1 61381 3 61375 1 0 1 61381 4 6 40379 7 0 1 61403 1 61401 1 61403 2 2 61402 1 61403 3 61401 5 0 1 61403 4 2 42392 10 0 1 61409 1 61406 1 61409 2 3 61408 1 61409 3 61406 1 0 1 61409 4 3 54546 7 0 1 61417 1 61412 1 61417 2 5 61408 1 61417 3 61412 6 0 1 61417 4 5 42540 14 0 1 61441 1 61424 1 61441 2 17 61440 1 61441 3 61424 2 0 1 61441 4 17 34907 12 0 1 61463 1 61458 1 61463 2 5 61461 1 61463 3 61458 9 0 1 61463 4 5 57285 14 0 1 61469 1 61467 1 61469 2 2 61464 1 61469 3 61467 10 0 1 61469 4 2 55713 20 0 1 61471 1 61468 1 61471 2 3 61469 1 61471 3 61468 7 0 1 61471 4 3 52115 6 0 1 61483 1 61481 1 61483 2 2 61478 1 61483 3 61481 6 0 1 61483 4 2 40254 2 0 1 61487 1 61482 1 61487 2 5 61485 1 61487 3 61482 11 0 1 61487 4 5 61483 3 0 1 61493 1 61491 1 61493 2 2 61492 1 61493 3 61491 7 0 1 61493 4 2 31024 21 0 1 61507 1 61505 1 61507 2 2 61506 1 61507 3 61505 2 0 1 61507 4 2 45654 2 0 1 61511 1 61504 1 61511 2 7 61510 1 61511 3 61504 1 0 1 61511 4 7 59211 3 0 1 61519 1 61516 1 61519 2 3 61518 1 61519 3 61516 1 0 1 61519 4 3 42703 2 0 1 61543 1 61540 1 61543 2 3 61541 1 61543 3 61540 3 0 1 61543 4 3 45606 3 0 1 61547 1 61545 1 61547 2 2 61543 1 61547 3 61545 2 0 1 61547 4 2 37014 7 0 1 61553 1 61550 1 61553 2 3 61548 1 61553 3 61550 1 0 1 61553 4 3 31054 0 0 1 61559 1 61552 1 61559 2 7 61557 1 61559 3 61552 3 0 1 61559 4 7 55248 4 0 1 61561 1 61554 1 61561 2 7 61554 1 61561 3 61554 2 0 1 61561 4 7 37994 0 0 1 61583 1 61578 1 61583 2 5 61578 1 61583 3 61578 1 0 1 61583 4 5 41969 6 0 1 61603 1 61601 1 61603 2 2 61602 1 61603 3 61601 6 0 1 61603 4 2 50916 2 0 1 61609 1 61596 1 61609 2 13 61606 1 61609 3 61596 3 0 1 61609 4 13 46793 26 0 1 61613 1 61611 1 61613 2 2 61597 1 61613 3 61611 2 0 1 61613 4 2 50836 3 0 1 61627 1 61624 1 61627 2 3 61622 1 61627 3 61624 6 0 1 61627 4 3 49372 3 0 1 61631 1 61620 1 61631 2 11 61630 1 61631 3 61620 6 0 1 61631 4 11 50465 2 0 1 61637 1 61635 1 61637 2 2 61632 1 61637 3 61635 8 0 1 61637 4 2 44458 0 0 1 61643 1 61641 1 61643 2 2 61639 1 61643 3 61641 3 0 1 61643 4 2 41731 8 0 1 61651 1 61649 1 61651 2 2 61647 1 61651 3 61649 5 0 1 61651 4 2 44616 8 0 1 61657 1 61652 1 61657 2 5 61656 1 61657 3 61652 1 0 1 61657 4 5 58391 6 0 1 61667 1 61665 1 61667 2 2 61663 1 61667 3 61665 3 0 1 61667 4 2 38136 8 0 1 61673 1 61668 1 61673 2 5 61670 1 61673 3 61668 2 0 1 61673 4 5 47605 0 0 1 61681 1 61652 1 61681 2 29 61674 1 61681 3 61652 3 0 1 61681 4 29 59222 36 0 1 61687 1 61681 1 61687 2 6 61684 1 61687 3 61681 2 0 1 61687 4 6 45338 5 0 1 61703 1 61698 1 61703 2 5 61702 1 61703 3 61698 2 0 1 61703 4 5 41755 4 0 1 61717 1 61715 1 61717 2 2 61716 1 61717 3 61715 6 0 1 61717 4 2 57170 3 0 1 61723 1 61718 1 61723 2 5 61721 1 61723 3 61718 5 0 1 61723 4 5 61719 3 0 1 61729 1 61722 1 61729 2 7 61722 1 61729 3 61722 2 0 1 61729 4 7 38315 0 0 1 61751 1 61744 1 61751 2 7 61750 1 61751 3 61744 8 0 1 61751 4 7 37416 6 0 1 61757 1 61755 1 61757 2 2 61756 1 61757 3 61755 2 0 1 61757 4 2 51635 4 0 1 61781 1 61779 1 61781 2 2 61774 1 61781 3 61779 4 0 1 61781 4 2 51262 17 0 1 61813 1 61811 1 61813 2 2 61812 1 61813 3 61811 4 0 1 61813 4 2 47977 6 0 1 61819 1 61816 1 61819 2 3 61812 1 61819 3 61816 5 0 1 61819 4 3 39500 0 0 1 61837 1 61831 1 61837 2 6 61835 1 61837 3 61831 2 0 1 61837 4 6 56096 0 0 1 61843 1 61841 1 61843 2 2 61842 1 61843 3 61841 6 0 1 61843 4 2 61836 8 0 1 61861 1 61859 1 61861 2 2 61857 1 61861 3 61859 6 0 1 61861 4 2 43169 12 0 1 61871 1 61852 1 61871 2 19 61870 1 61871 3 61852 3 0 1 61871 4 19 59775 6 0 1 61879 1 61876 1 61879 2 3 61877 1 61879 3 61876 5 0 1 61879 4 3 31536 3 0 1 61909 1 61903 1 61909 2 6 61905 1 61909 3 61903 7 0 1 61909 4 6 45367 2 0 1 61927 1 61924 1 61927 2 3 61926 1 61927 3 61924 4 0 1 61927 4 3 40760 5 0 1 61933 1 61928 1 61933 2 5 61932 1 61933 3 61928 1 0 1 61933 4 5 61581 3 0 1 61949 1 61947 1 61949 2 2 61943 1 61949 3 61947 9 0 1 61949 4 2 53327 3 0 1 61961 1 61958 1 61961 2 3 61955 1 61961 3 61958 14 0 1 61961 4 3 61949 0 0 1 61967 1 61962 1 61967 2 5 61966 1 61967 3 61962 5 0 1 61967 4 5 60581 2 0 1 61979 1 61977 1 61979 2 2 61973 1 61979 3 61977 2 0 1 61979 4 2 43937 4 0 1 61981 1 61974 1 61981 2 7 61979 1 61981 3 61974 3 0 1 61981 4 7 42871 4 0 1 61987 1 61985 1 61987 2 2 61983 1 61987 3 61985 4 0 1 61987 4 2 45800 14 0 1 61991 1 61978 1 61991 2 13 61989 1 61991 3 61978 1 0 1 61991 4 13 48932 7 0 1 62003 1 62001 1 62003 2 2 61999 1 62003 3 62001 3 0 1 62003 4 2 61007 8 0 1 62011 1 62009 1 62011 2 2 62010 1 62011 3 62009 5 0 1 62011 4 2 34612 6 0 1 62017 1 62007 1 62017 2 10 62016 1 62017 3 62007 5 0 1 62017 4 10 53517 6 0 1 62039 1 62022 1 62039 2 17 62037 1 62039 3 62022 1 0 1 62039 4 17 59403 4 0 1 62047 1 62044 1 62047 2 3 62046 1 62047 3 62044 1 0 1 62047 4 3 59196 5 0 1 62053 1 62051 1 62053 2 2 62052 1 62053 3 62051 5 0 1 62053 4 2 51561 7 0 1 62057 1 62054 1 62057 2 3 62050 1 62057 3 62054 4 0 1 62057 4 3 51886 1 0 1 62071 1 62064 1 62071 2 7 62062 1 62071 3 62064 1 0 1 62071 4 7 38517 3 0 1 62081 1 62075 1 62081 2 6 62078 1 62081 3 62075 6 0 1 62081 4 6 46374 0 0 1 62099 1 62097 1 62099 2 2 62095 1 62099 3 62097 3 0 1 62099 4 2 44457 7 0 1 62119 1 62112 1 62119 2 7 62116 1 62119 3 62112 10 0 1 62119 4 7 52234 5 0 1 62129 1 62126 1 62129 2 3 62124 1 62129 3 62126 1 0 1 62129 4 3 41537 2 0 1 62131 1 62129 1 62131 2 2 62127 1 62131 3 62129 6 0 1 62131 4 2 51020 1 0 1 62137 1 62130 1 62137 2 7 62130 1 62137 3 62130 4 0 1 62137 4 7 47863 14 0 1 62141 1 62139 1 62141 2 2 62137 1 62141 3 62139 3 0 1 62141 4 2 45909 6 0 1 62143 1 62140 1 62143 2 3 62141 1 62143 3 62140 9 0 1 62143 4 3 42592 3 0 1 62171 1 62169 1 62171 2 2 62165 1 62171 3 62169 2 0 1 62171 4 2 45467 0 0 1 62189 1 62187 1 62189 2 2 62185 1 62189 3 62187 2 0 1 62189 4 2 46417 6 0 1 62191 1 62188 1 62191 2 3 62190 1 62191 3 62188 1 0 1 62191 4 3 36223 2 0 1 62201 1 62198 1 62201 2 3 62195 1 62201 3 62198 11 0 1 62201 4 3 62189 0 0 1 62207 1 62202 1 62207 2 5 62205 1 62207 3 62202 3 0 1 62207 4 5 59062 9 0 1 62213 1 62211 1 62213 2 2 62209 1 62213 3 62211 15 0 1 62213 4 2 33853 12 0 1 62219 1 62217 1 62219 2 2 62218 1 62219 3 62217 3 0 1 62219 4 2 61608 2 0 1 62233 1 62226 1 62233 2 7 62230 1 62233 3 62226 3 0 1 62233 4 7 42282 10 0 1 62273 1 62270 1 62273 2 3 62272 1 62273 3 62270 10 0 1 62273 4 3 34964 4 0 1 62297 1 62294 1 62297 2 3 62291 1 62297 3 62294 4 0 1 62297 4 3 42663 1 0 1 62299 1 62297 1 62299 2 2 62298 1 62299 3 62297 6 0 1 62299 4 2 40082 17 0 1 62303 1 62298 1 62303 2 5 62302 1 62303 3 62298 1 0 1 62303 4 5 53972 2 0 1 62311 1 62305 1 62311 2 6 62309 1 62311 3 62305 1 0 1 62311 4 6 55233 4 0 1 62323 1 62321 1 62323 2 2 62319 1 62323 3 62321 6 0 1 62323 4 2 46418 8 0 1 62327 1 62322 1 62327 2 5 62322 1 62327 3 62322 2 0 1 62327 4 5 41669 6 0 1 62347 1 62344 1 62347 2 3 62346 1 62347 3 62344 3 0 1 62347 4 3 45311 2 0 1 62351 1 62344 1 62351 2 7 62350 1 62351 3 62344 3 0 1 62351 4 7 50862 3 0 1 62383 1 62378 1 62383 2 5 62381 1 62383 3 62378 6 0 1 62383 4 5 62379 3 0 1 62401 1 62384 1 62401 2 17 62398 1 62401 3 62384 1 0 1 62401 4 17 33894 17 0 1 62417 1 62414 1 62417 2 3 62411 1 62417 3 62414 6 0 1 62417 4 3 55883 9 0 1 62423 1 62418 1 62423 2 5 62422 1 62423 3 62418 5 0 1 62423 4 5 47543 2 0 1 62459 1 62453 1 62459 2 6 62458 1 62459 3 62453 2 0 1 62459 4 6 33256 2 0 1 62467 1 62464 1 62467 2 3 62462 1 62467 3 62464 7 0 1 62467 4 3 55812 11 0 1 62473 1 62468 1 62473 2 5 62468 1 62473 3 62468 1 0 1 62473 4 5 38917 15 0 1 62477 1 62475 1 62477 2 2 62469 1 62477 3 62475 10 0 1 62477 4 2 37627 11 0 1 62483 1 62481 1 62483 2 2 62479 1 62483 3 62481 3 0 1 62483 4 2 42208 8 0 1 62497 1 62487 1 62497 2 10 62496 1 62497 3 62487 2 0 1 62497 4 10 57867 12 0 1 62501 1 62499 1 62501 2 2 62500 1 62501 3 62499 5 0 1 62501 4 2 45749 3 0 1 62507 1 62505 1 62507 2 2 62503 1 62507 3 62505 3 0 1 62507 4 2 42044 7 0 1 62533 1 62531 1 62533 2 2 62529 1 62533 3 62531 4 0 1 62533 4 2 49614 6 0 1 62539 1 62537 1 62539 2 2 62535 1 62539 3 62537 2 0 1 62539 4 2 31486 8 0 1 62549 1 62547 1 62549 2 2 62545 1 62549 3 62547 3 0 1 62549 4 2 44535 6 0 1 62563 1 62560 1 62563 2 3 62562 1 62563 3 62560 4 0 1 62563 4 3 36586 2 0 1 62581 1 62579 1 62581 2 2 62577 1 62581 3 62579 4 0 1 62581 4 2 59696 10 0 1 62591 1 62584 1 62591 2 7 62590 1 62591 3 62584 7 0 1 62591 4 7 47670 3 0 1 62597 1 62595 1 62597 2 2 62596 1 62597 3 62595 2 0 1 62597 4 2 44147 3 0 1 62603 1 62601 1 62603 2 2 62599 1 62603 3 62601 9 0 1 62603 4 2 39073 8 0 1 62617 1 62612 1 62617 2 5 62616 1 62617 3 62612 3 0 1 62617 4 5 54329 6 0 1 62627 1 62625 1 62627 2 2 62626 1 62627 3 62625 2 0 1 62627 4 2 62014 2 0 1 62633 1 62630 1 62633 2 3 62632 1 62633 3 62630 1 0 1 62633 4 3 35689 4 0 1 62639 1 62628 1 62639 2 11 62636 1 62639 3 62628 4 0 1 62639 4 11 39672 5 0 1 62653 1 62651 1 62653 2 2 62652 1 62653 3 62651 2 0 1 62653 4 2 59122 3 0 1 62659 1 62656 1 62659 2 3 62652 1 62659 3 62656 1 0 1 62659 4 3 32070 5 0 1 62683 1 62680 1 62683 2 3 62676 1 62683 3 62680 7 0 1 62683 4 3 62123 2 0 1 62687 1 62682 1 62687 2 5 62685 1 62687 3 62682 1 0 1 62687 4 5 55913 14 0 1 62701 1 62699 1 62701 2 2 62697 1 62701 3 62699 6 0 1 62701 4 2 39258 6 0 1 62723 1 62721 1 62723 2 2 62722 1 62723 3 62721 2 0 1 62723 4 2 59565 2 0 1 62731 1 62721 1 62731 2 10 62730 1 62731 3 62721 6 0 1 62731 4 10 36959 5 0 1 62743 1 62736 1 62743 2 7 62732 1 62743 3 62736 1 0 1 62743 4 7 33771 1 0 1 62753 1 62750 1 62753 2 3 62747 1 62753 3 62750 1 0 1 62753 4 3 48144 9 0 1 62761 1 62754 1 62761 2 7 62754 1 62761 3 62754 2 0 1 62761 4 7 42142 0 0 1 62773 1 62768 1 62773 2 5 62770 1 62773 3 62768 8 0 1 62773 4 5 60647 23 0 1 62791 1 62788 1 62791 2 3 62789 1 62791 3 62788 3 0 1 62791 4 3 31727 3 0 1 62801 1 62798 1 62801 2 3 62796 1 62801 3 62798 3 0 1 62801 4 3 57059 2 0 1 62819 1 62817 1 62819 2 2 62815 1 62819 3 62817 2 0 1 62819 4 2 40689 7 0 1 62827 1 62824 1 62827 2 3 62826 1 62827 3 62824 8 0 1 62827 4 3 52046 2 0 1 62851 1 62849 1 62851 2 2 62850 1 62851 3 62849 6 0 1 62851 4 2 62844 8 0 1 62861 1 62858 1 62861 2 3 62860 1 62861 3 62858 3 0 1 62861 4 3 50905 3 0 1 62869 1 62867 1 62869 2 2 62865 1 62869 3 62867 4 0 1 62869 4 2 35329 6 0 1 62873 1 62870 1 62873 2 3 62867 1 62873 3 62870 1 0 1 62873 4 3 44762 11 0 1 62897 1 62894 1 62897 2 3 62896 1 62897 3 62894 6 0 1 62897 4 3 54782 7 0 1 62903 1 62898 1 62903 2 5 62902 1 62903 3 62898 1 0 1 62903 4 5 34079 9 0 1 62921 1 62907 1 62921 2 14 62916 1 62921 3 62907 2 0 1 62921 4 14 62089 8 0 1 62927 1 62922 1 62927 2 5 62920 1 62927 3 62922 10 0 1 62927 4 5 38104 2 0 1 62929 1 62915 1 62929 2 14 62926 1 62929 3 62915 2 0 1 62929 4 14 46660 24 0 1 62939 1 62937 1 62939 2 2 62933 1 62939 3 62937 2 0 1 62939 4 2 43142 4 0 1 62969 1 62966 1 62969 2 3 62963 1 62969 3 62966 14 0 1 62969 4 3 62957 0 0 1 62971 1 62961 1 62971 2 10 62967 1 62971 3 62961 4 0 1 62971 4 10 52750 2 0 1 62981 1 62979 1 62981 2 2 62977 1 62981 3 62979 2 0 1 62981 4 2 56568 7 0 1 62983 1 62978 1 62983 2 5 62981 1 62983 3 62978 3 0 1 62983 4 5 62979 3 0 1 62987 1 62985 1 62987 2 2 62983 1 62987 3 62985 3 0 1 62987 4 2 44134 8 0 1 62989 1 62987 1 62989 2 2 62985 1 62989 3 62987 6 0 1 62989 4 2 42878 10 0 1 63029 1 63027 1 63029 2 2 63025 1 63029 3 63027 3 0 1 63029 4 2 38322 6 0 1 63031 1 63028 1 63031 2 3 63029 1 63031 3 63028 7 0 1 63031 4 3 51837 3 0 1 63059 1 63057 1 63059 2 2 63049 1 63059 3 63057 11 0 1 63059 4 2 42683 0 0 1 63067 1 63065 1 63067 2 2 63063 1 63067 3 63065 6 0 1 63067 4 2 45304 8 0 1 63073 1 63068 1 63073 2 5 63072 1 63073 3 63068 1 0 1 63073 4 5 45905 6 0 1 63079 1 63076 1 63079 2 3 63073 1 63079 3 63076 3 0 1 63079 4 3 42838 7 0 1 63097 1 63092 1 63097 2 5 63092 1 63097 3 63092 2 0 1 63097 4 5 43546 10 0 1 63103 1 63100 1 63103 2 3 63102 1 63103 3 63100 1 0 1 63103 4 3 59006 2 0 1 63113 1 63110 1 63113 2 3 63107 1 63113 3 63110 1 0 1 63113 4 3 38456 1 0 1 63127 1 63124 1 63127 2 3 63125 1 63127 3 63124 1 0 1 63127 4 3 51151 6 0 1 63131 1 63129 1 63131 2 2 63130 1 63131 3 63129 3 0 1 63131 4 2 41900 4 0 1 63149 1 63147 1 63149 2 2 63141 1 63149 3 63147 3 0 1 63149 4 2 36683 0 0 1 63179 1 63177 1 63179 2 2 63175 1 63179 3 63177 2 0 1 63179 4 2 39541 8 0 1 63197 1 63195 1 63197 2 2 63188 1 63197 3 63195 10 0 1 63197 4 2 34917 4 0 1 63199 1 63196 1 63199 2 3 63194 1 63199 3 63196 5 0 1 63199 4 3 45062 7 0 1 63211 1 63204 1 63211 2 7 63209 1 63211 3 63204 1 0 1 63211 4 7 38146 6 0 1 63241 1 63234 1 63241 2 7 63234 1 63241 3 63234 4 0 1 63241 4 7 51494 0 0 1 63247 1 63242 1 63247 2 5 63246 1 63247 3 63242 1 0 1 63247 4 5 59655 5 0 1 63277 1 63275 1 63277 2 2 63273 1 63277 3 63275 6 0 1 63277 4 2 35827 6 0 1 63281 1 63275 1 63281 2 6 63278 1 63281 3 63275 4 0 1 63281 4 6 43459 0 0 1 63299 1 63297 1 63299 2 2 63298 1 63299 3 63297 3 0 1 63299 4 2 60566 2 0 1 63311 1 63294 1 63311 2 17 63310 1 63311 3 63294 1 0 1 63311 4 17 51397 3 0 1 63313 1 63308 1 63313 2 5 63310 1 63313 3 63308 1 0 1 63313 4 5 34930 10 0 1 63317 1 63315 1 63317 2 2 63313 1 63317 3 63315 7 0 1 63317 4 2 57640 7 0 1 63331 1 63329 1 63331 2 2 63327 1 63331 3 63329 2 0 1 63331 4 2 60540 8 0 1 63337 1 63332 1 63337 2 5 63336 1 63337 3 63332 5 0 1 63337 4 5 38091 16 0 1 63347 1 63345 1 63347 2 2 63343 1 63347 3 63345 3 0 1 63347 4 2 53866 8 0 1 63353 1 63350 1 63353 2 3 63347 1 63353 3 63350 11 0 1 63353 4 3 62641 1 0 1 63361 1 63324 1 63361 2 37 63344 1 63361 3 63324 7 0 1 63361 4 37 46878 36 0 1 63367 1 63364 1 63367 2 3 63366 1 63367 3 63364 1 0 1 63367 4 3 34185 2 0 1 63377 1 63374 1 63377 2 3 63372 1 63377 3 63374 1 0 1 63377 4 3 52720 0 0 1 63389 1 63387 1 63389 2 2 63385 1 63389 3 63387 2 0 1 63389 4 2 48122 12 0 1 63391 1 63388 1 63391 2 3 63389 1 63391 3 63388 1 0 1 63391 4 3 52937 6 0 1 63397 1 63395 1 63397 2 2 63396 1 63397 3 63395 5 0 1 63397 4 2 55543 6 0 1 63409 1 63402 1 63409 2 7 63402 1 63409 3 63402 7 0 1 63409 4 7 62501 0 0 1 63419 1 63417 1 63419 2 2 63418 1 63419 3 63417 3 0 1 63419 4 2 47019 4 0 1 63421 1 63419 1 63421 2 2 63417 1 63421 3 63419 5 0 1 63421 4 2 41070 6 0 1 63439 1 63436 1 63439 2 3 63438 1 63439 3 63436 1 0 1 63439 4 3 61658 2 0 1 63443 1 63441 1 63443 2 2 63439 1 63443 3 63441 3 0 1 63443 4 2 50612 7 0 1 63463 1 63458 1 63463 2 5 63462 1 63463 3 63458 10 0 1 63463 4 5 59293 3 0 1 63467 1 63465 1 63467 2 2 63466 1 63467 3 63465 2 0 1 63467 4 2 50599 4 0 1 63473 1 63470 1 63473 2 3 63468 1 63473 3 63470 1 0 1 63473 4 3 42553 0 0 1 63487 1 63484 1 63487 2 3 63486 1 63487 3 63484 7 0 1 63487 4 3 45109 5 0 1 63493 1 63491 1 63493 2 2 63492 1 63493 3 63491 2 0 1 63493 4 2 32266 6 0 1 63499 1 63496 1 63499 2 3 63498 1 63499 3 63496 4 0 1 63499 4 3 53027 2 0 1 63521 1 63518 1 63521 2 3 63520 1 63521 3 63518 7 0 1 63521 4 3 44157 4 0 1 63527 1 63522 1 63527 2 5 63526 1 63527 3 63522 1 0 1 63527 4 5 59118 2 0 1 63533 1 63530 1 63533 2 3 63531 1 63533 3 63530 3 0 1 63533 4 3 45853 7 0 1 63541 1 63539 1 63541 2 2 63537 1 63541 3 63539 6 0 1 63541 4 2 39262 6 0 1 63559 1 63556 1 63559 2 3 63557 1 63559 3 63556 4 0 1 63559 4 3 55017 6 0 1 63577 1 63572 1 63577 2 5 63576 1 63577 3 63572 1 0 1 63577 4 5 52829 6 0 1 63587 1 63585 1 63587 2 2 63583 1 63587 3 63585 3 0 1 63587 4 2 50506 11 0 1 63589 1 63587 1 63589 2 2 63585 1 63589 3 63587 6 0 1 63589 4 2 44259 12 0 1 63599 1 63592 1 63599 2 7 63598 1 63599 3 63592 2 0 1 63599 4 7 49293 3 0 1 63601 1 63594 1 63601 2 7 63598 1 63601 3 63594 2 0 1 63601 4 7 63244 16 0 1 63607 1 63604 1 63607 2 3 63605 1 63607 3 63604 1 0 1 63607 4 3 63603 4 0 1 63611 1 63609 1 63611 2 2 63606 1 63611 3 63609 5 0 1 63611 4 2 32024 3 0 1 63617 1 63614 1 63617 2 3 63612 1 63617 3 63614 3 0 1 63617 4 3 42887 0 0 1 63629 1 63627 1 63629 2 2 63628 1 63629 3 63627 3 0 1 63629 4 2 54409 9 0 1 63647 1 63642 1 63647 2 5 63642 1 63647 3 63642 1 0 1 63647 4 5 39696 7 0 1 63649 1 63642 1 63649 2 7 63646 1 63649 3 63642 3 0 1 63649 4 7 48666 17 0 1 63659 1 63657 1 63659 2 2 63655 1 63659 3 63657 2 0 1 63659 4 2 44961 7 0 1 63667 1 63665 1 63667 2 2 63663 1 63667 3 63665 6 0 1 63667 4 2 61260 10 0 1 63671 1 63660 1 63671 2 11 63669 1 63671 3 63660 5 0 1 63671 4 11 62157 3 0 1 63689 1 63686 1 63689 2 3 63683 1 63689 3 63686 3 0 1 63689 4 3 63677 0 0 1 63691 1 63676 1 63691 2 15 63690 1 63691 3 63676 1 0 1 63691 4 15 34653 6 0 1 63697 1 63692 1 63697 2 5 63694 1 63697 3 63692 1 0 1 63697 4 5 63686 14 0 1 63703 1 63700 1 63703 2 3 63702 1 63703 3 63700 3 0 1 63703 4 3 44331 2 0 1 63709 1 63703 1 63709 2 6 63708 1 63709 3 63703 1 0 1 63709 4 6 52134 27 0 1 63719 1 63706 1 63719 2 13 63715 1 63719 3 63706 1 0 1 63719 4 13 49694 6 0 1 63727 1 63721 1 63727 2 6 63726 1 63727 3 63721 1 0 1 63727 4 6 60312 9 0 1 63737 1 63734 1 63737 2 3 63729 1 63737 3 63734 3 0 1 63737 4 3 44762 2 0 1 63743 1 63738 1 63743 2 5 63738 1 63743 3 63738 7 0 1 63743 4 5 44314 6 0 1 63761 1 63758 1 63761 2 3 63755 1 63761 3 63758 5 0 1 63761 4 3 63749 0 0 1 63773 1 63771 1 63773 2 2 63772 1 63773 3 63771 2 0 1 63773 4 2 51531 3 0 1 63781 1 63779 1 63781 2 2 63777 1 63781 3 63779 4 0 1 63781 4 2 46335 6 0 1 63793 1 63788 1 63793 2 5 63792 1 63793 3 63788 1 0 1 63793 4 5 46437 11 0 1 63799 1 63793 1 63799 2 6 63798 1 63799 3 63793 3 0 1 63799 4 6 33492 3 0 1 63803 1 63801 1 63803 2 2 63802 1 63803 3 63801 3 0 1 63803 4 2 45662 2 0 1 63809 1 63806 1 63809 2 3 63804 1 63809 3 63806 4 0 1 63809 4 3 38517 2 0 1 63823 1 63820 1 63823 2 3 63821 1 63823 3 63820 10 0 1 63823 4 3 44743 3 0 1 63839 1 63810 1 63839 2 29 63836 1 63839 3 63810 6 0 1 63839 4 29 52266 4 0 1 63841 1 63824 1 63841 2 17 63840 1 63841 3 63824 1 0 1 63841 4 17 32205 18 0 1 63853 1 63851 1 63853 2 2 63852 1 63853 3 63851 2 0 1 63853 4 2 60444 6 0 1 63857 1 63854 1 63857 2 3 63856 1 63857 3 63854 4 0 1 63857 4 3 41700 4 0 1 63863 1 63858 1 63863 2 5 63860 1 63863 3 63858 5 0 1 63863 4 5 50800 6 0 1 63901 1 63894 1 63901 2 7 63899 1 63901 3 63894 3 0 1 63901 4 7 42432 4 0 1 63907 1 63905 1 63907 2 2 63903 1 63907 3 63905 4 0 1 63907 4 2 36755 10 0 1 63913 1 63900 1 63913 2 13 63912 1 63913 3 63900 4 0 1 63913 4 13 50745 6 0 1 63929 1 63926 1 63929 2 3 63928 1 63929 3 63926 3 0 1 63929 4 3 51391 4 0 1 63949 1 63947 1 63949 2 2 63945 1 63949 3 63947 5 0 1 63949 4 2 62108 6 0 1 63977 1 63974 1 63977 2 3 63966 1 63977 3 63974 15 0 1 63977 4 3 47618 1 0 1 63997 1 63995 1 63997 2 2 63996 1 63997 3 63995 2 0 1 63997 4 2 49095 3 0 1 64007 1 64002 1 64007 2 5 64005 1 64007 3 64002 1 0 1 64007 4 5 51492 8 0 1 64013 1 64011 1 64013 2 2 64012 1 64013 3 64011 2 0 1 64013 4 2 36728 6 0 1 64019 1 64017 1 64019 2 2 64015 1 64019 3 64017 3 0 1 64019 4 2 55357 7 0 1 64033 1 64028 1 64033 2 5 64032 1 64033 3 64028 2 0 1 64033 4 5 42155 12 0 1 64037 1 64035 1 64037 2 2 64033 1 64037 3 64035 3 0 1 64037 4 2 40137 9 0 1 64063 1 64060 1 64063 2 3 64062 1 64063 3 64060 3 0 1 64063 4 3 56576 5 0 1 64067 1 64062 1 64067 2 5 64066 1 64067 3 64062 5 0 1 64067 4 5 33568 13 0 1 64081 1 64070 1 64081 2 11 64078 1 64081 3 64070 2 0 1 64081 4 11 55613 14 0 1 64091 1 64089 1 64091 2 2 64090 1 64091 3 64089 3 0 1 64091 4 2 39373 4 0 1 64109 1 64107 1 64109 2 2 64108 1 64109 3 64107 4 0 1 64109 4 2 42240 4 0 1 64123 1 64121 1 64123 2 2 64122 1 64123 3 64121 2 0 1 64123 4 2 55300 2 0 1 64151 1 64134 1 64151 2 17 64150 1 64151 3 64134 10 0 1 64151 4 17 38195 3 0 1 64153 1 64148 1 64153 2 5 64148 1 64153 3 64148 2 0 1 64153 4 5 45494 15 0 1 64157 1 64155 1 64157 2 2 64153 1 64157 3 64155 3 0 1 64157 4 2 38351 7 0 1 64171 1 64164 1 64171 2 7 64169 1 64171 3 64164 4 0 1 64171 4 7 39100 6 0 1 64187 1 64185 1 64187 2 2 64183 1 64187 3 64185 3 0 1 64187 4 2 57561 8 0 1 64189 1 64187 1 64189 2 2 64188 1 64189 3 64187 6 0 1 64189 4 2 54808 7 0 1 64217 1 64214 1 64217 2 3 64216 1 64217 3 64214 1 0 1 64217 4 3 46207 4 0 1 64223 1 64218 1 64223 2 5 64221 1 64223 3 64218 3 0 1 64223 4 5 64219 3 0 1 64231 1 64219 1 64231 2 12 64230 1 64231 3 64219 1 0 1 64231 4 12 48608 8 0 1 64237 1 64235 1 64237 2 2 64236 1 64237 3 64235 6 0 1 64237 4 2 56727 3 0 1 64271 1 64264 1 64271 2 7 64270 1 64271 3 64264 4 0 1 64271 4 7 46350 3 0 1 64279 1 64250 1 64279 2 29 64278 1 64279 3 64250 1 0 1 64279 4 29 62098 2 0 1 64283 1 64281 1 64283 2 2 64279 1 64283 3 64281 3 0 1 64283 4 2 32361 8 0 1 64301 1 64299 1 64301 2 2 64297 1 64301 3 64299 3 0 1 64301 4 2 37355 1 0 1 64303 1 64297 1 64303 2 6 64300 1 64303 3 64297 10 0 1 64303 4 6 32487 5 0 1 64319 1 64306 1 64319 2 13 64315 1 64319 3 64306 1 0 1 64319 4 13 42640 7 0 1 64327 1 64324 1 64327 2 3 64326 1 64327 3 64324 3 0 1 64327 4 3 33104 5 0 1 64333 1 64331 1 64333 2 2 64329 1 64333 3 64331 5 0 1 64333 4 2 50093 6 0 1 64373 1 64371 1 64373 2 2 64368 1 64373 3 64371 7 0 1 64373 4 2 42537 0 0 1 64381 1 64379 1 64381 2 2 64377 1 64381 3 64379 2 0 1 64381 4 2 54656 12 0 1 64399 1 64396 1 64399 2 3 64397 1 64399 3 64396 3 0 1 64399 4 3 38922 3 0 1 64403 1 64398 1 64403 2 5 64401 1 64403 3 64398 1 0 1 64403 4 5 53529 0 0 1 64433 1 64430 1 64433 2 3 64428 1 64433 3 64430 3 0 1 64433 4 3 55938 0 0 1 64439 1 64432 1 64439 2 7 64437 1 64439 3 64432 2 0 1 64439 4 7 63003 4 0 1 64451 1 64449 1 64451 2 2 64447 1 64451 3 64449 2 0 1 64451 4 2 54312 7 0 1 64453 1 64451 1 64453 2 2 64449 1 64453 3 64451 6 0 1 64453 4 2 38959 6 0 1 64483 1 64481 1 64483 2 2 64479 1 64483 3 64481 2 0 1 64483 4 2 50586 1 0 1 64489 1 64482 1 64489 2 7 64486 1 64489 3 64482 1 0 1 64489 4 7 54347 14 0 1 64499 1 64497 1 64499 2 2 64495 1 64499 3 64497 2 0 1 64499 4 2 50377 7 0 1 64513 1 64508 1 64513 2 5 64512 1 64513 3 64508 1 0 1 64513 4 5 50578 6 0 1 64553 1 64550 1 64553 2 3 64548 1 64553 3 64550 3 0 1 64553 4 3 60008 0 0 1 64567 1 64564 1 64567 2 3 64566 1 64567 3 64564 1 0 1 64567 4 3 50465 5 0 1 64577 1 64574 1 64577 2 3 64571 1 64577 3 64574 1 0 1 64577 4 3 36260 11 0 1 64579 1 64577 1 64579 2 2 64573 1 64579 3 64577 2 0 1 64579 4 2 59371 3 0 1 64591 1 64588 1 64591 2 3 64590 1 64591 3 64588 1 0 1 64591 4 3 53938 3 0 1 64601 1 64598 1 64601 2 3 64595 1 64601 3 64598 6 0 1 64601 4 3 64589 0 0 1 64609 1 64574 1 64609 2 35 64596 1 64609 3 64574 1 0 1 64609 4 35 37869 20 0 1 64613 1 64611 1 64613 2 2 64612 1 64613 3 64611 3 0 1 64613 4 2 43964 3 0 1 64621 1 64615 1 64621 2 6 64620 1 64621 3 64615 1 0 1 64621 4 6 41431 7 0 1 64627 1 64622 1 64627 2 5 64626 1 64627 3 64622 5 0 1 64627 4 5 57281 10 0 1 64633 1 64628 1 64633 2 5 64632 1 64633 3 64628 5 0 1 64633 4 5 57835 12 0 1 64661 1 64659 1 64661 2 2 64657 1 64661 3 64659 2 0 1 64661 4 2 52413 6 0 1 64663 1 64657 1 64663 2 6 64662 1 64663 3 64657 2 0 1 64663 4 6 57699 3 0 1 64667 1 64665 1 64667 2 2 64663 1 64667 3 64665 3 0 1 64667 4 2 58548 8 0 1 64679 1 64662 1 64679 2 17 64674 1 64679 3 64662 5 0 1 64679 4 17 60594 6 0 1 64693 1 64691 1 64693 2 2 64692 1 64693 3 64691 6 0 1 64693 4 2 62227 3 0 1 64709 1 64706 1 64709 2 3 64704 1 64709 3 64706 6 0 1 64709 4 3 56549 2 0 1 64717 1 64715 1 64717 2 2 64713 1 64717 3 64715 4 0 1 64717 4 2 42839 10 0 1 64747 1 64742 1 64747 2 5 64746 1 64747 3 64742 1 0 1 64747 4 5 36222 5 0 1 64763 1 64761 1 64763 2 2 64759 1 64763 3 64761 3 0 1 64763 4 2 43934 16 0 1 64781 1 64779 1 64781 2 2 64776 1 64781 3 64779 4 0 1 64781 4 2 38678 2 0 1 64783 1 64778 1 64783 2 5 64782 1 64783 3 64778 1 0 1 64783 4 5 58349 2 0 1 64793 1 64790 1 64793 2 3 64787 1 64793 3 64790 6 0 1 64793 4 3 41440 9 0 1 64811 1 64809 1 64811 2 2 64810 1 64811 3 64809 12 0 1 64811 4 2 58749 2 0 1 64817 1 64814 1 64817 2 3 64811 1 64817 3 64814 4 0 1 64817 4 3 59280 9 0 1 64849 1 64836 1 64849 2 13 64848 1 64849 3 64836 4 0 1 64849 4 13 41497 14 0 1 64853 1 64851 1 64853 2 2 64849 1 64853 3 64851 3 0 1 64853 4 2 57996 1 0 1 64871 1 64864 1 64871 2 7 64870 1 64871 3 64864 7 0 1 64871 4 7 39297 3 0 1 64877 1 64874 1 64877 2 3 64876 1 64877 3 64874 7 0 1 64877 4 3 60577 6 0 1 64879 1 64873 1 64879 2 6 64878 1 64879 3 64873 3 0 1 64879 4 6 42037 3 0 1 64891 1 64881 1 64891 2 10 64890 1 64891 3 64881 5 0 1 64891 4 10 64217 2 0 1 64901 1 64899 1 64901 2 2 64897 1 64901 3 64899 3 0 1 64901 4 2 52960 6 0 1 64919 1 64912 1 64919 2 7 64917 1 64919 3 64912 9 0 1 64919 4 7 54303 5 0 1 64921 1 64914 1 64921 2 7 64914 1 64921 3 64914 1 0 1 64921 4 7 32920 0 0 1 64927 1 64924 1 64927 2 3 64925 1 64927 3 64924 4 0 1 64927 4 3 55506 6 0 1 64937 1 64934 1 64937 2 3 64932 1 64937 3 64934 1 0 1 64937 4 3 53518 0 0 1 64951 1 64948 1 64951 2 3 64950 1 64951 3 64948 4 0 1 64951 4 3 56365 2 0 1 64969 1 64956 1 64969 2 13 64968 1 64969 3 64956 1 0 1 64969 4 13 53294 14 0 1 64997 1 64995 1 64997 2 2 64993 1 64997 3 64995 3 0 1 64997 4 2 52445 7 0 1 65003 1 64998 1 65003 2 5 65001 1 65003 3 64998 3 0 1 65003 4 5 34388 0 0 1 65011 1 65009 1 65011 2 2 65007 1 65011 3 65009 5 0 1 65011 4 2 57311 8 0 1 65027 1 65025 1 65027 2 2 65021 1 65027 3 65025 4 0 1 65027 4 2 54894 4 0 1 65029 1 65027 1 65029 2 2 65028 1 65029 3 65027 6 0 1 65029 4 2 56829 3 0 1 65033 1 65030 1 65033 2 3 65028 1 65033 3 65030 1 0 1 65033 4 3 58622 0 0 1 65053 1 65048 1 65053 2 5 65050 1 65053 3 65048 9 0 1 65053 4 5 57093 1 0 1 65063 1 65058 1 65063 2 5 65061 1 65063 3 65058 6 0 1 65063 4 5 51223 10 0 1 65071 1 65068 1 65071 2 3 65070 1 65071 3 65068 6 0 1 65071 4 3 40238 3 0 1 65089 1 65082 1 65089 2 7 65086 1 65089 3 65082 2 0 1 65089 4 7 65070 22 0 1 65099 1 65097 1 65099 2 2 65090 1 65099 3 65097 3 0 1 65099 4 2 53861 1 0 1 65101 1 65099 1 65101 2 2 65097 1 65101 3 65099 2 0 1 65101 4 2 61904 10 0 1 65111 1 65104 1 65111 2 7 65110 1 65111 3 65104 1 0 1 65111 4 7 58892 2 0 1 65119 1 65116 1 65119 2 3 65114 1 65119 3 65116 4 0 1 65119 4 3 47853 7 0 1 65123 1 65121 1 65123 2 2 65119 1 65123 3 65121 3 0 1 65123 4 2 55674 8 0 1 65129 1 65126 1 65129 2 3 65120 1 65129 3 65126 1 0 1 65129 4 3 37272 3 0 1 65141 1 65139 1 65141 2 2 65136 1 65141 3 65139 3 0 1 65141 4 2 64516 18 0 1 65147 1 65145 1 65147 2 2 65146 1 65147 3 65145 5 0 1 65147 4 2 41370 10 0 1 65167 1 65162 1 65167 2 5 65165 1 65167 3 65162 3 0 1 65167 4 5 65163 3 0 1 65171 1 65169 1 65171 2 2 65167 1 65171 3 65169 3 0 1 65171 4 2 35802 7 0 1 65173 1 65171 1 65173 2 2 65172 1 65173 3 65171 5 0 1 65173 4 2 58034 6 0 1 65179 1 65177 1 65179 2 2 65175 1 65179 3 65177 2 0 1 65179 4 2 39472 8 0 1 65183 1 65178 1 65183 2 5 65181 1 65183 3 65178 2 0 1 65183 4 5 65179 3 0 1 65203 1 65201 1 65203 2 2 65202 1 65203 3 65201 2 0 1 65203 4 2 56555 10 0 1 65213 1 65211 1 65213 2 2 65209 1 65213 3 65211 3 0 1 65213 4 2 64642 7 0 1 65239 1 65236 1 65239 2 3 65234 1 65239 3 65236 7 0 1 65239 4 3 38859 6 0 1 65257 1 65252 1 65257 2 5 65252 1 65257 3 65252 2 0 1 65257 4 5 49206 12 0 1 65267 1 65265 1 65267 2 2 65266 1 65267 3 65265 2 0 1 65267 4 2 65260 8 0 1 65269 1 65267 1 65269 2 2 65265 1 65269 3 65267 6 0 1 65269 4 2 49182 6 0 1 65287 1 65284 1 65287 2 3 65286 1 65287 3 65284 3 0 1 65287 4 3 40493 5 0 1 65293 1 65291 1 65293 2 2 65289 1 65293 3 65291 6 0 1 65293 4 2 61269 15 0 1 65309 1 65307 1 65309 2 2 65308 1 65309 3 65307 3 0 1 65309 4 2 39470 3 0 1 65323 1 65321 1 65323 2 2 65322 1 65323 3 65321 4 0 1 65323 4 2 51095 2 0 1 65327 1 65322 1 65327 2 5 65320 1 65327 3 65322 1 0 1 65327 4 5 41871 9 0 1 65353 1 65348 1 65353 2 5 65352 1 65353 3 65348 1 0 1 65353 4 5 41358 6 0 1 65357 1 65355 1 65357 2 2 65356 1 65357 3 65355 3 0 1 65357 4 2 58240 3 0 1 65371 1 65369 1 65371 2 2 65370 1 65371 3 65369 4 0 1 65371 4 2 58383 2 0 1 65381 1 65378 1 65381 2 3 65379 1 65381 3 65378 6 0 1 65381 4 3 65373 10 0 1 65393 1 65390 1 65393 2 3 65386 1 65393 3 65390 13 0 1 65393 4 3 40335 13 0 1 65407 1 65404 1 65407 2 3 65405 1 65407 3 65404 1 0 1 65407 4 3 33781 6 0 1 65413 1 65408 1 65413 2 5 65412 1 65413 3 65408 5 0 1 65413 4 5 43090 6 0 1 65419 1 65416 1 65419 2 3 65418 1 65419 3 65416 5 0 1 65419 4 3 33267 7 0 1 65423 1 65418 1 65423 2 5 65420 1 65423 3 65418 2 0 1 65423 4 5 55880 6 0 1 65437 1 65431 1 65437 2 6 65435 1 65437 3 65431 1 0 1 65437 4 6 35512 16 0 1 65447 1 65442 1 65447 2 5 65445 1 65447 3 65442 7 0 1 65447 4 5 34701 5 0 1 65449 1 65438 1 65449 2 11 65445 1 65449 3 65438 1 0 1 65449 4 11 65435 11 0 1 65479 1 65472 1 65479 2 7 65467 1 65479 3 65472 3 0 1 65479 4 7 58767 0 0 1 65497 1 65490 1 65497 2 7 65490 1 65497 3 65490 11 0 1 65497 4 7 42170 14 0 1 65519 1 65508 1 65519 2 11 65518 1 65519 3 65508 2 0 1 65519 4 11 41499 3 0 1 65521 1 65504 1 65521 2 17 65518 1 65521 3 65504 1 0 1 65521 4 17 42121 20 0 1 65537 4 3 48035 7 0 1 65539 4 2 53504 6 0 1 65543 4 5 44768 11 0 1 65551 4 6 65547 6 0 1 65557 4 5 60449 1 0 1 65563 4 3 59509 0 0 1 65579 4 2 39899 7 0 1 65581 4 2 56596 3 0 1 65587 4 2 39688 10 0 1 65599 4 3 48691 3 0 1 65609 4 3 65597 0 0 1 65617 4 13 46802 11 0 1 65629 4 2 64483 2 0 1 65633 4 3 53051 9 0 1 65647 4 3 54892 2 0 1 65651 4 2 58463 2 0 1 65657 4 3 54810 0 0 1 65677 4 2 52138 3 0 1 65687 4 5 39057 5 0 1 65699 4 2 58874 3 0 1 65701 4 6 35742 0 0 1 65707 4 2 62355 2 0 1 65713 4 10 63124 6 0 1 65717 4 2 56730 7 0 1 65719 4 3 65715 4 0 1 65729 4 3 37642 4 0 1 65731 4 10 61963 0 0 1 65761 4 7 65398 16 0 1 65777 4 3 51201 7 0 1 65789 4 2 52108 4 0 1 65809 4 11 36642 23 0 1 65827 4 2 41666 0 0 1 65831 4 31 64129 4 0 1 65837 4 2 56209 18 0 1 65839 4 3 38189 6 0 1 65843 4 2 36484 0 0 1 65851 4 3 44421 3 0 1 65867 4 2 60917 7 0 1 65881 4 11 46761 18 0 1 65899 4 3 56823 3 0 1 65921 4 3 54248 1 0 1 65927 4 5 65915 11 0 1 65929 4 7 45196 14 0 1 65951 4 13 64135 7 0 1 65957 4 2 62325 1 0 1 65963 4 2 38212 7 0 1 65981 4 2 62459 9 0 1 65983 4 3 52265 3 0 1 65993 4 3 37433 1 0 1 66029 4 2 42133 1 0 1 66037 4 2 47483 6 0 1 66041 4 3 51490 2 0 1 66047 4 5 49893 2 0 1 66067 4 3 41503 2 0 1 66071 4 22 33376 7 0 1 66083 4 2 43702 4 0 1 66089 4 3 66077 0 0 1 66103 4 3 64179 3 0 1 66107 4 2 59363 14 0 1 66109 4 2 47832 10 0 1 66137 4 3 36824 0 0 1 66161 4 3 36306 4 0 1 66169 4 14 34612 20 0 1 66173 4 2 48656 4 0 1 66179 4 2 46239 0 0 1 66191 4 11 40036 3 0 1 66221 4 2 43440 6 0 1 66239 4 17 38430 7 0 1 66271 4 3 33897 2 0 1 66293 4 2 36555 1 0 1 66301 4 22 66277 12 0 1 66337 4 5 63257 12 0 1 66343 4 5 53293 2 0 1 66347 4 2 52402 8 0 1 66359 4 13 40724 3 0 1 66361 4 17 54358 35 0 1 66373 4 2 64893 14 0 1 66377 4 3 37215 1 0 1 66383 4 5 46399 10 0 1 66403 4 2 46989 8 0 1 66413 4 2 39202 6 0 1 66431 4 7 43779 9 0 1 66449 4 3 49019 3 0 1 66457 4 5 35848 6 0 1 66463 4 10 47564 2 0 1 66467 4 2 38103 13 0 1 66491 4 2 47685 2 0 1 66499 4 2 46693 6 0 1 66509 4 2 42163 19 0 1 66523 4 2 46700 8 0 1 66529 4 19 34453 26 0 1 66533 4 2 49134 2 0 1 66541 4 6 50298 2 0 1 66553 4 10 57958 6 0 1 66569 4 3 61968 0 0 1 66571 4 7 66124 6 0 1 66587 4 2 46349 2 0 1 66593 4 3 47462 4 0 1 66601 4 7 42297 0 0 1 66617 4 3 37334 0 0 1 66629 4 2 45627 1 0 1 66643 4 2 37302 2 0 1 66653 4 2 37184 1 0 1 66683 4 5 66675 6 0 1 66697 4 5 51165 10 0 1 66701 4 3 39641 3 0 1 66713 4 3 51248 1 0 1 66721 4 13 51624 14 0 1 66733 4 2 49817 10 0 1 66739 4 2 51010 8 0 1 66749 4 3 41570 2 0 1 66751 4 3 61431 7 0 1 66763 4 3 34439 3 0 1 66791 4 7 63890 6 0 1 66797 4 2 46537 6 0 1 66809 4 6 59124 4 0 1 66821 4 2 49306 3 0 1 66841 4 7 35751 24 0 1 66851 4 2 53354 3 0 1 66853 4 2 60261 3 0 1 66863 4 5 61991 2 0 1 66877 4 5 57414 9 0 1 66883 4 2 34328 2 0 1 66889 4 17 40264 20 0 1 66919 4 6 63458 3 0 1 66923 4 2 41480 11 0 1 66931 4 3 49609 2 0 1 66943 4 3 42749 5 0 1 66947 4 2 52267 2 0 1 66949 4 10 59718 12 0 1 66959 4 7 66950 4 0 1 66973 4 2 60937 6 0 1 66977 4 5 47327 6 0 1 67003 4 2 60348 7 0 1 67021 4 7 66503 12 0 1 67033 4 5 40294 16 0 1 67043 4 2 45952 7 0 1 67049 4 3 36231 2 0 1 67057 4 5 66160 20 0 1 67061 4 2 66482 12 0 1 67073 4 3 46520 6 0 1 67079 4 11 59667 2 0 1 67103 4 5 40335 7 0 1 67121 4 6 44101 10 0 1 67129 4 7 47157 17 0 1 67139 4 2 35718 1 0 1 67141 4 2 42216 10 0 1 67153 4 5 60531 10 0 1 67157 4 2 64015 0 0 1 67169 4 3 44657 2 0 1 67181 4 2 40205 6 0 1 67187 4 2 39121 8 0 1 67189 4 6 34897 2 0 1 67211 4 2 66762 8 0 1 67213 4 2 34141 6 0 1 67217 4 3 63758 6 0 1 67219 4 11 52068 1 0 1 67231 4 3 47479 2 0 1 67247 4 5 63238 5 0 1 67261 4 2 54686 3 0 1 67271 4 14 36213 10 0 1 67273 4 7 62964 10 0 1 67289 4 3 60185 7 0 1 67307 4 2 38062 7 0 1 67339 4 3 39869 7 0 1 67343 4 5 67339 3 0 1 67349 4 2 50278 9 0 1 67369 4 19 38219 42 0 1 67391 4 7 40053 3 0 1 67399 4 3 37548 3 0 1 67409 4 3 67397 0 0 1 67411 4 2 40791 8 0 1 67421 4 2 39383 1 0 1 67427 4 2 54909 7 0 1 67429 4 2 62571 3 0 1 67433 4 3 62067 0 0 1 67447 4 3 60311 2 0 1 67453 4 2 45967 21 0 1 67477 4 2 54738 12 0 1 67481 4 3 34031 2 0 1 67489 4 23 65362 27 0 1 67493 4 2 34037 1 0 1 67499 4 2 34518 7 0 1 67511 4 11 52043 3 0 1 67523 4 2 44628 7 0 1 67531 4 10 40415 0 0 1 67537 4 5 46327 16 0 1 67547 4 2 37219 0 0 1 67559 4 7 65191 2 0 1 67567 4 3 36628 6 0 1 67577 4 3 66797 6 0 1 67579 4 7 65404 8 0 1 67589 4 2 58765 0 0 1 67601 4 3 67233 1 0 1 67607 4 5 66360 5 0 1 67619 4 2 44755 2 0 1 67631 4 7 51169 2 0 1 67651 4 11 40363 10 0 1 67679 4 19 66816 9 0 1 67699 4 2 59915 2 0 1 67709 4 2 50938 0 0 1 67723 4 5 38763 0 0 1 67733 4 2 36882 0 0 1 67741 4 6 67733 12 0 1 67751 4 13 39889 5 0 1 67757 4 3 67753 4 0 1 67759 4 6 60346 3 0 1 67763 4 2 50484 10 0 1 67777 4 5 54147 16 0 1 67783 4 3 57395 3 0 1 67789 4 6 62008 2 0 1 67801 4 11 44970 12 0 1 67807 4 3 44975 3 0 1 67819 4 10 46696 0 0 1 67829 4 2 64028 1 0 1 67843 4 14 60029 0 0 1 67853 4 2 41571 6 0 1 67867 4 2 54474 8 0 1 67883 4 2 42483 8 0 1 67891 4 3 47030 2 0 1 67901 4 3 67897 4 0 1 67927 4 3 53290 2 0 1 67931 4 6 67921 7 0 1 67933 4 2 50804 3 0 1 67939 4 3 56500 6 0 1 67943 4 5 41694 3 0 1 67957 4 2 58354 9 0 1 67961 4 3 67949 0 0 1 67967 4 5 67963 3 0 1 67979 4 2 65282 4 0 1 67987 4 2 58210 2 0 1 67993 4 5 67982 14 0 1 68023 4 3 66480 5 0 1 68041 4 22 53027 0 0 1 68053 4 5 50643 3 0 1 68059 4 2 61367 7 0 1 68071 4 6 63651 2 0 1 68087 4 5 61008 12 0 1 68099 4 2 56605 7 0 1 68111 4 7 56197 5 0 1 68113 4 5 58986 19 0 1 68141 4 3 56253 11 0 1 68147 4 2 50319 7 0 1 68161 4 13 61180 35 0 1 68171 4 2 53531 7 0 1 68207 4 5 57650 4 0 1 68209 4 13 66709 24 0 1 68213 4 2 34705 3 0 1 68219 4 2 48877 8 0 1 68227 4 2 67030 7 0 1 68239 4 3 42806 3 0 1 68261 4 2 64746 6 0 1 68279 4 7 54053 7 0 1 68281 4 7 62806 17 0 1 68311 4 6 35999 3 0 1 68329 4 11 44735 12 0 1 68351 4 17 39570 5 0 1 68371 4 7 67918 6 0 1 68389 4 2 43445 3 0 1 68399 4 7 67493 4 0 1 68437 4 2 65782 3 0 1 68443 4 5 68435 6 0 1 68447 4 5 68443 3 0 1 68449 4 7 61208 0 0 1 68473 4 10 59060 14 0 1 68477 4 2 64640 3 0 1 68483 4 2 35912 18 0 1 68489 4 3 44684 2 0 1 68491 4 10 64941 5 0 1 68501 4 3 59518 4 0 1 68507 4 2 46230 4 0 1 68521 4 7 44205 0 0 1 68531 4 6 36372 0 0 1 68539 4 2 48277 3 0 1 68543 4 5 67315 3 0 1 68567 4 5 63503 3 0 1 68581 4 6 39927 2 0 1 68597 4 2 43600 12 0 1 68611 4 2 35758 8 0 1 68633 4 3 61618 1 0 1 68639 4 7 39801 7 0 1 68659 4 2 57459 2 0 1 68669 4 2 48273 3 0 1 68683 4 2 68676 8 0 1 68687 4 5 50345 3 0 1 68699 4 2 44701 0 0 1 68711 4 11 43127 5 0 1 68713 4 5 48329 16 0 1 68729 4 3 68717 0 0 1 68737 4 5 56637 11 0 1 68743 4 3 68739 4 0 1 68749 4 6 52637 0 0 1 68767 4 3 36909 2 0 1 68771 4 10 54749 6 0 1 68777 4 3 48049 0 0 1 68791 4 3 46092 2 0 1 68813 4 2 57442 3 0 1 68819 4 2 65671 8 0 1 68821 4 14 58139 1 0 1 68863 4 3 68855 10 0 1 68879 4 13 60045 16 0 1 68881 4 22 68855 19 0 1 68891 4 2 43114 3 0 1 68897 4 3 47010 9 0 1 68899 4 2 59615 2 0 1 68903 4 5 36021 5 0 1 68909 4 2 65803 7 0 1 68917 4 5 38485 1 0 1 68927 4 5 52010 8 0 1 68947 4 2 60274 35 0 1 68963 4 2 53458 2 0 1 68993 4 3 64207 1 0 1 69001 4 19 67000 32 0 1 69011 4 6 63999 9 0 1 69019 4 2 47422 2 0 1 69029 4 2 52075 2 0 1 69031 4 3 55096 3 0 1 69061 4 2 59670 6 0 1 69067 4 2 69060 8 0 1 69073 4 10 41305 0 0 1 69109 4 2 53659 3 0 1 69119 4 13 35190 4 0 1 69127 4 5 69123 3 0 1 69143 4 5 43087 2 0 1 69149 4 2 56221 2 0 1 69151 4 11 57951 3 0 1 69163 4 2 69156 8 0 1 69191 4 11 53053 5 0 1 69193 4 10 35071 8 0 1 69197 4 2 68453 9 0 1 69203 4 2 68459 15 0 1 69221 4 2 45363 12 0 1 69233 4 3 35325 4 0 1 69239 4 7 50195 3 0 1 69247 4 3 59921 5 0 1 69257 4 3 68051 2 0 1 69259 4 2 39845 8 0 1 69263 4 5 59152 8 0 1 69313 4 10 67033 0 0 1 69317 4 3 51122 4 0 1 69337 4 5 48687 15 0 1 69341 4 3 69333 10 0 1 69371 4 2 38806 8 0 1 69379 4 2 53834 8 0 1 69383 4 5 69379 3 0 1 69389 4 2 45620 4 0 1 69401 4 6 58645 4 0 1 69403 4 14 66102 7 0 1 69427 4 2 49466 8 0 1 69431 4 13 60664 7 0 1 69439 4 3 68321 3 0 1 69457 4 5 66848 6 0 1 69463 4 6 47263 4 0 1 69467 4 2 43474 2 0 1 69473 4 3 44504 0 0 1 69481 4 7 56254 2 0 1 69491 4 2 35320 8 0 1 69493 4 2 61830 6 0 1 69497 4 3 56279 7 0 1 69499 4 3 49301 5 0 1 69539 4 2 36956 7 0 1 69557 4 2 37857 4 0 1 69593 4 3 61280 1 0 1 69623 4 5 35040 6 0 1 69653 4 2 40852 1 0 1 69661 4 6 46057 7 0 1 69677 4 2 67391 4 0 1 69691 4 2 54995 2 0 1 69697 4 5 38932 12 0 1 69709 4 11 59497 11 0 1 69737 4 3 40589 4 0 1 69739 4 2 41714 2 0 1 69761 4 3 54923 4 0 1 69763 4 2 43287 10 0 1 69767 4 5 60380 5 0 1 69779 4 2 62123 7 0 1 69809 4 3 50037 0 0 1 69821 4 7 45311 9 0 1 69827 4 2 66053 24 0 1 69829 4 10 41766 14 0 1 69833 4 5 62115 10 0 1 69847 4 10 57258 3 0 1 69857 4 3 43449 4 0 1 69859 4 10 54267 1 0 1 69877 4 2 40066 6 0 1 69899 4 2 65475 4 0 1 69911 4 7 69902 4 0 1 69929 4 3 51163 2 0 1 69931 4 3 69231 2 0 1 69941 4 2 43594 6 0 1 69959 4 7 54329 5 0 1 69991 4 3 68518 3 0 1 69997 4 2 67197 2 0 1 70001 4 3 63569 4 0 1 70003 4 2 42929 10 0 1 70009 4 19 60077 32 0 1 70019 4 6 38012 5 0 1 70039 4 3 51654 2 0 1 70051 4 7 37283 6 0 1 70061 4 2 68098 3 0 1 70067 4 2 69150 0 0 1 70079 4 7 40728 3 0 1 70099 4 3 45248 2 0 1 70111 4 6 57088 3 0 1 70117 4 2 47614 6 0 1 70121 4 6 36468 7 0 1 70123 4 2 50832 14 0 1 70139 4 2 42365 1 0 1 70141 4 10 69186 12 0 1 70157 4 2 42002 5 0 1 70163 4 2 43249 1 0 1 70177 4 5 51571 6 0 1 70181 4 7 65289 0 0 1 70183 4 3 70179 4 0 1 70199 4 17 53238 8 0 1 70201 4 14 54788 8 0 1 70207 4 5 42032 5 0 1 70223 4 5 37478 3 0 1 70229 4 2 47017 4 0 1 70237 4 2 56553 3 0 1 70241 4 6 53215 4 0 1 70249 4 23 41688 34 0 1 70271 4 11 68323 5 0 1 70289 4 3 64290 4 0 1 70297 4 5 47250 10 0 1 70309 4 6 53424 11 0 1 70313 4 3 56400 11 0 1 70321 4 7 36964 17 0 1 70327 4 11 68433 14 0 1 70351 4 6 63404 2 0 1 70373 4 2 51044 6 0 1 70379 4 6 57535 0 0 1 70381 4 10 56129 1 0 1 70393 4 5 48327 10 0 1 70423 4 5 70419 3 0 1 70429 4 10 59245 2 0 1 70439 4 13 36995 6 0 1 70451 4 6 57297 5 0 1 70457 4 3 60784 4 0 1 70459 4 3 51996 2 0 1 70481 4 3 48650 2 0 1 70487 4 5 44704 14 0 1 70489 4 17 45627 20 0 1 70501 4 2 64881 10 0 1 70507 4 2 44678 2 0 1 70529 4 3 56755 7 0 1 70537 4 5 62941 15 0 1 70549 4 2 56638 3 0 1 70571 4 2 54714 7 0 1 70573 4 2 70566 8 0 1 70583 4 5 70579 3 0 1 70589 4 2 49075 4 0 1 70607 4 5 58381 4 0 1 70619 4 2 61619 2 0 1 70621 4 6 41805 7 0 1 70627 4 7 53445 13 0 1 70639 4 3 61082 3 0 1 70657 4 7 36137 8 0 1 70663 4 3 54656 2 0 1 70667 4 2 59153 3 0 1 70687 4 5 70671 18 0 1 70709 4 2 57901 6 0 1 70717 4 2 39997 6 0 1 70729 4 22 48128 0 0 1 70753 4 5 63030 15 0 1 70769 4 3 53835 4 0 1 70783 4 3 36793 7 0 1 70793 4 3 53597 6 0 1 70823 4 5 63787 2 0 1 70841 4 3 48633 1 0 1 70843 4 2 69291 7 0 1 70849 4 17 38090 35 0 1 70853 4 2 66950 3 0 1 70867 4 3 68822 3 0 1 70877 4 2 54683 2 0 1 70879 4 3 43553 2 0 1 70891 4 3 65467 2 0 1 70901 4 2 67460 3 0 1 70913 4 3 42051 4 0 1 70919 4 7 39710 6 0 1 70921 4 13 54135 14 0 1 70937 4 3 56041 11 0 1 70949 4 2 62905 0 0 1 70951 4 6 57780 3 0 1 70957 4 2 51988 3 0 1 70969 4 11 61783 16 0 1 70979 4 2 57757 2 0 1 70981 4 6 66178 2 0 1 70991 4 7 61011 2 0 1 70997 4 2 38359 9 0 1 70999 4 11 66744 9 0 1 71011 4 15 49875 6 0 1 71023 4 6 58735 3 0 1 71039 4 11 68825 6 0 1 71059 4 7 41189 6 0 1 71069 4 2 43626 9 0 1 71081 4 3 69416 7 0 1 71089 4 11 39634 22 0 1 71119 4 3 67357 8 0 1 71129 4 3 43019 2 0 1 71143 4 6 70219 7 0 1 71147 4 2 46222 4 0 1 71153 4 3 42472 9 0 1 71161 4 11 66960 12 0 1 71167 4 3 59112 2 0 1 71171 4 2 51451 4 0 1 71191 4 3 47696 2 0 1 71209 4 7 45847 0 0 1 71233 4 11 55561 7 0 1 71237 4 2 65919 6 0 1 71249 4 3 70494 4 0 1 71257 4 5 71246 14 0 1 71261 4 3 66274 12 0 1 71263 4 5 54562 2 0 1 71287 4 3 41172 2 0 1 71293 4 5 67279 1 0 1 71317 4 2 52171 12 0 1 71327 4 5 71323 3 0 1 71329 4 7 42666 0 0 1 71333 4 2 49522 11 0 1 71339 4 2 42483 13 0 1 71341 4 6 71337 6 0 1 71347 4 2 55724 7 0 1 71353 4 5 41313 12 0 1 71359 4 6 44808 4 0 1 71363 4 2 52079 10 0 1 71387 4 2 44921 15 0 1 71389 4 11 46466 8 0 1 71399 4 11 35931 2 0 1 71411 4 2 40070 7 0 1 71413 4 2 71406 8 0 1 71419 4 2 68999 7 0 1 71429 4 2 50209 6 0 1 71437 4 2 54737 10 0 1 71443 4 11 36676 5 0 1 71453 4 2 37951 3 0 1 71471 4 7 41094 4 0 1 71473 4 5 45163 6 0 1 71479 4 6 56282 10 0 1 71483 4 2 47456 4 0 1 71503 4 3 68586 6 0 1 71527 4 3 39248 6 0 1 71537 4 3 36582 0 0 1 71549 4 2 70584 4 0 1 71551 4 6 64114 3 0 1 71563 4 2 58689 8 0 1 71569 4 19 60317 32 0 1 71593 4 5 36565 15 0 1 71597 4 2 70889 0 0 1 71633 4 3 38013 4 0 1 71647 4 3 59824 6 0 1 71663 4 5 51461 2 0 1 71671 4 15 43839 3 0 1 71693 4 2 55090 1 0 1 71699 4 2 67291 6 0 1 71707 4 2 63239 1 0 1 71711 4 17 38247 7 0 1 71713 4 5 47165 12 0 1 71719 4 3 63829 3 0 1 71741 4 2 65142 3 0 1 71761 4 44 51693 13 0 1 71777 4 3 58795 9 0 1 71789 4 2 48870 0 0 1 71807 4 5 71795 11 0 1 71809 4 7 68346 17 0 1 71821 4 2 47183 10 0 1 71837 4 2 41955 3 0 1 71843 4 2 37674 8 0 1 71849 4 3 43545 7 0 1 71861 4 7 57037 5 0 1 71867 4 2 55662 2 0 1 71879 4 11 58652 2 0 1 71881 4 7 51859 0 0 1 71887 4 3 55991 2 0 1 71899 4 2 65761 8 0 1 71909 4 2 71061 3 0 1 71917 4 2 41181 6 0 1 71933 4 2 62443 6 0 1 71941 4 2 48283 6 0 1 71947 4 2 67395 8 0 1 71963 4 2 71956 8 0 1 71971 4 2 40745 8 0 1 71983 4 3 64115 5 0 1 71987 4 2 47287 26 0 1 71993 4 3 53608 1 0 1 71999 4 7 57398 7 0 1 72019 4 2 62742 1 0 1 72031 4 3 55350 3 0 1 72043 4 5 41388 8 0 1 72047 4 5 62811 5 0 1 72053 4 2 59135 7 0 1 72073 4 5 48859 10 0 1 72077 4 2 42757 4 0 1 72089 4 3 72077 0 0 1 72091 4 2 60530 2 0 1 72101 4 2 63163 12 0 1 72103 4 6 57940 2 0 1 72109 4 2 46459 6 0 1 72139 4 2 45029 8 0 1 72161 4 6 44064 4 0 1 72167 4 5 72163 3 0 1 72169 4 7 37026 0 0 1 72173 4 2 47862 1 0 1 72211 4 2 62661 2 0 1 72221 4 2 42079 6 0 1 72223 4 3 63494 17 0 1 72227 4 2 60882 2 0 1 72229 4 2 71628 9 0 1 72251 4 7 72242 4 0 1 72253 4 2 36427 6 0 1 72269 4 3 58151 3 0 1 72271 4 3 65518 3 0 1 72277 4 5 66880 1 0 1 72287 4 5 72283 3 0 1 72307 4 3 64560 0 0 1 72313 4 5 62407 6 0 1 72337 4 7 39917 17 0 1 72341 4 2 58293 9 0 1 72353 4 3 55199 0 0 1 72367 4 3 62623 6 0 1 72379 4 2 51422 12 0 1 72383 4 5 71622 4 0 1 72421 4 6 66249 7 0 1 72431 4 13 58708 6 0 1 72461 4 2 43369 6 0 1 72467 4 2 61622 13 0 1 72469 4 6 60664 7 0 1 72481 4 11 36542 8 0 1 72493 4 2 69682 6 0 1 72497 4 5 36734 6 0 1 72503 4 5 54638 2 0 1 72533 4 2 64635 1 0 1 72547 4 2 72540 8 0 1 72551 4 13 41107 9 0 1 72559 4 3 46343 14 0 1 72577 4 5 72566 14 0 1 72613 4 2 57646 6 0 1 72617 4 3 69042 4 0 1 72623 4 5 59960 8 0 1 72643 4 2 49227 17 0 1 72647 4 5 72643 3 0 1 72649 4 7 47012 17 0 1 72661 4 11 62100 3 0 1 72671 4 7 61218 3 0 1 72673 4 5 72662 14 0 1 72679 4 6 41235 3 0 1 72689 4 3 69268 2 0 1 72701 4 2 72694 8 0 1 72707 4 2 55870 7 0 1 72719 4 11 63204 5 0 1 72727 4 7 64380 0 0 1 72733 4 2 62105 6 0 1 72739 4 2 52065 15 0 1 72763 4 2 50862 16 0 1 72767 4 5 44380 4 0 1 72797 4 2 68786 6 0 1 72817 4 5 40745 25 0 1 72823 4 5 39509 5 0 1 72859 4 2 42403 2 0 1 72869 4 2 72862 8 0 1 72871 4 6 49897 2 0 1 72883 4 3 40725 8 0 1 72889 4 7 59320 0 0 1 72893 4 2 52422 6 0 1 72901 4 2 65487 7 0 1 72907 4 2 42627 8 0 1 72911 4 11 39056 6 0 1 72923 4 2 55043 8 0 1 72931 4 10 60579 9 0 1 72937 4 5 39982 6 0 1 72949 4 2 52415 12 0 1 72953 4 3 65046 9 0 1 72959 4 17 72933 17 0 1 72973 4 2 45763 7 0 1 72977 4 3 45322 0 0 1 72997 4 2 60557 9 0 1 73009 4 7 61290 1 0 1 73013 4 2 38041 4 0 1 73019 4 2 47919 3 0 1 73037 4 2 44880 3 0 1 73039 4 3 59389 2 0 1 73043 4 2 66445 7 0 1 73061 4 2 58871 6 0 1 73063 4 3 48207 3 0 1 73079 4 13 40351 4 0 1 73091 4 2 43963 4 0 1 73121 4 3 42292 2 0 1 73127 4 5 73123 3 0 1 73133 4 2 72158 17 0 1 73141 4 7 43993 4 0 1 73181 4 2 47002 7 0 1 73189 4 2 55841 12 0 1 73237 4 6 65241 6 0 1 73243 4 3 71712 2 0 1 73259 4 2 61316 7 0 1 73277 4 3 73273 4 0 1 73291 4 3 69472 11 0 1 73303 4 5 62926 5 0 1 73309 4 2 66589 9 0 1 73327 4 3 73323 4 0 1 73331 4 2 42910 4 0 1 73351 4 3 65865 6 0 1 73361 4 11 51499 4 0 1 73363 4 5 73359 3 0 1 73369 4 11 70828 16 0 1 73379 4 2 72262 1 0 1 73387 4 2 73380 8 0 1 73417 4 10 53155 21 0 1 73421 4 2 37199 3 0 1 73433 4 3 48227 1 0 1 73453 4 2 72911 10 0 1 73459 4 2 49334 8 0 1 73471 4 3 73467 4 0 1 73477 4 6 68628 8 0 1 73483 4 2 70827 8 0 1 73517 4 2 53158 6 0 1 73523 4 2 46328 0 0 1 73529 4 3 42582 0 0 1 73547 4 2 66601 13 0 1 73553 4 3 64744 7 0 1 73561 4 13 42718 16 0 1 73571 4 2 68944 8 0 1 73583 4 5 63211 3 0 1 73589 4 2 41254 14 0 1 73597 4 2 51616 9 0 1 73607 4 5 66527 6 0 1 73609 4 19 72074 14 0 1 73613 4 2 37537 12 0 1 73637 4 2 56357 4 0 1 73643 4 2 51879 14 0 1 73651 4 2 67415 8 0 1 73673 4 3 57691 4 0 1 73679 4 14 64280 6 0 1 73681 4 14 57935 0 0 1 73693 4 2 58210 9 0 1 73699 4 2 67161 1 0 1 73709 4 2 39653 4 0 1 73721 4 6 53276 0 0 1 73727 4 5 73715 11 0 1 73751 4 13 42278 3 0 1 73757 4 2 53235 3 0 1 73771 4 2 43300 6 0 1 73783 4 3 72176 5 0 1 73819 4 3 46285 3 0 1 73823 4 5 38688 2 0 1 73847 4 5 73843 3 0 1 73849 4 7 54332 0 0 1 73859 4 2 68126 3 0 1 73867 4 2 51175 2 0 1 73877 4 2 51052 4 0 1 73883 4 2 72698 0 0 1 73897 4 5 62054 16 0 1 73907 4 2 38461 9 0 1 73939 4 2 73468 1 0 1 73943 4 5 67134 3 0 1 73951 4 3 65283 3 0 1 73961 4 3 73949 0 0 1 73973 4 2 69985 8 0 1 73999 4 6 37849 10 0 1 74017 4 7 60515 10 0 1 74021 4 2 66942 1 0 1 74027 4 2 60175 14 0 1 74047 4 3 66570 5 0 1 74051 4 6 59760 2 0 1 74071 4 14 65525 3 0 1 74077 4 5 69539 3 0 1 74093 4 2 48470 9 0 1 74099 4 2 56842 0 0 1 74101 4 2 74094 8 0 1 74131 4 2 73228 8 0 1 74143 4 5 74139 3 0 1 74149 4 2 60624 7 0 1 74159 4 13 74147 5 0 1 74161 4 7 61232 0 0 1 74167 4 5 46898 2 0 1 74177 4 3 73054 1 0 1 74189 4 2 74182 8 0 1 74197 4 5 61162 6 0 1 74201 4 6 46682 0 0 1 74203 4 2 59268 2 0 1 74209 4 19 72874 0 0 1 74219 4 2 45079 4 0 1 74231 4 11 64699 9 0 1 74257 4 5 62236 32 0 1 74279 4 7 74270 4 0 1 74287 4 3 74283 4 0 1 74293 4 5 45178 6 0 1 74297 4 3 43437 5 0 1 74311 4 12 69621 3 0 1 74317 4 2 42707 6 0 1 74323 4 5 65969 2 0 1 74353 4 5 44387 10 0 1 74357 4 2 64986 1 0 1 74363 4 2 53504 8 0 1 74377 4 5 58041 23 0 1 74381 4 2 60053 1 0 1 74383 4 5 74367 18 0 1 74411 4 2 63354 7 0 1 74413 4 5 52255 7 0 1 74419 4 2 52003 8 0 1 74441 4 3 74429 0 0 1 74449 4 13 43654 14 0 1 74453 4 2 67106 6 0 1 74471 4 11 38724 5 0 1 74489 4 3 70962 7 0 1 74507 4 2 45482 7 0 1 74509 4 2 66467 10 0 1 74521 4 13 71684 10 0 1 74527 4 3 56896 5 0 1 74531 4 2 45219 7 0 1 74551 4 11 67291 2 0 1 74561 4 3 74549 0 0 1 74567 4 5 74563 3 0 1 74573 4 2 55217 6 0 1 74587 4 2 74114 8 0 1 74597 4 2 50072 3 0 1 74609 4 3 48007 2 0 1 74611 4 2 41939 2 0 1 74623 4 3 39560 5 0 1 74653 4 2 37632 3 0 1 74687 4 5 48383 5 0 1 74699 4 2 61778 7 0 1 74707 4 2 72057 7 0 1 74713 4 10 47033 16 0 1 74717 4 2 67732 1 0 1 74719 4 7 52460 0 0 1 74729 4 3 65169 4 0 1 74731 4 2 46647 5 0 1 74747 4 2 52370 7 0 1 74759 4 11 68112 3 0 1 74761 4 19 57690 18 0 1 74771 4 2 53812 4 0 1 74779 4 2 65169 6 0 1 74797 4 5 67484 7 0 1 74821 4 6 74817 6 0 1 74827 4 3 53210 5 0 1 74831 4 7 46151 4 0 1 74843 4 2 65225 7 0 1 74857 4 5 42453 10 0 1 74861 4 2 59239 1 0 1 74869 4 2 43349 37 0 1 74873 4 3 52027 4 0 1 74887 4 3 62207 2 0 1 74891 4 2 45677 9 0 1 74897 4 3 44783 1 0 1 74903 4 5 74899 3 0 1 74923 4 5 74919 3 0 1 74929 4 17 74910 26 0 1 74933 4 2 56989 6 0 1 74941 4 6 38035 8 0 1 74959 4 3 74955 4 0 1 75011 4 6 75001 7 0 1 75013 4 2 68366 10 0 1 75017 4 3 45462 8 0 1 75029 4 2 43015 4 0 1 75037 4 2 55138 10 0 1 75041 4 3 60728 2 0 1 75079 4 3 49811 3 0 1 75083 4 2 38728 7 0 1 75109 4 2 70881 7 0 1 75133 4 2 63032 6 0 1 75149 4 2 57023 0 0 1 75161 4 3 57173 2 0 1 75167 4 5 73433 5 0 1 75169 4 7 59133 0 0 1 75181 4 2 61827 6 0 1 75193 4 7 45746 10 0 1 75209 4 3 75197 0 0 1 75211 4 2 53922 6 0 1 75217 4 5 65957 23 0 1 75223 4 3 64366 3 0 1 75227 4 2 38702 2 0 1 75239 4 13 74289 16 0 1 75253 4 2 43719 3 0 1 75269 4 2 61218 3 0 1 75277 4 2 53931 6 0 1 75289 4 13 63503 40 0 1 75307 4 3 66690 6 0 1 75323 4 2 39729 7 0 1 75329 4 3 75317 0 0 1 75337 4 5 59122 6 0 1 75347 4 2 55916 11 0 1 75353 4 3 49497 9 0 1 75367 4 3 54296 5 0 1 75377 4 3 47702 9 0 1 75389 4 2 50980 3 0 1 75391 4 3 62947 3 0 1 75401 4 3 64247 7 0 1 75403 4 3 47857 2 0 1 75407 4 5 75403 3 0 1 75431 4 19 64329 3 0 1 75437 4 2 52905 3 0 1 75479 4 19 54717 2 0 1 75503 4 5 75499 3 0 1 75511 4 3 63924 2 0 1 75521 4 3 58652 4 0 1 75527 4 5 39797 2 0 1 75533 4 2 55610 3 0 1 75539 4 2 71048 0 0 1 75541 4 2 61862 6 0 1 75553 4 5 49539 10 0 1 75557 4 2 41269 1 0 1 75571 4 2 41127 2 0 1 75577 4 17 75551 17 0 1 75583 4 5 57532 20 0 1 75611 4 2 56351 3 0 1 75617 4 3 49824 2 0 1 75619 4 2 38524 5 0 1 75629 4 2 74529 12 0 1 75641 4 3 75252 2 0 1 75653 4 2 63291 6 0 1 75659 4 2 66607 2 0 1 75679 4 6 61237 4 0 1 75683 4 2 44590 2 0 1 75689 4 3 75677 0 0 1 75703 4 5 49498 9 0 1 75707 4 2 44851 6 0 1 75709 4 2 62812 12 0 1 75721 4 11 68593 20 0 1 75731 4 2 47760 19 0 1 75743 4 5 62967 4 0 1 75767 4 5 48472 7 0 1 75773 4 2 42560 6 0 1 75781 4 6 74581 8 0 1 75787 4 5 73821 2 0 1 75793 4 10 53297 8 0 1 75797 4 2 39226 7 0 1 75821 4 2 46250 0 0 1 75833 4 3 38658 4 0 1 75853 4 5 48073 1 0 1 75869 4 2 57594 0 0 1 75883 4 2 39825 7 0 1 75913 4 5 49747 12 0 1 75931 4 3 46134 3 0 1 75937 4 10 42999 0 0 1 75941 4 2 58727 3 0 1 75967 4 3 75963 4 0 1 75979 4 2 49107 8 0 1 75983 4 5 66619 7 0 1 75989 4 2 72681 0 0 1 75991 4 11 61459 4 0 1 75997 4 2 67184 6 0 1 76001 4 3 53826 2 0 1 76003 4 5 45793 5 0 1 76031 4 7 61858 2 0 1 76039 4 12 48240 3 0 1 76079 4 11 67672 7 0 1 76081 4 7 46107 0 0 1 76091 4 2 48161 8 0 1 76099 4 7 66436 6 0 1 76103 4 5 71301 6 0 1 76123 4 3 67204 3 0 1 76129 4 17 76086 48 0 1 76147 4 2 43774 8 0 1 76157 4 2 75162 6 0 1 76159 4 3 68242 6 0 1 76163 4 2 64513 3 0 1 76207 4 3 73692 5 0 1 76213 4 5 65965 7 0 1 76231 4 6 56446 4 0 1 76243 4 3 42989 5 0 1 76249 4 7 56790 0 0 1 76253 4 2 59618 4 0 1 76259 4 2 58288 7 0 1 76261 4 2 76254 8 0 1 76283 4 2 57665 7 0 1 76289 4 3 54581 4 0 1 76303 4 3 75307 8 0 1 76333 4 5 62666 3 0 1 76343 4 5 58212 0 0 1 76367 4 5 68296 7 0 1 76369 4 11 76355 11 0 1 76379 4 2 40673 0 0 1 76387 4 3 67788 2 0 1 76403 4 2 67684 7 0 1 76421 4 3 74011 6 0 1 76423 4 5 76407 18 0 1 76441 4 11 48662 23 0 1 76463 4 5 54082 5 0 1 76471 4 6 47297 3 0 1 76481 4 3 39574 2 0 1 76487 4 5 53589 2 0 1 76493 4 2 42860 2 0 1 76507 4 2 69273 8 0 1 76511 4 7 54082 11 0 1 76519 4 3 59686 6 0 1 76537 4 5 42941 10 0 1 76541 4 2 76534 8 0 1 76543 4 3 40615 6 0 1 76561 4 17 46886 20 0 1 76579 4 14 50427 2 0 1 76597 4 7 43441 10 0 1 76603 4 2 58855 8 0 1 76607 4 5 73867 7 0 1 76631 4 7 70497 6 0 1 76649 4 6 56278 0 0 1 76651 4 3 52165 5 0 1 76667 4 2 62005 7 0 1 76673 4 3 66368 9 0 1 76679 4 7 55592 4 0 1 76697 4 3 50870 1 0 1 76717 4 2 45082 9 0 1 76733 4 2 56050 3 0 1 76753 4 5 39385 6 0 1 76757 4 2 49527 3 0 1 76771 4 2 71492 8 0 1 76777 4 5 76766 14 0 1 76781 4 2 67454 9 0 1 76801 4 17 48804 20 0 1 76819 4 7 66753 8 0 1 76829 4 2 61574 6 0 1 76831 4 29 58581 2 0 1 76837 4 5 60173 1 0 1 76847 4 5 50138 9 0 1 76871 4 7 58549 2 0 1 76873 4 10 60065 22 0 1 76883 4 2 41684 4 0 1 76907 4 2 55765 7 0 1 76913 4 3 52470 0 0 1 76919 4 13 48489 3 0 1 76943 4 10 69382 4 0 1 76949 4 2 72266 1 0 1 76961 4 3 76949 0 0 1 76963 4 3 67494 7 0 1 76991 4 13 55398 4 0 1 77003 4 2 55719 2 0 1 77017 4 7 64348 10 0 1 77023 4 3 75692 6 0 1 77029 4 2 58146 0 0 1 77041 4 7 60137 0 0 1 77047 4 3 61257 3 0 1 77069 4 2 75574 1 0 1 77081 4 3 77069 0 0 1 77093 4 2 72956 4 0 1 77101 4 7 40000 4 0 1 77137 4 13 71265 4 0 1 77141 4 3 77137 4 0 1 77153 4 3 46439 0 0 1 77167 4 21 39536 12 0 1 77171 4 2 55211 4 0 1 77191 4 6 70075 10 0 1 77201 4 3 60243 2 0 1 77213 4 2 41850 4 0 1 77237 4 2 56993 3 0 1 77239 4 3 61017 2 0 1 77243 4 2 52825 2 0 1 77249 4 3 52093 4 0 1 77261 4 2 59385 19 0 1 77263 4 5 77251 11 0 1 77267 4 2 60416 7 0 1 77269 4 2 73786 9 0 1 77279 4 11 56247 5 0 1 77291 4 2 65473 0 0 1 77317 4 2 67074 19 0 1 77323 4 2 59021 8 0 1 77339 4 2 51352 4 0 1 77347 4 3 63248 2 0 1 77351 4 14 39544 7 0 1 77359 4 3 55517 2 0 1 77369 4 3 42002 7 0 1 77377 4 5 74267 10 0 1 77383 4 3 66656 3 0 1 77417 4 3 57001 9 0 1 77419 4 2 48070 2 0 1 77431 4 3 43837 2 0 1 77447 4 5 65461 4 0 1 77471 4 7 44438 3 0 1 77477 4 2 69614 4 0 1 77479 4 6 64095 5 0 1 77489 4 3 68695 3 0 1 77491 4 3 47151 2 0 1 77509 4 2 46053 7 0 1 77513 4 3 70285 1 0 1 77521 4 7 61075 0 0 1 77527 4 5 39718 10 0 1 77543 4 5 77539 3 0 1 77549 4 2 58006 1 0 1 77551 4 6 52072 3 0 1 77557 4 5 42053 6 0 1 77563 4 2 56342 10 0 1 77569 4 13 77530 0 0 1 77573 4 2 52860 1 0 1 77587 4 2 50630 2 0 1 77591 4 13 39037 6 0 1 77611 4 2 73968 8 0 1 77617 4 10 58808 6 0 1 77621 4 2 77614 8 0 1 77641 4 13 76166 42 0 1 77647 4 3 60310 6 0 1 77659 4 2 73063 8 0 1 77681 4 3 77669 0 0 1 77687 4 5 53507 3 0 1 77689 4 14 62425 8 0 1 77699 4 2 52513 9 0 1 77711 4 14 66066 7 0 1 77713 4 7 43614 12 0 1 77719 4 6 76382 8 0 1 77723 4 2 58596 8 0 1 77731 4 2 53946 2 0 1 77743 4 3 44481 2 0 1 77747 4 2 77740 8 0 1 77761 4 11 39193 16 0 1 77773 4 2 65208 6 0 1 77783 4 5 75933 5 0 1 77797 4 5 43634 10 0 1 77801 4 7 77783 13 0 1 77813 4 2 46881 7 0 1 77839 4 3 39991 6 0 1 77849 4 3 53594 13 0 1 77863 4 5 77859 3 0 1 77867 4 2 41264 2 0 1 77893 4 2 40695 10 0 1 77899 4 14 75848 2 0 1 77929 4 14 47811 9 0 1 77933 4 2 67619 2 0 1 77951 4 11 55967 6 0 1 77969 4 3 70513 2 0 1 77977 4 5 42830 10 0 1 77983 4 3 54514 6 0 1 77999 4 11 59423 7 0 1 78007 4 3 77217 5 0 1 78017 4 3 54087 1 0 1 78031 4 7 61180 0 0 1 78041 4 3 69721 4 0 1 78049 4 7 46692 0 0 1 78059 4 2 44202 3 0 1 78079 4 12 40845 5 0 1 78101 4 2 72401 6 0 1 78121 4 11 66847 16 0 1 78137 4 3 73578 2 0 1 78139 4 3 77255 7 0 1 78157 4 6 47619 8 0 1 78163 4 3 76509 2 0 1 78167 4 5 44736 6 0 1 78173 4 2 57237 0 0 1 78179 4 2 54881 2 0 1 78191 4 11 59080 6 0 1 78193 4 5 46298 6 0 1 78203 4 2 77518 2 0 1 78229 4 2 46801 15 0 1 78233 4 3 72963 2 0 1 78241 4 19 75215 40 0 1 78259 4 2 57170 1 0 1 78277 4 6 78267 7 0 1 78283 4 3 47118 5 0 1 78301 4 6 49151 10 0 1 78307 4 2 64618 11 0 1 78311 4 14 46637 2 0 1 78317 4 2 45633 7 0 1 78341 4 2 57293 8 0 1 78347 4 2 65609 2 0 1 78367 4 5 78355 11 0 1 78401 4 13 77775 0 0 1 78427 4 3 49267 7 0 1 78437 4 2 46740 7 0 1 78439 4 6 39762 10 0 1 78467 4 2 65667 3 0 1 78479 4 7 68429 2 0 1 78487 4 3 74525 5 0 1 78497 4 3 53802 13 0 1 78509 4 3 78505 4 0 1 78511 4 3 41910 3 0 1 78517 4 2 78510 8 0 1 78539 4 2 78532 8 0 1 78541 4 2 64106 10 0 1 78553 4 5 78542 14 0 1 78569 4 3 52115 4 0 1 78571 4 2 74274 1 0 1 78577 4 5 67410 11 0 1 78583 4 3 40331 5 0 1 78593 4 3 64531 12 0 1 78607 4 3 68027 6 0 1 78623 4 5 72708 7 0 1 78643 4 11 65412 2 0 1 78649 4 11 61309 12 0 1 78653 4 3 45000 11 0 1 78691 4 7 63442 6 0 1 78697 4 5 71814 6 0 1 78707 4 2 40959 7 0 1 78713 4 3 50674 8 0 1 78721 4 7 45214 0 0 1 78737 4 3 60761 9 0 1 78779 4 2 60950 7 0 1 78781 4 10 44740 2 0 1 78787 4 2 75674 8 0 1 78791 4 11 40272 3 0 1 78797 4 2 67871 4 0 1 78803 4 2 70667 7 0 1 78809 4 3 64605 0 0 1 78823 4 3 56477 2 0 1 78839 4 13 43368 7 0 1 78853 4 5 50889 6 0 1 78857 4 3 76077 3 0 1 78877 4 2 76365 6 0 1 78887 4 5 57880 10 0 1 78889 4 11 60182 10 0 1 78893 4 2 59423 6 0 1 78901 4 10 60797 5 0 1 78919 4 3 74576 3 0 1 78929 4 3 74478 1 0 1 78941 4 2 72076 0 0 1 78977 4 3 74142 4 0 1 78979 4 3 60274 6 0 1 78989 4 2 65252 0 0 1 79031 4 7 52820 5 0 1 79039 4 6 46887 2 0 1 79043 4 2 75219 4 0 1 79063 4 5 79059 3 0 1 79087 4 3 47249 16 0 1 79103 4 5 53185 5 0 1 79111 4 6 58142 2 0 1 79133 4 2 41941 1 0 1 79139 4 2 75121 8 0 1 79147 4 2 79140 8 0 1 79151 4 13 67901 2 0 1 79153 4 10 67468 25 0 1 79159 4 3 79155 4 0 1 79181 4 2 69094 6 0 1 79187 4 5 57992 1 0 1 79193 4 3 72932 15 0 1 79201 4 13 57322 16 0 1 79229 4 2 57924 3 0 1 79231 4 3 79227 4 0 1 79241 4 3 77951 2 0 1 79259 4 2 44765 13 0 1 79273 4 5 79262 14 0 1 79279 4 3 52356 6 0 1 79283 4 2 60361 4 0 1 79301 4 2 54740 3 0 1 79309 4 2 46121 10 0 1 79319 4 7 44979 2 0 1 79333 4 5 61604 6 0 1 79337 4 3 60327 0 0 1 79349 4 2 60161 6 0 1 79357 4 7 65224 7 0 1 79367 4 5 79355 11 0 1 79379 4 2 78891 2 0 1 79393 4 5 76492 16 0 1 79397 4 2 72098 3 0 1 79399 4 3 67608 6 0 1 79411 4 2 79404 8 0 1 79423 4 3 49546 6 0 1 79427 4 2 76844 4 0 1 79433 4 3 58499 46 0 1 79451 4 6 44750 6 0 1 79481 4 6 46790 0 0 1 79493 4 5 56334 3 0 1 79531 4 2 44457 8 0 1 79537 4 7 76539 20 0 1 79549 4 2 74949 7 0 1 79559 4 7 68022 7 0 1 79561 4 7 77151 0 0 1 79579 4 10 60920 5 0 1 79589 4 2 52849 1 0 1 79601 4 3 40116 2 0 1 79609 4 14 72499 8 0 1 79613 4 2 63052 12 0 1 79621 4 2 78990 9 0 1 79627 4 3 78996 3 0 1 79631 4 13 79619 5 0 1 79633 4 13 44968 6 0 1 79657 4 5 44055 23 0 1 79669 4 10 44344 3 0 1 79687 4 3 48111 6 0 1 79691 4 10 49652 1 0 1 79693 4 5 42715 7 0 1 79697 4 3 47978 4 0 1 79699 4 2 58007 8 0 1 79757 4 2 51791 3 0 1 79769 4 3 79757 0 0 1 79777 4 5 75249 6 0 1 79801 4 23 45329 24 0 1 79811 4 2 77043 8 0 1 79813 4 2 41146 9 0 1 79817 4 3 77684 1 0 1 79823 4 5 58590 8 0 1 79829 4 2 48036 2 0 1 79841 4 3 59475 8 0 1 79843 4 2 41769 8 0 1 79847 4 5 73592 6 0 1 79861 4 2 40440 7 0 1 79867 4 2 48936 8 0 1 79873 4 7 59499 12 0 1 79889 4 3 59347 7 0 1 79901 4 2 50778 3 0 1 79903 4 3 46371 3 0 1 79907 4 2 70669 8 0 1 79939 4 3 42155 6 0 1 79943 4 5 46832 2 0 1 79967 4 5 41208 2 0 1 79973 4 2 65729 6 0 1 79979 4 2 67881 3 0 1 79987 4 2 54593 7 0 1 79997 4 2 55896 6 0 1 79999 4 3 64502 2 0 1 80021 4 2 63575 12 0 1 80039 4 11 51580 3 0 1 80051 4 2 72344 2 0 1 80071 4 3 50443 2 0 1 80077 4 2 49161 6 0 1 80107 4 2 40428 10 0 1 80111 4 11 45203 2 0 1 80141 4 2 79392 3 0 1 80147 4 2 40809 8 0 1 80149 4 6 70486 2 0 1 80153 4 3 53569 6 0 1 80167 4 3 65523 2 0 1 80173 4 6 43355 4 0 1 80177 4 3 71491 2 0 1 80191 4 11 51587 2 0 1 80207 4 5 59881 2 0 1 80209 4 14 48958 12 0 1 80221 4 2 56865 12 0 1 80231 4 7 61268 2 0 1 80233 4 7 72373 13 0 1 80239 4 3 56406 3 0 1 80251 4 2 78779 2 0 1 80263 4 3 48238 2 0 1 80273 4 3 66155 0 0 1 80279 4 11 50740 5 0 1 80287 4 3 60988 3 0 1 80309 4 2 43863 4 0 1 80317 4 2 63865 3 0 1 80329 4 11 51392 12 0 1 80341 4 2 59368 13 0 1 80347 4 2 52202 10 0 1 80363 4 2 80356 8 0 1 80369 4 3 80357 0 0 1 80387 4 2 57221 11 0 1 80407 4 3 68664 5 0 1 80429 4 2 41322 3 0 1 80447 4 5 52770 6 0 1 80449 4 7 67212 16 0 1 80471 4 17 71746 4 0 1 80473 4 5 74835 12 0 1 80489 4 3 71800 2 0 1 80491 4 2 76331 6 0 1 80513 4 3 65304 13 0 1 80527 4 3 63782 2 0 1 80537 4 3 67798 7 0 1 80557 4 2 52088 6 0 1 80567 4 5 79065 10 0 1 80599 4 3 45384 2 0 1 80603 4 2 42304 2 0 1 80611 4 2 75776 6 0 1 80621 4 2 65341 6 0 1 80627 4 2 44131 7 0 1 80629 4 2 48667 3 0 1 80651 4 2 58369 8 0 1 80657 4 3 77638 1 0 1 80669 4 2 79013 17 0 1 80671 4 3 72929 2 0 1 80677 4 2 69647 6 0 1 80681 4 3 62240 7 0 1 80683 4 3 59236 3 0 1 80687 4 5 66673 3 0 1 80701 4 2 67080 7 0 1 80713 4 5 68049 18 0 1 80737 4 7 63594 18 0 1 80747 4 2 60140 7 0 1 80749 4 2 71585 12 0 1 80761 4 11 56384 28 0 1 80777 4 3 57078 1 0 1 80779 4 2 41715 2 0 1 80783 4 5 75803 2 0 1 80789 4 2 59014 6 0 1 80803 4 2 78391 13 0 1 80809 4 19 71007 42 0 1 80819 4 2 73319 7 0 1 80831 4 7 63312 3 0 1 80833 4 5 76540 20 0 1 80849 4 3 80837 0 0 1 80863 4 3 59199 5 0 1 80897 4 3 44553 1 0 1 80909 4 2 72495 4 0 1 80911 4 3 65970 6 0 1 80917 4 6 47894 8 0 1 80923 4 2 75107 7 0 1 80929 4 19 56800 0 0 1 80933 4 2 52283 3 0 1 80953 4 7 73436 8 0 1 80963 4 5 74575 5 0 1 80989 4 2 56470 3 0 1 81001 4 11 70314 14 0 1 81013 4 6 62924 19 0 1 81017 4 3 69703 17 0 1 81019 4 2 73095 2 0 1 81023 4 5 75713 8 0 1 81031 4 6 66505 10 0 1 81041 4 6 75738 5 0 1 81043 4 5 79030 2 0 1 81047 4 5 63890 16 0 1 81049 4 7 81030 22 0 1 81071 4 7 44123 6 0 1 81077 4 2 77672 3 0 1 81083 4 2 59721 14 0 1 81097 4 5 42547 10 0 1 81101 4 2 56209 1 0 1 81119 4 11 69730 3 0 1 81131 4 2 44016 7 0 1 81157 4 6 76125 9 0 1 81163 4 2 46963 2 0 1 81173 4 2 75089 5 0 1 81181 4 6 64088 11 0 1 81197 4 2 62182 6 0 1 81199 4 6 58312 3 0 1 81203 4 2 81196 8 0 1 81223 4 5 81211 11 0 1 81233 4 3 72077 11 0 1 81239 4 7 51287 2 0 1 81281 4 3 62754 7 0 1 81283 4 2 61273 7 0 1 81293 4 2 72331 9 0 1 81299 4 2 69876 3 0 1 81307 4 2 75198 8 0 1 81331 4 12 64308 6 0 1 81343 4 6 80036 3 0 1 81349 4 2 48042 12 0 1 81353 4 3 66025 1 0 1 81359 4 11 42040 2 0 1 81371 4 2 47683 2 0 1 81373 4 2 49604 7 0 1 81401 4 3 80763 2 0 1 81409 4 7 78971 6 0 1 81421 4 11 68224 31 0 1 81439 4 3 57820 2 0 1 81457 4 5 81446 14 0 1 81463 4 5 44020 2 0 1 81509 4 2 41409 0 0 1 81517 4 2 71606 12 0 1 81527 4 5 81523 3 0 1 81533 4 3 66135 5 0 1 81547 4 3 66662 3 0 1 81551 4 7 79472 5 0 1 81553 4 5 81542 14 0 1 81559 4 6 63371 4 0 1 81563 4 2 56504 11 0 1 81569 4 3 59997 2 0 1 81611 4 2 81604 8 0 1 81619 4 3 51777 6 0 1 81629 4 2 55990 6 0 1 81637 4 2 55131 3 0 1 81647 4 5 50077 8 0 1 81649 4 11 75177 0 0 1 81667 4 3 56420 5 0 1 81671 4 7 41578 2 0 1 81677 4 3 75110 4 0 1 81689 4 3 67242 3 0 1 81701 4 2 73754 12 0 1 81703 4 3 76131 5 0 1 81707 4 2 74069 1 0 1 81727 4 3 70729 5 0 1 81737 4 3 43365 7 0 1 81749 4 2 52507 1 0 1 81761 4 12 63911 0 0 1 81769 4 11 48137 0 0 1 81773 4 2 44810 0 0 1 81799 4 3 59239 1 0 1 81817 4 5 54243 6 0 1 81839 4 7 78131 15 0 1 81847 4 3 55689 5 0 1 81853 4 11 74376 1 0 1 81869 4 2 74007 8 0 1 81883 4 3 72549 5 0 1 81899 4 2 72373 1 0 1 81901 4 2 69257 6 0 1 81919 4 3 76496 3 0 1 81929 4 3 51057 8 0 1 81931 4 3 79907 3 0 1 81937 4 5 62686 15 0 1 81943 4 5 59549 5 0 1 81953 4 3 58809 9 0 1 81967 4 5 77324 10 0 1 81971 4 2 51046 8 0 1 81973 4 2 56121 6 0 1 82003 4 2 65809 7 0 1 82007 4 5 62385 2 0 1 82009 4 13 72624 16 0 1 82013 4 11 62069 3 0 1 82021 4 22 82009 6 0 1 82031 4 11 54552 3 0 1 82037 4 2 70086 6 0 1 82039 4 15 63270 2 0 1 82051 4 2 62947 8 0 1 82067 4 2 65454 0 0 1 82073 4 3 63700 0 0 1 82129 4 13 63046 24 0 1 82139 4 6 44113 4 0 1 82141 4 6 55716 2 0 1 82153 4 5 46076 15 0 1 82163 4 2 75805 8 0 1 82171 4 2 44300 2 0 1 82183 4 21 74480 2 0 1 82189 4 10 76121 2 0 1 82193 4 5 50705 8 0 1 82207 4 3 82203 4 0 1 82217 4 3 80903 2 0 1 82219 4 2 69126 3 0 1 82223 4 5 71062 5 0 1 82231 4 7 44407 5 0 1 82237 4 5 74473 10 0 1 82241 4 3 82229 0 0 1 82261 4 6 55032 10 0 1 82267 4 2 67823 1 0 1 82279 4 6 82275 6 0 1 82301 4 2 49980 0 0 1 82307 4 2 52422 8 0 1 82339 4 2 49544 2 0 1 82349 4 3 51170 14 0 1 82351 4 3 82347 4 0 1 82361 4 3 56310 8 0 1 82373 4 2 67086 5 0 1 82387 4 2 54542 8 0 1 82393 4 5 55968 15 0 1 82421 4 2 46757 1 0 1 82457 4 3 77652 0 0 1 82463 4 5 78808 2 0 1 82469 4 2 49032 2 0 1 82471 4 3 48843 6 0 1 82483 4 2 80432 8 0 1 82487 4 5 78103 8 0 1 82493 4 2 77844 6 0 1 82499 4 6 53676 2 0 1 82507 4 2 76333 7 0 1 82529 4 3 71002 2 0 1 82531 4 3 75326 3 0 1 82549 4 2 46110 9 0 1 82559 4 7 63452 2 0 1 82561 4 7 75309 0 0 1 82567 4 3 68679 6 0 1 82571 4 6 80871 4 0 1 82591 4 6 75332 2 0 1 82601 4 3 82589 0 0 1 82609 4 11 58894 22 0 1 82613 4 2 47546 6 0 1 82619 4 2 69694 2 0 1 82633 4 5 58355 6 0 1 82651 4 2 59623 8 0 1 82657 4 10 48337 15 0 1 82699 4 3 75912 3 0 1 82721 4 6 72837 0 0 1 82723 4 2 61102 8 0 1 82727 4 5 62324 2 0 1 82729 4 7 82710 22 0 1 82757 4 2 72493 6 0 1 82759 4 3 45072 2 0 1 82763 4 2 52949 7 0 1 82781 4 2 64996 1 0 1 82787 4 2 42141 11 0 1 82793 4 3 72993 1 0 1 82799 4 13 46750 4 0 1 82811 4 2 43150 7 0 1 82813 4 2 66458 6 0 1 82837 4 2 77577 7 0 1 82847 4 5 61464 8 0 1 82883 4 2 55847 18 0 1 82889 4 3 82877 0 0 1 82891 4 2 72806 8 0 1 82903 4 3 73894 5 0 1 82913 4 3 68256 7 0 1 82939 4 2 44621 2 0 1 82963 4 3 52130 3 0 1 82981 4 2 49573 3 0 1 82997 4 2 54972 3 0 1 83003 4 2 46629 4 0 1 83009 4 3 82997 0 0 1 83023 4 3 47178 8 0 1 83047 4 3 47635 5 0 1 83059 4 2 53800 8 0 1 83063 4 5 78249 2 0 1 83071 4 14 43185 6 0 1 83077 4 14 57821 7 0 1 83089 4 7 48300 0 0 1 83093 4 2 58833 12 0 1 83101 4 2 78175 6 0 1 83117 4 2 60873 6 0 1 83137 4 5 73266 10 0 1 83177 4 3 61245 4 0 1 83203 4 2 67888 8 0 1 83207 4 5 80501 3 0 1 83219 4 2 71402 2 0 1 83221 4 7 73515 13 0 1 83227 4 5 42363 0 0 1 83231 4 7 49723 13 0 1 83233 4 7 79225 8 0 1 83243 4 2 42837 10 0 1 83257 4 5 59600 6 0 1 83267 4 2 77915 4 0 1 83269 4 2 74469 15 0 1 83273 4 3 70147 2 0 1 83299 4 2 44145 0 0 1 83311 4 12 67642 3 0 1 83339 4 2 77318 7 0 1 83341 4 10 81383 3 0 1 83357 4 2 55141 8 0 1 83383 4 3 83375 10 0 1 83389 4 2 81043 7 0 1 83399 4 7 45528 5 0 1 83401 4 7 60294 16 0 1 83407 4 5 83403 3 0 1 83417 4 3 60180 9 0 1 83423 4 5 63381 2 0 1 83431 4 12 76750 6 0 1 83437 4 2 80169 18 0 1 83443 4 2 44134 2 0 1 83449 4 13 42049 26 0 1 83459 4 2 71233 2 0 1 83471 4 11 69008 2 0 1 83477 4 2 75305 6 0 1 83497 4 10 46830 6 0 1 83537 4 3 55121 3 0 1 83557 4 2 66055 7 0 1 83561 4 3 83549 0 0 1 83563 4 2 58344 8 0 1 83579 4 2 44355 11 0 1 83591 4 7 83582 4 0 1 83597 4 2 71004 1 0 1 83609 4 3 75159 3 0 1 83617 4 5 45680 18 0 1 83621 4 2 69792 3 0 1 83639 4 19 43072 8 0 1 83641 4 7 61860 14 0 1 83653 4 5 80330 8 0 1 83663 4 5 49846 9 0 1 83689 4 13 73739 34 0 1 83701 4 6 53413 2 0 1 83717 4 2 73333 9 0 1 83719 4 6 65689 2 0 1 83737 4 5 43562 15 0 1 83761 4 11 65650 10 0 1 83773 4 5 51690 3 0 1 83777 4 3 61569 0 0 1 83791 4 3 73069 6 0 1 83813 4 2 63896 9 0 1 83833 4 5 46024 18 0 1 83843 4 2 48028 0 0 1 83857 4 5 62309 6 0 1 83869 4 6 63809 7 0 1 83873 4 3 70093 9 0 1 83891 4 2 47157 4 0 1 83903 4 5 83899 3 0 1 83911 4 3 67617 6 0 1 83921 4 3 42888 7 0 1 83933 4 2 65209 6 0 1 83939 4 2 43773 7 0 1 83969 4 3 53813 7 0 1 83983 4 5 65906 5 0 1 83987 4 2 75739 3 0 1 84011 4 6 68532 4 0 1 84017 4 3 68671 0 0 1 84047 4 5 51858 4 0 1 84053 4 2 44102 6 0 1 84059 4 2 66685 2 0 1 84061 4 7 52237 4 0 1 84067 4 2 58797 8 0 1 84089 4 3 57127 2 0 1 84121 4 13 81912 14 0 1 84127 4 3 62032 5 0 1 84131 4 2 78301 7 0 1 84137 4 3 48372 3 0 1 84143 4 5 84139 3 0 1 84163 4 2 70983 8 0 1 84179 4 2 73594 7 0 1 84181 4 2 84174 8 0 1 84191 4 7 84182 4 0 1 84199 4 11 46401 5 0 1 84211 4 3 54952 6 0 1 84221 4 2 82432 4 0 1 84223 4 6 53831 2 0 1 84229 4 2 42439 3 0 1 84239 4 11 68558 5 0 1 84247 4 5 60526 10 0 1 84263 4 5 71886 6 0 1 84299 4 2 63350 2 0 1 84307 4 3 58693 11 0 1 84313 4 5 53362 6 0 1 84317 4 2 42483 16 0 1 84319 4 6 54492 10 0 1 84347 4 2 83844 8 0 1 84349 4 2 66228 6 0 1 84377 4 3 67026 0 0 1 84389 4 2 44813 12 0 1 84391 4 3 65740 10 0 1 84401 4 3 72744 2 0 1 84407 4 5 79795 9 0 1 84421 4 2 78870 12 0 1 84431 4 7 53302 3 0 1 84437 4 2 59837 4 0 1 84443 4 2 75808 4 0 1 84449 4 3 78305 4 0 1 84457 4 5 78551 6 0 1 84463 4 5 60009 5 0 1 84467 4 2 74475 11 0 1 84481 4 7 60446 0 0 1 84499 4 2 51269 8 0 1 84503 4 15 43248 5 0 1 84509 4 2 55675 3 0 1 84521 4 3 61147 13 0 1 84523 4 2 57944 2 0 1 84533 4 2 61937 17 0 1 84551 4 19 68949 2 0 1 84559 4 3 55918 3 0 1 84589 4 2 60868 16 0 1 84629 4 2 74132 2 0 1 84631 4 6 61193 2 0 1 84649 4 13 62937 14 0 1 84653 4 2 78406 7 0 1 84659 4 2 57484 0 0 1 84673 4 10 61794 8 0 1 84691 4 2 56204 2 0 1 84697 4 11 75971 12 0 1 84701 4 2 49463 6 0 1 84713 4 3 74698 4 0 1 84719 4 13 45992 6 0 1 84731 4 2 46079 6 0 1 84737 4 3 56766 1 0 1 84751 4 6 43010 2 0 1 84761 4 7 64891 7 0 1 84787 4 2 47901 2 0 1 84793 4 5 75166 21 0 1 84809 4 3 71505 4 0 1 84811 4 3 47337 7 0 1 84827 4 2 63494 3 0 1 84857 4 3 84033 1 0 1 84859 4 2 59239 6 0 1 84869 4 3 59778 2 0 1 84871 4 3 66439 2 0 1 84913 4 5 73940 6 0 1 84919 4 3 70169 3 0 1 84947 4 2 77330 18 0 1 84961 4 11 81274 16 0 1 84967 4 3 68727 6 0 1 84977 4 3 65886 9 0 1 84979 4 2 48347 6 0 1 84991 4 3 66190 6 0 1 85009 4 13 46408 28 0 1 85021 4 7 75704 4 0 1 85027 4 2 57937 10 0 1 85037 4 2 47435 2 0 1 85049 4 3 51697 4 0 1 85061 4 2 68635 6 0 1 85081 4 7 73852 24 0 1 85087 4 3 69501 2 0 1 85091 4 6 52263 4 0 1 85093 4 2 57947 12 0 1 85103 4 5 69098 6 0 1 85109 4 2 71033 1 0 1 85121 4 6 71135 7 0 1 85133 4 2 71810 1 0 1 85147 4 2 69923 7 0 1 85159 4 3 51289 2 0 1 85193 4 3 60997 1 0 1 85199 4 7 85190 4 0 1 85201 4 22 63597 25 0 1 85213 4 6 71391 7 0 1 85223 4 5 65949 2 0 1 85229 4 3 84816 4 0 1 85237 4 2 47471 6 0 1 85243 4 3 68405 3 0 1 85247 4 5 85243 3 0 1 85259 4 2 63812 6 0 1 85297 4 15 57173 6 0 1 85303 4 5 71357 5 0 1 85313 4 3 77832 4 0 1 85331 4 2 46636 8 0 1 85333 4 5 72738 1 0 1 85361 4 3 44557 4 0 1 85363 4 3 61217 3 0 1 85369 4 17 64954 16 0 1 85381 4 6 67497 11 0 1 85411 4 2 48210 8 0 1 85427 4 2 79618 6 0 1 85429 4 6 50139 7 0 1 85439 4 7 85430 4 0 1 85447 4 3 46532 5 0 1 85451 4 2 67788 8 0 1 85453 4 2 72121 6 0 1 85469 4 3 85465 4 0 1 85487 4 5 61207 5 0 1 85513 4 5 75894 6 0 1 85517 4 2 55533 6 0 1 85523 4 2 50514 8 0 1 85531 4 14 77821 2 0 1 85549 4 2 55721 6 0 1 85571 4 2 85564 8 0 1 85577 4 3 70921 7 0 1 85597 4 2 43941 10 0 1 85601 4 3 57286 0 0 1 85607 4 5 43057 4 0 1 85619 4 6 84127 1 0 1 85621 4 10 64858 17 0 1 85627 4 2 85620 8 0 1 85639 4 3 85635 4 0 1 85643 4 2 66957 0 0 1 85661 4 2 68797 7 0 1 85667 4 5 70694 11 0 1 85669 4 2 54576 6 0 1 85691 4 2 53620 8 0 1 85703 4 5 72072 4 0 1 85711 4 6 84740 3 0 1 85717 4 2 73875 10 0 1 85733 4 2 51237 7 0 1 85751 4 14 57604 7 0 1 85781 4 2 61366 4 0 1 85793 4 3 78800 2 0 1 85817 4 3 63942 4 0 1 85819 4 2 43548 7 0 1 85829 4 2 62106 7 0 1 85831 4 3 57416 3 0 1 85837 4 2 85830 8 0 1 85843 4 3 61435 5 0 1 85847 4 5 85843 3 0 1 85853 4 2 76113 6 0 1 85889 4 3 49293 2 0 1 85903 4 3 44603 6 0 1 85909 4 2 73309 0 0 1 85931 4 2 64320 2 0 1 85933 4 5 54460 3 0 1 85991 4 11 69614 7 0 1 85999 4 3 71115 6 0 1 86011 4 7 79304 6 0 1 86017 4 5 86006 14 0 1 86027 4 2 77272 8 0 1 86029 4 2 56318 10 0 1 86069 4 2 83006 0 0 1 86077 4 5 82618 1 0 1 86083 4 2 45544 8 0 1 86111 4 11 60598 5 0 1 86113 4 5 75500 12 0 1 86117 4 2 65408 4 0 1 86131 4 2 68761 2 0 1 86137 4 5 67832 6 0 1 86143 4 3 78747 2 0 1 86161 4 14 48931 22 0 1 86171 4 7 48630 2 0 1 86179 4 2 58736 8 0 1 86183 4 5 62841 3 0 1 86197 4 2 66956 7 0 1 86201 4 3 47936 2 0 1 86209 4 11 61514 14 0 1 86239 4 3 81264 6 0 1 86243 4 2 66854 13 0 1 86249 4 3 86237 0 0 1 86257 4 5 45060 10 0 1 86263 4 3 68526 3 0 1 86269 4 6 85210 2 0 1 86287 4 11 67760 2 0 1 86291 4 2 45154 8 0 1 86293 4 2 76062 10 0 1 86297 4 3 71712 1 0 1 86311 4 3 64381 3 0 1 86323 4 2 77742 7 0 1 86341 4 2 64182 3 0 1 86351 4 13 72249 2 0 1 86353 4 10 52875 24 0 1 86357 4 2 45402 3 0 1 86369 4 3 86357 0 0 1 86371 4 3 46150 2 0 1 86381 4 3 66569 12 0 1 86389 4 2 74249 7 0 1 86399 4 11 83534 10 0 1 86413 4 2 55786 3 0 1 86423 4 5 86006 6 0 1 86441 4 3 86429 0 0 1 86453 4 2 68996 1 0 1 86461 4 2 52347 12 0 1 86467 4 2 68868 2 0 1 86477 4 2 81636 3 0 1 86491 4 2 65433 2 0 1 86501 4 2 81054 7 0 1 86509 4 6 81483 10 0 1 86531 4 2 85699 7 0 1 86533 4 2 66465 7 0 1 86539 4 3 49584 7 0 1 86561 4 3 72627 4 0 1 86573 4 2 54557 12 0 1 86579 4 2 73124 2 0 1 86587 4 3 67004 7 0 1 86599 4 3 44640 2 0 1 86627 4 2 57171 16 0 1 86629 4 2 85044 6 0 1 86677 4 2 64843 9 0 1 86689 4 13 84972 14 0 1 86693 4 2 55253 3 0 1 86711 4 7 55000 3 0 1 86719 4 6 57420 3 0 1 86729 4 3 71675 2 0 1 86743 4 3 49384 2 0 1 86753 4 3 75157 7 0 1 86767 4 3 48986 5 0 1 86771 4 6 71195 5 0 1 86783 4 5 56575 2 0 1 86813 4 2 68698 0 0 1 86837 4 2 82049 7 0 1 86843 4 2 52412 8 0 1 86851 4 2 54827 8 0 1 86857 4 10 74284 22 0 1 86861 4 2 84997 9 0 1 86869 4 2 53726 11 0 1 86923 4 2 54590 8 0 1 86927 4 5 59244 4 0 1 86929 4 14 70834 12 0 1 86939 4 2 53450 4 0 1 86951 4 7 83694 2 0 1 86959 4 3 55630 3 0 1 86969 4 3 73143 3 0 1 86981 4 2 69207 3 0 1 86993 4 3 51121 9 0 1 87011 4 2 48638 7 0 1 87013 4 5 82915 6 0 1 87037 4 2 84714 6 0 1 87041 4 3 77323 2 0 1 87049 4 19 82393 8 0 1 87071 4 17 84135 2 0 1 87083 4 2 59950 2 0 1 87103 4 3 74077 6 0 1 87107 4 2 82394 13 0 1 87119 4 7 58638 0 0 1 87121 4 7 82060 0 0 1 87133 4 6 79783 4 0 1 87149 4 2 49705 1 0 1 87151 4 3 79521 6 0 1 87179 4 2 56367 3 0 1 87181 4 2 73538 3 0 1 87187 4 3 46572 2 0 1 87211 4 13 43996 0 0 1 87221 4 10 70413 8 0 1 87223 4 3 84598 3 0 1 87251 4 2 81055 7 0 1 87253 4 2 78421 7 0 1 87257 4 3 69139 1 0 1 87277 4 5 70778 3 0 1 87281 4 3 85436 7 0 1 87293 4 2 71729 4 0 1 87299 4 2 65226 3 0 1 87313 4 5 64889 12 0 1 87317 4 2 77751 1 0 1 87323 4 2 60246 4 0 1 87337 4 5 57913 6 0 1 87359 4 19 71352 7 0 1 87383 4 5 75760 4 0 1 87403 4 2 79194 8 0 1 87407 4 5 55107 5 0 1 87421 4 6 81011 11 0 1 87427 4 2 61148 8 0 1 87433 4 5 52544 6 0 1 87443 4 2 62593 3 0 1 87473 4 5 44636 10 0 1 87481 4 29 48219 36 0 1 87491 4 2 65234 2 0 1 87509 4 2 80161 2 0 1 87511 4 3 62448 2 0 1 87517 4 2 80313 6 0 1 87523 4 2 75300 8 0 1 87539 4 2 47703 16 0 1 87541 4 18 63377 7 0 1 87547 4 2 61089 10 0 1 87553 4 5 81453 10 0 1 87557 4 3 64239 15 0 1 87559 4 3 62832 6 0 1 87583 4 3 73976 6 0 1 87587 4 2 84795 4 0 1 87589 4 2 45093 3 0 1 87613 4 2 81843 9 0 1 87623 4 5 69085 3 0 1 87629 4 2 69345 4 0 1 87631 4 6 81868 3 0 1 87641 4 3 86979 2 0 1 87643 4 3 52502 2 0 1 87649 4 17 73497 18 0 1 87671 4 11 84308 9 0 1 87679 4 3 80235 3 0 1 87683 4 2 76787 3 0 1 87691 4 7 87178 6 0 1 87697 4 17 52724 11 0 1 87701 4 2 85003 4 0 1 87719 4 7 86693 4 0 1 87721 4 11 72924 20 0 1 87739 4 7 58923 11 0 1 87743 4 5 47423 8 0 1 87751 4 3 87747 4 0 1 87767 4 5 87763 3 0 1 87793 4 5 81599 6 0 1 87797 4 2 61351 3 0 1 87803 4 5 83146 1 0 1 87811 4 2 86300 6 0 1 87833 4 3 55388 26 0 1 87853 4 2 72141 3 0 1 87869 4 2 47212 4 0 1 87877 4 2 67457 6 0 1 87881 4 3 63538 7 0 1 87887 4 5 47133 7 0 1 87911 4 29 80044 4 0 1 87917 4 2 87254 6 0 1 87931 4 10 83876 0 0 1 87943 4 3 81473 6 0 1 87959 4 7 87950 4 0 1 87961 4 14 64659 0 0 1 87973 4 2 68687 10 0 1 87977 4 3 74554 4 0 1 87991 4 6 50810 10 0 1 88001 4 6 73068 0 0 1 88003 4 2 45385 2 0 1 88007 4 5 55334 2 0 1 88019 4 2 53516 3 0 1 88037 4 2 69629 2 0 1 88069 4 2 55880 12 0 1 88079 4 31 49692 6 0 1 88093 4 2 65214 6 0 1 88117 4 5 65820 6 0 1 88129 4 11 76899 8 0 1 88169 4 3 82590 0 0 1 88177 4 5 47824 15 0 1 88211 4 2 44598 7 0 1 88223 4 5 66757 2 0 1 88237 4 2 72822 6 0 1 88241 4 3 61281 2 0 1 88259 4 2 77291 2 0 1 88261 4 2 82703 3 0 1 88289 4 3 55821 1 0 1 88301 4 2 76602 2 0 1 88321 4 34 74290 13 0 1 88327 4 5 60040 5 0 1 88337 4 3 87076 6 0 1 88339 4 3 55904 5 0 1 88379 4 2 78778 16 0 1 88397 4 2 75084 6 0 1 88411 4 2 69314 3 0 1 88423 4 6 79157 2 0 1 88427 4 2 82450 4 0 1 88463 4 5 88459 3 0 1 88469 4 2 55759 3 0 1 88471 4 11 46755 3 0 1 88493 4 2 57070 6 0 1 88499 4 2 77171 3 0 1 88513 4 10 73337 15 0 1 88523 4 2 69774 0 0 1 88547 4 2 77053 15 0 1 88589 4 2 61714 19 0 1 88591 4 15 65659 10 0 1 88607 4 5 88595 11 0 1 88609 4 17 64549 20 0 1 88643 4 2 60879 0 0 1 88651 4 3 54690 2 0 1 88657 4 5 61668 12 0 1 88661 4 2 77749 4 0 1 88663 4 3 88655 10 0 1 88667 4 2 69703 11 0 1 88681 4 7 79580 0 0 1 88721 4 3 85597 7 0 1 88729 4 17 76589 22 0 1 88741 4 2 69371 10 0 1 88747 4 7 60687 11 0 1 88771 4 11 68103 5 0 1 88789 4 2 52808 10 0 1 88793 4 3 45894 2 0 1 88799 4 7 88790 4 0 1 88801 4 7 60014 26 0 1 88807 4 5 88803 3 0 1 88811 4 2 86213 8 0 1 88813 4 5 45904 1 0 1 88817 4 3 70968 1 0 1 88819 4 2 56474 1 0 1 88843 4 2 88836 8 0 1 88853 4 2 58554 2 0 1 88861 4 2 85821 9 0 1 88867 4 2 85769 8 0 1 88873 4 15 58644 8 0 1 88883 4 2 48911 7 0 1 88897 4 11 88877 12 0 1 88903 4 3 53184 3 0 1 88919 4 23 66274 6 0 1 88937 4 3 79818 7 0 1 88951 4 3 88947 4 0 1 88969 4 7 52073 0 0 1 88993 4 5 72906 20 0 1 88997 4 2 83220 11 0 1 89003 4 2 63678 2 0 1 89009 4 3 88587 7 0 1 89017 4 5 48720 6 0 1 89021 4 2 85906 12 0 1 89041 4 29 49844 25 0 1 89051 4 2 52231 7 0 1 89057 4 3 62232 0 0 1 89069 4 2 65186 16 0 1 89071 4 6 80263 2 0 1 89083 4 2 84206 8 0 1 89087 4 5 60314 3 0 1 89101 4 2 50989 7 0 1 89107 4 2 88590 8 0 1 89113 4 7 57056 10 0 1 89119 4 6 79322 3 0 1 89123 4 5 60119 2 0 1 89137 4 5 73978 6 0 1 89153 4 3 76538 1 0 1 89189 4 2 82558 6 0 1 89203 4 2 83761 8 0 1 89209 4 22 78469 0 0 1 89213 4 2 83322 1 0 1 89227 4 3 82947 7 0 1 89231 4 14 54243 2 0 1 89237 4 2 78562 7 0 1 89261 4 2 47531 2 0 1 89269 4 2 89262 8 0 1 89273 4 3 82440 11 0 1 89293 4 5 73019 3 0 1 89303 4 5 70612 2 0 1 89317 4 2 47251 10 0 1 89329 4 13 80083 14 0 1 89363 4 5 71387 0 0 1 89371 4 2 75314 8 0 1 89381 4 2 48063 1 0 1 89387 4 2 76759 7 0 1 89393 4 3 70160 6 0 1 89399 4 7 53441 2 0 1 89413 4 2 78153 7 0 1 89417 4 3 66268 1 0 1 89431 4 11 63805 2 0 1 89443 4 2 65879 10 0 1 89449 4 11 72948 10 0 1 89459 4 2 48498 7 0 1 89477 4 2 67764 9 0 1 89491 4 2 89484 8 0 1 89501 4 2 88832 9 0 1 89513 4 3 49461 22 0 1 89519 4 11 66672 5 0 1 89521 4 14 77349 10 0 1 89527 4 3 56588 3 0 1 89533 4 2 50430 6 0 1 89561 4 3 58735 7 0 1 89563 4 2 67302 7 0 1 89567 4 5 56806 4 0 1 89591 4 13 79892 2 0 1 89597 4 2 76712 6 0 1 89599 4 3 68467 3 0 1 89603 4 2 78467 11 0 1 89611 4 2 51932 8 0 1 89627 4 2 74306 13 0 1 89633 4 3 87516 2 0 1 89653 4 17 47869 3 0 1 89657 4 3 46656 4 0 1 89659 4 10 66021 5 0 1 89669 4 2 77196 3 0 1 89671 4 6 83849 3 0 1 89681 4 3 88834 8 0 1 89689 4 7 73283 0 0 1 89753 4 3 72351 1 0 1 89759 4 13 50779 3 0 1 89767 4 3 61326 5 0 1 89779 4 2 78492 8 0 1 89783 4 5 68963 5 0 1 89797 4 5 87272 3 0 1 89809 4 7 50080 17 0 1 89819 4 2 62438 8 0 1 89821 4 2 53125 6 0 1 89833 4 5 61199 18 0 1 89839 4 7 48463 0 0 1 89849 4 3 74019 2 0 1 89867 4 2 86502 6 0 1 89891 4 7 89882 4 0 1 89897 4 3 54108 0 0 1 89899 4 2 83993 1 0 1 89909 4 2 52838 7 0 1 89917 4 2 71569 22 0 1 89923 4 3 77197 24 0 1 89939 4 2 79281 2 0 1 89959 4 3 58162 3 0 1 89963 4 2 66614 4 0 1 89977 4 5 72067 6 0 1 89983 4 3 50744 3 0 1 89989 4 2 77048 10 0 1 90001 4 13 58023 23 0 1 90007 4 6 70111 5 0 1 90011 4 2 51361 11 0 1 90017 4 3 65711 0 0 1 90019 4 14 59043 2 0 1 90023 4 5 45731 5 0 1 90031 4 3 80184 3 0 1 90053 4 2 86329 3 0 1 90059 4 2 72422 6 0 1 90067 4 2 46751 17 0 1 90071 4 7 49992 2 0 1 90073 4 10 48964 22 0 1 90089 4 3 88445 7 0 1 90107 4 2 46823 15 0 1 90121 4 23 87998 16 0 1 90127 4 3 55920 3 0 1 90149 4 2 86484 1 0 1 90163 4 2 88312 2 0 1 90173 4 2 60563 4 0 1 90187 4 2 53565 2 0 1 90191 4 17 72994 14 0 1 90197 4 2 67144 0 0 1 90199 4 3 90195 4 0 1 90203 4 2 87602 7 0 1 90217 4 22 86753 6 0 1 90227 4 2 82857 1 0 1 90239 4 7 51383 2 0 1 90247 4 5 72406 9 0 1 90263 4 5 52953 7 0 1 90271 4 3 67902 3 0 1 90281 4 3 70020 3 0 1 90289 4 23 69885 8 0 1 90313 4 5 88188 10 0 1 90353 4 3 79362 1 0 1 90359 4 11 76295 10 0 1 90371 4 2 65545 4 0 1 90373 4 5 49256 1 0 1 90379 4 2 79573 8 0 1 90397 4 2 84894 3 0 1 90401 4 6 54060 0 0 1 90403 4 3 51970 3 0 1 90407 4 5 90395 11 0 1 90437 4 2 79758 6 0 1 90439 4 13 60092 2 0 1 90469 4 2 71719 7 0 1 90473 4 3 74211 0 0 1 90481 4 14 45930 8 0 1 90499 4 2 71957 10 0 1 90511 4 3 80865 3 0 1 90523 4 2 85970 7 0 1 90527 4 5 61759 7 0 1 90529 4 7 52506 24 0 1 90533 4 2 87647 9 0 1 90547 4 2 52710 10 0 1 90583 4 5 90579 3 0 1 90599 4 11 57709 3 0 1 90617 4 3 54153 6 0 1 90619 4 3 46200 5 0 1 90631 4 3 75393 3 0 1 90641 4 3 77187 2 0 1 90647 4 5 52402 6 0 1 90659 4 2 76125 11 0 1 90677 4 2 90670 8 0 1 90679 4 3 78993 3 0 1 90697 4 5 85335 6 0 1 90703 4 3 75915 2 0 1 90709 4 6 64890 0 0 1 90731 4 2 67657 8 0 1 90749 4 2 49247 6 0 1 90787 4 3 55921 3 0 1 90793 4 5 61253 10 0 1 90803 4 2 51188 7 0 1 90821 4 3 90817 4 0 1 90823 4 6 90149 8 0 1 90833 4 3 51966 7 0 1 90841 4 17 51367 20 0 1 90847 4 5 84626 2 0 1 90863 4 5 90859 3 0 1 90887 4 5 80344 5 0 1 90901 4 2 65844 7 0 1 90907 4 5 90903 3 0 1 90911 4 7 69833 2 0 1 90917 4 2 65494 7 0 1 90931 4 11 70813 2 0 1 90947 4 2 69616 1 0 1 90971 4 2 65157 4 0 1 90977 4 3 77733 11 0 1 90989 4 2 58819 3 0 1 90997 4 5 84198 20 0 1 91009 4 11 81745 16 0 1 91019 4 2 79315 4 0 1 91033 4 5 91022 14 0 1 91079 4 7 73240 12 0 1 91081 4 17 49467 30 0 1 91097 4 3 57390 0 0 1 91099 4 2 86394 8 0 1 91121 4 6 74214 0 0 1 91127 4 5 50315 3 0 1 91129 4 7 73326 0 0 1 91139 4 2 73038 1 0 1 91141 4 6 74979 7 0 1 91151 4 7 90724 2 0 1 91153 4 7 88955 8 0 1 91159 4 6 81521 2 0 1 91163 4 2 53788 7 0 1 91183 4 3 76981 3 0 1 91193 4 3 69107 2 0 1 91199 4 11 57553 4 0 1 91229 4 2 74540 1 0 1 91237 4 6 54395 6 0 1 91243 4 5 91235 6 0 1 91249 4 17 88547 21 0 1 91253 4 2 78562 12 0 1 91283 4 2 52796 13 0 1 91291 4 2 46882 28 0 1 91297 4 5 75899 6 0 1 91303 4 3 53758 3 0 1 91309 4 10 91297 10 0 1 91331 4 2 81982 3 0 1 91367 4 11 78831 6 0 1 91369 4 7 58816 0 0 1 91373 4 3 63406 20 0 1 91381 4 17 85807 4 0 1 91387 4 2 67182 8 0 1 91393 4 23 79072 47 0 1 91397 4 2 49266 1 0 1 91411 4 2 61380 6 0 1 91423 4 3 82479 2 0 1 91433 4 3 60385 2 0 1 91453 4 6 62412 6 0 1 91457 4 3 85056 0 0 1 91459 4 2 84182 8 0 1 91463 4 5 86817 5 0 1 91493 4 2 53089 9 0 1 91499 4 2 50634 7 0 1 91513 4 10 65693 6 0 1 91529 4 3 91517 0 0 1 91541 4 2 57756 1 0 1 91571 4 2 55807 8 0 1 91573 4 5 91145 3 0 1 91577 4 3 55670 7 0 1 91583 4 5 90626 2 0 1 91591 4 3 91587 4 0 1 91621 4 2 68885 3 0 1 91631 4 7 74108 4 0 1 91639 4 3 68529 3 0 1 91673 4 3 83024 4 0 1 91691 4 2 73690 2 0 1 91703 4 5 91699 3 0 1 91711 4 11 69581 6 0 1 91733 4 2 69673 6 0 1 91753 4 10 85710 8 0 1 91757 4 2 50197 11 0 1 91771 4 2 75038 8 0 1 91781 4 2 61413 12 0 1 91801 4 13 89177 10 0 1 91807 4 3 91803 4 0 1 91811 4 2 74995 7 0 1 91813 4 2 61823 10 0 1 91823 4 5 78435 5 0 1 91837 4 2 48907 6 0 1 91841 4 3 64452 4 0 1 91867 4 2 67015 10 0 1 91873 4 5 79986 6 0 1 91909 4 2 54536 9 0 1 91921 4 13 62926 16 0 1 91939 4 2 53264 3 0 1 91943 4 5 60751 3 0 1 91951 4 3 82295 3 0 1 91957 4 7 70115 4 0 1 91961 4 15 78886 3 0 1 91967 4 5 91963 3 0 1 91969 4 13 69462 16 0 1 91997 4 2 55417 6 0 1 92003 4 2 86036 13 0 1 92009 4 3 54896 2 0 1 92033 4 3 50748 0 0 1 92041 4 7 64681 0 0 1 92051 4 6 74667 2 0 1 92077 4 2 60404 3 0 1 92083 4 2 67601 12 0 1 92107 4 2 52323 8 0 1 92111 4 13 83816 7 0 1 92119 4 3 67374 6 0 1 92143 4 5 65197 5 0 1 92153 4 3 61292 7 0 1 92173 4 2 80029 12 0 1 92177 4 6 73491 8 0 1 92179 4 3 85229 2 0 1 92189 4 2 56701 2 0 1 92203 4 2 69284 11 0 1 92219 4 2 61932 7 0 1 92221 4 6 47606 8 0 1 92227 4 3 88520 3 0 1 92233 4 5 74044 15 0 1 92237 4 2 66244 1 0 1 92243 4 2 83218 4 0 1 92251 4 2 73491 6 0 1 92269 4 10 77657 3 0 1 92297 4 3 57158 6 0 1 92311 4 7 89997 5 0 1 92317 4 6 76088 4 0 1 92333 4 2 75472 3 0 1 92347 4 5 46963 0 0 1 92353 4 5 59252 12 0 1 92357 4 3 52873 14 0 1 92363 4 2 68580 12 0 1 92369 4 3 84567 4 0 1 92377 4 7 46885 10 0 1 92381 4 2 64984 6 0 1 92383 4 3 92379 4 0 1 92387 4 2 54274 8 0 1 92399 4 13 91487 4 0 1 92401 4 34 72727 32 0 1 92413 4 2 51430 3 0 1 92419 4 2 92412 8 0 1 92431 4 6 75729 3 0 1 92459 4 2 54438 7 0 1 92461 4 2 76655 3 0 1 92467 4 2 50389 8 0 1 92479 4 6 62711 3 0 1 92489 4 3 92477 0 0 1 92503 4 5 83399 10 0 1 92507 4 2 88006 8 0 1 92551 4 7 62292 5 0 1 92557 4 2 86841 6 0 1 92567 4 5 72826 4 0 1 92569 4 31 85427 26 0 1 92581 4 6 72794 0 0 1 92593 4 5 92582 14 0 1 92623 4 11 68484 5 0 1 92627 4 2 56687 0 0 1 92639 4 7 70281 7 0 1 92641 4 11 47585 22 0 1 92647 4 3 75648 3 0 1 92657 4 3 91796 0 0 1 92669 4 2 60388 9 0 1 92671 4 3 71451 2 0 1 92681 4 3 53959 7 0 1 92683 4 3 79305 2 0 1 92693 4 2 57116 3 0 1 92699 4 2 51708 2 0 1 92707 4 2 51068 2 0 1 92717 4 2 84707 12 0 1 92723 4 2 63648 3 0 1 92737 4 5 72599 16 0 1 92753 4 3 57683 1 0 1 92761 4 26 56897 29 0 1 92767 4 3 67277 6 0 1 92779 4 2 90004 8 0 1 92789 4 2 66713 6 0 1 92791 4 6 64287 3 0 1 92801 4 3 49917 2 0 1 92809 4 14 70472 8 0 1 92821 4 6 92813 12 0 1 92831 4 7 51923 2 0 1 92849 4 3 79914 8 0 1 92857 4 5 92846 14 0 1 92861 4 2 89454 1 0 1 92863 4 6 63894 5 0 1 92867 4 2 63074 10 0 1 92893 4 5 68537 3 0 1 92899 4 7 86070 0 0 1 92921 4 3 92909 0 0 1 92927 4 5 92915 11 0 1 92941 4 2 62327 10 0 1 92951 4 11 47140 2 0 1 92957 4 2 64421 7 0 1 92959 4 6 60236 5 0 1 92987 4 2 61611 2 0 1 92993 4 3 74567 4 0 1 93001 4 14 81131 8 0 1 93047 4 5 52220 8 0 1 93053 4 2 84425 6 0 1 93059 4 2 60438 7 0 1 93077 4 2 82908 3 0 1 93083 4 2 48340 8 0 1 93089 4 3 67299 0 0 1 93097 4 10 54524 10 0 1 93103 4 5 46816 8 0 1 93113 4 3 82056 11 0 1 93131 4 6 50691 5 0 1 93133 4 6 86194 0 0 1 93139 4 2 81769 8 0 1 93151 4 3 74064 3 0 1 93169 4 11 89770 10 0 1 93179 4 2 79311 8 0 1 93187 4 3 54248 5 0 1 93199 4 7 61765 5 0 1 93229 4 6 83093 7 0 1 93239 4 11 66356 7 0 1 93241 4 13 55403 30 0 1 93251 4 2 90259 8 0 1 93253 4 2 69769 3 0 1 93257 4 3 92449 0 0 1 93263 4 5 78965 1 0 1 93281 4 3 84093 2 0 1 93283 4 2 92225 8 0 1 93287 4 5 93283 3 0 1 93307 4 2 92778 14 0 1 93319 4 3 58537 3 0 1 93323 4 2 69739 7 0 1 93329 4 3 58619 2 0 1 93337 4 5 93326 14 0 1 93371 4 2 89104 11 0 1 93377 4 3 77700 0 0 1 93383 4 5 61397 5 0 1 93407 4 5 62820 4 0 1 93419 4 2 52904 7 0 1 93427 4 2 52093 2 0 1 93463 4 3 71770 5 0 1 93479 4 7 64398 4 0 1 93481 4 35 62766 8 0 1 93487 4 6 85764 2 0 1 93491 4 2 51730 2 0 1 93493 4 2 64208 12 0 1 93497 4 3 73856 0 0 1 93503 4 5 56264 10 0 1 93523 4 2 52065 11 0 1 93529 4 11 50187 24 0 1 93553 4 5 58144 10 0 1 93557 4 2 52052 6 0 1 93559 4 3 87503 3 0 1 93563 4 5 49564 0 0 1 93581 4 3 87932 12 0 1 93601 4 22 81215 12 0 1 93607 4 3 55991 5 0 1 93629 4 2 66153 8 0 1 93637 4 5 85296 7 0 1 93683 4 2 60736 18 0 1 93701 4 2 65243 4 0 1 93703 4 5 48177 2 0 1 93719 4 13 67929 8 0 1 93739 4 3 60347 0 0 1 93761 4 6 56073 0 0 1 93763 4 2 51543 2 0 1 93787 4 7 58891 19 0 1 93809 4 3 93797 0 0 1 93811 4 2 61705 8 0 1 93827 4 2 53937 2 0 1 93851 4 2 53104 8 0 1 93871 4 3 59140 2 0 1 93887 4 5 73264 2 0 1 93889 4 14 69762 10 0 1 93893 4 2 75439 2 0 1 93901 4 2 88746 7 0 1 93911 4 11 87317 2 0 1 93913 4 5 68389 6 0 1 93923 4 2 88020 7 0 1 93937 4 15 48278 14 0 1 93941 4 2 88961 7 0 1 93949 4 2 60276 0 0 1 93967 4 11 85776 2 0 1 93971 4 2 62226 4 0 1 93979 4 3 54012 3 0 1 93983 4 5 92921 5 0 1 93997 4 11 68986 3 0 1 94007 4 5 49707 11 0 1 94009 4 13 93970 0 0 1 94033 4 15 75335 13 0 1 94049 4 3 58138 4 0 1 94057 4 7 80469 14 0 1 94063 4 3 61800 2 0 1 94079 4 13 57861 6 0 1 94099 4 2 52964 2 0 1 94109 4 2 81390 17 0 1 94111 4 3 90076 3 0 1 94117 4 2 86182 10 0 1 94121 4 3 94109 0 0 1 94151 4 7 69112 5 0 1 94153 4 5 66094 6 0 1 94169 4 3 94157 0 0 1 94201 4 11 53642 27 0 1 94207 4 6 92735 2 0 1 94219 4 3 56115 3 0 1 94229 4 2 53294 9 0 1 94253 4 2 70338 4 0 1 94261 4 6 66238 7 0 1 94273 4 5 91249 6 0 1 94291 4 2 51158 8 0 1 94307 4 2 51537 4 0 1 94309 4 6 60382 2 0 1 94321 4 7 64258 0 0 1 94327 4 3 92510 5 0 1 94331 4 2 57050 2 0 1 94343 4 5 90761 5 0 1 94349 4 2 70590 3 0 1 94351 4 3 70560 6 0 1 94379 4 2 62113 2 0 1 94397 4 2 75264 4 0 1 94399 4 3 76959 3 0 1 94421 4 2 67118 3 0 1 94427 4 2 47481 2 0 1 94433 4 5 57405 4 0 1 94439 4 7 74611 2 0 1 94441 4 11 61560 20 0 1 94447 4 5 94435 11 0 1 94463 4 5 73343 7 0 1 94477 4 2 92533 9 0 1 94483 4 2 48946 8 0 1 94513 4 5 74549 10 0 1 94529 4 3 70277 7 0 1 94531 4 10 73810 2 0 1 94541 4 2 86720 3 0 1 94543 4 3 54415 3 0 1 94547 4 2 75384 4 0 1 94559 4 11 66411 2 0 1 94561 4 14 57069 20 0 1 94573 4 2 83257 3 0 1 94583 4 5 94579 3 0 1 94597 4 5 67430 6 0 1 94603 4 5 89653 18 0 1 94613 4 3 81968 6 0 1 94621 4 2 47865 10 0 1 94649 4 3 79805 10 0 1 94651 4 2 54714 8 0 1 94687 4 5 77788 12 0 1 94693 4 5 54942 23 0 1 94709 4 2 82155 7 0 1 94723 4 2 94716 8 0 1 94727 4 5 61647 8 0 1 94747 4 2 80561 8 0 1 94771 4 10 68212 0 0 1 94777 4 10 61064 16 0 1 94781 4 2 86227 6 0 1 94789 4 2 76763 6 0 1 94793 4 3 61930 1 0 1 94811 4 2 65216 2 0 1 94819 4 2 71968 8 0 1 94823 4 5 94819 3 0 1 94837 4 2 55689 6 0 1 94841 4 3 79982 4 0 1 94847 4 5 79653 3 0 1 94849 4 7 64470 6 0 1 94873 4 5 63762 10 0 1 94889 4 3 63113 8 0 1 94903 4 3 72731 5 0 1 94907 4 2 83172 0 0 1 94933 4 2 94926 8 0 1 94949 4 2 93796 4 0 1 94951 4 6 93929 2 0 1 94961 4 3 73412 4 0 1 94993 4 10 72892 6 0 1 94999 4 3 67981 3 0 1 95003 4 2 88963 0 0 1 95009 4 3 94997 0 0 1 95021 4 2 93750 3 0 1 95027 4 2 69054 4 0 1 95063 4 5 86191 3 0 1 95071 4 3 85185 3 0 1 95083 4 2 65786 8 0 1 95087 4 5 67780 6 0 1 95089 4 13 62743 28 0 1 95093 4 2 79129 9 0 1 95101 4 2 65026 3 0 1 95107 4 5 59108 2 0 1 95111 4 11 57452 6 0 1 95131 4 7 71012 6 0 1 95143 4 3 95139 4 0 1 95153 4 3 74243 0 0 1 95177 4 3 60159 12 0 1 95189 4 2 83204 1 0 1 95191 4 13 93882 4 0 1 95203 4 2 48274 7 0 1 95213 4 3 87737 6 0 1 95219 4 2 49786 2 0 1 95231 4 11 61498 5 0 1 95233 4 5 68408 10 0 1 95239 4 7 49752 11 0 1 95257 4 5 75830 6 0 1 95261 4 2 62802 4 0 1 95267 4 2 48970 7 0 1 95273 4 3 83479 12 0 1 95279 4 7 80857 2 0 1 95287 4 3 85970 6 0 1 95311 4 3 69780 6 0 1 95317 4 5 48647 8 0 1 95327 4 5 81502 7 0 1 95339 4 2 79802 4 0 1 95369 4 3 76681 7 0 1 95383 4 3 73155 5 0 1 95393 4 3 74291 11 0 1 95401 4 7 48825 26 0 1 95413 4 2 68600 3 0 1 95419 4 3 93540 7 0 1 95429 4 2 75302 1 0 1 95441 4 3 91825 2 0 1 95443 4 3 64280 5 0 1 95461 4 2 84420 6 0 1 95467 4 5 89914 0 0 1 95471 4 43 78567 4 0 1 95479 4 17 72918 9 0 1 95483 4 2 86754 2 0 1 95507 4 2 93236 10 0 1 95527 4 3 82183 3 0 1 95531 4 2 76672 8 0 1 95539 4 3 67779 3 0 1 95549 4 2 95542 8 0 1 95561 4 3 78911 2 0 1 95569 4 14 92540 12 0 1 95581 4 2 69439 3 0 1 95597 4 2 77240 1 0 1 95603 4 5 53811 4 0 1 95617 4 5 74245 10 0 1 95621 4 3 89689 14 0 1 95629 4 2 51163 10 0 1 95633 4 3 75190 2 0 1 95651 4 2 81910 2 0 1 95701 4 2 78245 10 0 1 95707 4 2 64406 7 0 1 95713 4 5 79947 6 0 1 95717 4 2 81045 2 0 1 95723 4 2 66923 2 0 1 95731 4 2 69479 6 0 1 95737 4 5 79467 6 0 1 95747 4 5 74356 0 0 1 95773 4 7 89150 8 0 1 95783 4 5 95779 3 0 1 95789 4 2 74195 6 0 1 95791 4 3 84161 3 0 1 95801 4 3 59716 4 0 1 95803 4 3 55773 11 0 1 95813 4 2 58590 12 0 1 95819 4 2 52328 4 0 1 95857 4 10 66217 6 0 1 95869 4 6 70183 7 0 1 95873 4 3 61085 0 0 1 95881 4 13 80960 16 0 1 95891 4 2 80263 2 0 1 95911 4 3 77739 2 0 1 95917 4 2 75116 3 0 1 95923 4 3 52044 2 0 1 95929 4 26 48312 0 0 1 95947 4 2 93508 2 0 1 95957 4 2 84588 5 0 1 95959 4 3 55515 3 0 1 95971 4 3 53167 6 0 1 95987 4 2 85476 13 0 1 95989 4 6 68967 8 0 1 96001 4 7 75790 17 0 1 96013 4 2 93294 9 0 1 96017 4 3 67724 1 0 1 96043 4 2 74901 7 0 1 96053 4 2 93405 6 0 1 96059 4 2 77432 4 0 1 96079 4 3 81412 3 0 1 96097 4 5 81898 6 0 1 96137 4 3 78031 7 0 1 96149 4 2 68855 6 0 1 96157 4 5 85623 1 0 1 96167 4 5 87206 5 0 1 96179 4 2 79292 3 0 1 96181 4 6 96177 6 0 1 96199 4 3 62765 7 0 1 96211 4 2 59834 6 0 1 96221 4 2 75652 1 0 1 96223 4 5 96219 3 0 1 96233 4 3 94954 11 0 1 96259 4 2 94201 8 0 1 96263 4 5 71103 9 0 1 96269 4 2 55930 3 0 1 96281 4 3 96269 0 0 1 96289 4 11 55587 14 0 1 96293 4 2 71802 6 0 1 96323 4 2 58808 20 0 1 96329 4 3 51241 4 0 1 96331 4 10 67123 0 0 1 96337 4 5 74628 10 0 1 96353 4 3 71768 12 0 1 96377 4 3 93121 7 0 1 96401 4 3 67648 4 0 1 96419 4 6 51814 0 0 1 96431 4 11 68311 7 0 1 96443 4 2 94119 0 0 1 96451 4 2 75576 2 0 1 96457 4 5 84928 6 0 1 96461 4 2 60988 6 0 1 96469 4 10 90351 2 0 1 96479 4 11 56985 2 0 1 96487 4 3 96483 4 0 1 96493 4 5 62411 7 0 1 96497 4 3 62856 0 0 1 96517 4 2 88676 10 0 1 96527 4 5 67420 11 0 1 96553 4 5 80776 6 0 1 96557 4 2 67702 3 0 1 96581 4 2 59621 12 0 1 96587 4 2 76978 3 0 1 96589 4 6 67855 2 0 1 96601 4 11 63429 20 0 1 96643 4 2 79925 8 0 1 96661 4 7 59902 1 0 1 96667 4 2 54005 8 0 1 96671 4 7 92488 5 0 1 96697 4 7 48909 12 0 1 96703 4 3 49867 5 0 1 96731 4 2 61297 7 0 1 96737 4 3 52379 0 0 1 96739 4 2 75132 6 0 1 96749 4 2 49212 7 0 1 96757 4 5 79768 7 0 1 96763 4 5 65086 2 0 1 96769 4 22 78211 26 0 1 96779 4 2 92856 3 0 1 96787 4 2 86895 2 0 1 96797 4 2 92267 12 0 1 96799 4 6 67656 2 0 1 96821 4 2 53675 8 0 1 96823 4 5 68098 2 0 1 96827 4 2 87707 2 0 1 96847 4 3 83225 6 0 1 96851 4 2 62054 2 0 1 96857 4 3 73630 2 0 1 96893 4 2 94442 6 0 1 96907 4 2 65057 1 0 1 96911 4 11 52910 2 0 1 96931 4 2 60283 8 0 1 96953 4 3 94602 0 0 1 96959 4 7 81272 2 0 1 96973 4 2 49922 6 0 1 96979 4 3 77350 5 0 1 96989 4 2 71391 14 0 1 96997 4 2 50855 3 0 1 97001 4 3 75690 2 0 1 97003 4 7 56471 11 0 1 97007 4 5 73660 5 0 1 97021 4 2 58337 10 0 1 97039 4 3 89245 3 0 1 97073 4 3 64947 13 0 1 97081 4 7 90865 25 0 1 97103 4 5 68961 8 0 1 97117 4 2 59869 7 0 1 97127 4 5 97123 3 0 1 97151 4 13 89716 7 0 1 97157 4 2 86477 5 0 1 97159 4 3 59421 3 0 1 97169 4 3 97157 0 0 1 97171 4 10 65438 8 0 1 97177 4 5 65272 15 0 1 97187 4 2 87090 1 0 1 97213 4 5 91750 1 0 1 97231 4 6 56787 2 0 1 97241 4 3 97229 0 0 1 97259 4 6 83125 1 0 1 97283 4 2 56145 7 0 1 97301 4 2 56394 2 0 1 97303 4 3 70350 2 0 1 97327 4 5 82939 2 0 1 97367 4 5 81613 6 0 1 97369 4 7 87306 14 0 1 97373 4 2 86367 1 0 1 97379 4 2 66311 7 0 1 97381 4 2 73755 6 0 1 97387 4 2 65200 10 0 1 97397 4 2 74074 3 0 1 97423 4 3 57360 5 0 1 97429 4 6 97425 6 0 1 97441 4 37 66484 29 0 1 97453 4 2 68677 6 0 1 97459 4 2 89451 7 0 1 97463 4 5 63961 8 0 1 97499 4 2 61863 4 0 1 97501 4 7 80183 4 0 1 97511 4 7 90201 10 0 1 97523 4 2 97516 8 0 1 97547 4 2 79551 7 0 1 97549 4 2 93801 0 0 1 97553 4 3 54418 12 0 1 97561 4 11 81708 12 0 1 97571 4 2 54336 2 0 1 97577 4 3 89843 6 0 1 97579 4 2 63825 6 0 1 97583 4 5 53026 7 0 1 97607 4 5 97603 3 0 1 97609 4 17 53535 16 0 1 97613 4 2 96625 3 0 1 97649 4 3 97207 7 0 1 97651 4 2 84145 8 0 1 97673 4 3 73017 0 0 1 97687 4 5 62987 3 0 1 97711 4 11 88700 9 0 1 97729 4 13 51717 22 0 1 97771 4 3 90080 3 0 1 97777 4 17 92452 8 0 1 97787 4 2 65537 8 0 1 97789 4 2 88523 3 0 1 97813 4 2 63890 6 0 1 97829 4 2 90608 6 0 1 97841 4 6 52449 6 0 1 97843 4 2 54813 8 0 1 97847 4 5 85087 14 0 1 97849 4 13 64418 4 0 1 97859 4 2 69466 2 0 1 97861 4 2 92362 10 0 1 97871 4 7 52802 2 0 1 97879 4 6 81139 2 0 1 97883 4 2 71286 8 0 1 97919 4 23 83099 4 0 1 97927 4 3 69330 6 0 1 97931 4 2 91641 7 0 1 97943 4 5 72877 4 0 1 97961 4 3 51177 4 0 1 97967 4 5 71612 6 0 1 97973 4 2 89220 4 0 1 97987 4 2 65742 8 0 1 98009 4 3 80745 8 0 1 98011 4 10 52900 0 0 1 98017 4 7 66882 8 0 1 98041 4 13 86782 33 0 1 98047 4 5 98043 3 0 1 98057 4 3 66944 0 0 1 98081 4 6 65154 0 0 1 98101 4 2 73751 9 0 1 98123 4 2 75528 4 0 1 98129 4 3 90198 3 0 1 98143 4 5 79362 2 0 1 98179 4 2 69135 8 0 1 98207 4 5 75019 2 0 1 98213 4 2 68474 9 0 1 98221 4 2 64436 6 0 1 98227 4 3 60233 5 0 1 98251 4 2 58585 7 0 1 98257 4 10 94292 12 0 1 98269 4 2 49485 3 0 1 98297 4 3 60788 1 0 1 98299 4 2 57555 1 0 1 98317 4 6 49805 6 0 1 98321 4 3 98309 0 0 1 98323 4 3 97436 2 0 1 98327 4 5 64582 3 0 1 98347 4 2 49445 10 0 1 98369 4 3 55675 7 0 1 98377 4 5 81792 8 0 1 98387 4 2 94623 8 0 1 98389 4 2 59966 6 0 1 98407 4 6 85397 7 0 1 98411 4 2 52914 6 0 1 98419 4 2 88714 7 0 1 98429 4 2 56713 12 0 1 98443 4 2 85043 8 0 1 98453 4 2 75524 4 0 1 98459 4 2 88983 8 0 1 98467 4 3 60098 5 0 1 98473 4 10 50191 6 0 1 98479 4 3 96260 2 0 1 98491 4 7 66517 6 0 1 98507 4 2 87406 11 0 1 98519 4 7 54357 7 0 1 98533 4 2 87373 18 0 1 98543 4 5 84185 15 0 1 98561 4 3 82017 2 0 1 98563 4 2 88061 2 0 1 98573 4 2 97685 9 0 1 98597 4 2 97828 18 0 1 98621 4 7 98612 4 0 1 98627 4 2 51821 0 0 1 98639 4 7 88232 2 0 1 98641 4 17 78207 20 0 1 98663 4 5 77646 3 0 1 98669 4 2 59692 12 0 1 98689 4 7 91235 14 0 1 98711 4 13 83300 6 0 1 98713 4 5 88728 6 0 1 98717 4 2 64223 6 0 1 98729 4 3 85831 2 0 1 98731 4 2 96422 2 0 1 98737 4 5 59469 6 0 1 98773 4 2 77188 6 0 1 98779 4 2 59519 3 0 1 98801 4 3 77245 4 0 1 98807 4 5 96652 8 0 1 98809 4 17 64705 32 0 1 98837 4 2 64513 12 0 1 98849 4 3 98837 0 0 1 98867 4 2 89513 4 0 1 98869 4 2 92236 6 0 1 98873 4 3 86974 0 0 1 98887 4 3 98876 12 0 1 98893 4 2 91158 9 0 1 98897 4 3 84197 6 0 1 98899 4 2 78657 2 0 1 98909 4 2 88337 3 0 1 98911 4 12 57552 2 0 1 98927 4 5 98923 3 0 1 98929 4 11 95329 8 0 1 98939 4 2 89466 4 0 1 98947 4 3 57547 7 0 1 98953 4 10 82272 0 0 1 98963 4 2 54403 8 0 1 98981 4 3 98977 4 0 1 98993 4 3 83315 0 0 1 98999 4 19 66741 2 0 1 99013 4 6 53070 6 0 1 99017 4 3 86521 6 0 1 99023 4 5 83330 5 0 1 99041 4 6 95398 0 0 1 99053 4 2 69467 6 0 1 99079 4 3 63619 2 0 1 99083 4 2 89229 7 0 1 99089 4 3 69977 8 0 1 99103 4 3 99099 4 0 1 99109 4 6 99105 6 0 1 99119 4 11 55145 6 0 1 99131 4 6 78401 4 0 1 99133 4 2 94358 6 0 1 99137 4 3 83228 26 0 1 99139 4 2 51038 6 0 1 99149 4 2 90254 4 0 1 99173 4 2 62125 6 0 1 99181 4 7 83135 12 0 1 99191 4 11 65978 7 0 1 99223 4 3 99219 4 0 1 99233 4 3 94614 7 0 1 99241 4 11 58571 22 0 1 99251 4 10 60280 2 0 1 99257 4 3 87776 0 0 1 99259 4 2 99252 8 0 1 99277 4 2 75149 9 0 1 99289 4 26 50603 22 0 1 99317 4 2 71690 6 0 1 99347 4 2 66879 2 0 1 99349 4 11 56004 3 0 1 99367 4 3 87376 6 0 1 99371 4 2 90073 3 0 1 99377 4 3 59447 2 0 1 99391 4 6 95466 3 0 1 99397 4 2 60075 10 0 1 99401 4 3 99389 0 0 1 99409 4 11 55067 2 0 1 99431 4 13 96774 3 0 1 99439 4 3 91222 3 0 1 99469 4 2 56284 8 0 1 99487 4 3 81536 3 0 1 99497 4 3 60273 0 0 1 99523 4 5 59386 0 0 1 99527 4 5 50890 6 0 1 99529 4 7 72102 0 0 1 99551 4 7 92660 3 0 1 99559 4 3 97156 6 0 1 99563 4 2 54616 7 0 1 99571 4 2 87056 7 0 1 99577 4 5 63318 15 0 1 99581 4 2 76108 4 0 1 99607 4 3 52843 2 0 1 99611 4 2 66058 0 0 1 99623 4 5 88069 8 0 1 99643 4 3 72041 3 0 1 99661 4 2 68473 6 0 1 99667 4 2 50357 8 0 1 99679 4 6 58807 2 0 1 99689 4 3 99678 12 0 1 99707 4 2 81678 4 0 1 99709 4 10 59397 5 0 1 99713 4 3 82670 11 0 1 99719 4 7 52361 6 0 1 99721 4 11 67218 24 0 1 99733 4 2 94954 6 0 1 99761 4 3 75746 1 0 1 99767 4 5 76539 5 0 1 99787 4 2 55326 2 0 1 99793 4 5 86930 10 0 1 99809 4 3 74403 4 0 1 99817 4 5 91887 11 0 1 99823 4 21 63356 2 0 1 99829 4 2 58958 6 0 1 99833 4 3 76290 4 0 1 99839 4 11 83927 3 0 1 99859 4 2 57571 7 0 1 99871 4 3 69176 2 0 1 99877 4 2 80944 12 0 1 99881 4 6 94555 0 0 1 99901 4 2 76750 12 0 1 99907 4 2 81363 7 0 1 99923 4 2 88689 2 0 1 99929 4 3 68784 1 0 1 99961 4 31 95999 30 0 1 99971 4 2 80658 0 0 1 99989 4 2 65733 0 0 1 99991 4 6 63566 3 0 1 100003 4 2 98003 19 0 1 100019 4 2 94727 11 0 1 100043 4 2 80144 2 0 1 100049 4 6 60696 7 0 1 100057 4 10 50599 24 0 1 100069 4 10 65117 2 0 1 100103 4 5 84148 8 0 1 100109 4 2 87453 12 0 1 100129 4 11 85213 27 0 1 100151 4 7 100142 4 0 1 100153 4 5 85065 10 0 1 100169 4 3 100157 0 0 1 100183 4 3 61963 8 0 1 100189 4 2 100182 8 0 1 100193 4 3 54015 0 0 1 100207 4 3 79012 5 0 1 100213 4 2 52584 9 0 1 100237 4 5 61791 7 0 1 100267 4 5 100259 6 0 1 100271 4 13 57533 7 0 1 100279 4 3 51225 6 0 1 100291 4 3 76569 2 0 1 100297 4 13 80672 4 0 1 100313 4 3 54952 0 0 1 100333 4 2 82356 12 0 1 100343 4 5 86579 9 0 1 100357 4 2 54408 6 0 1 100361 4 3 62889 4 0 1 100363 4 2 97259 8 0 1 100379 4 2 60895 2 0 1 100391 4 7 70589 2 0 1 100393 4 5 63844 16 0 1 100403 4 2 80213 14 0 1 100411 4 2 53510 1 0 1 100417 4 5 78734 6 0 1 100447 4 3 74631 2 0 1 100459 4 2 76639 8 0 1 100469 4 2 57663 3 0 1 100483 4 3 88247 3 0 1 100493 4 2 92806 0 0 1 100501 4 2 50822 6 0 1 100511 4 11 50675 3 0 1 100517 4 2 55941 13 0 1 100519 4 6 82185 3 0 1 100523 4 2 62593 13 0 1 100537 4 7 86031 8 0 1 100547 4 2 56101 2 0 1 100549 4 2 50629 6 0 1 100559 4 7 79981 6 0 1 100591 4 6 94786 4 0 1 100609 4 7 87081 20 0 1 100613 4 2 81955 6 0 1 100621 4 18 96659 9 0 1 100649 4 3 78430 3 0 1 100669 4 6 55740 12 0 1 100673 4 3 65991 1 0 1 100693 4 2 55534 10 0 1 100699 4 2 58357 8 0 1 100703 4 5 81421 5 0 1 100733 4 2 60875 4 0 1 100741 4 6 52359 10 0 1 100747 4 2 63140 10 0 1 100769 4 3 58892 1 0 1 100787 4 2 72686 4 0 1 100799 4 17 67707 4 0 1 100801 4 11 56231 20 0 1 100811 4 2 68525 4 0 1 100823 4 5 71888 6 0 1 100829 4 2 86843 12 0 1 100847 4 5 77189 7 0 1 100853 4 3 66999 12 0 1 100907 4 2 98156 7 0 1 100913 4 3 95347 0 0 1 100927 4 3 53940 5 0 1 100931 4 2 77774 1 0 1 100937 4 3 95053 0 0 1 100943 4 5 74933 7 0 1 100957 4 2 54986 9 0 1 100981 4 7 91700 9 0 1 100987 4 2 60984 2 0 1 100999 4 3 84306 3 0 1 101009 4 3 74909 1 0 1 101021 4 2 96296 6 0 1 101027 4 2 53688 2 0 1 101051 4 2 96739 9 0 1 101063 4 7 101054 4 0 1 101081 4 6 79352 9 0 1 101089 4 31 63437 17 0 1 101107 4 3 83486 5 0 1 101111 4 17 61375 7 0 1 101113 4 5 90770 6 0 1 101117 4 2 91989 7 0 1 101119 4 3 69572 2 0 1 101141 4 3 92023 3 0 1 101149 4 2 50930 11 0 1 101159 4 7 76253 3 0 1 101161 4 13 92503 14 0 1 101173 4 2 86538 6 0 1 101183 4 5 99691 3 0 1 101197 4 2 54187 3 0 1 101203 4 7 59682 16 0 1 101207 4 5 88094 5 0 1 101209 4 7 65889 17 0 1 101221 4 6 61316 12 0 1 101267 4 2 74117 2 0 1 101273 4 3 72475 6 0 1 101279 4 17 53259 4 0 1 101281 4 14 82421 16 0 1 101287 4 3 101276 12 0 1 101293 4 2 92263 6 0 1 101323 4 2 65516 2 0 1 101333 4 2 97244 7 0 1 101341 4 2 61994 10 0 1 101347 4 2 71845 8 0 1 101359 4 3 97886 3 0 1 101363 4 2 74202 2 0 1 101377 4 5 70545 6 0 1 101383 4 3 61665 5 0 1 101399 4 7 101390 4 0 1 101411 4 2 69358 8 0 1 101419 4 2 96674 2 0 1 101429 4 2 101422 8 0 1 101449 4 11 85031 18 0 1 101467 4 2 60770 8 0 1 101477 4 2 86313 3 0 1 101483 4 2 96436 7 0 1 101489 4 3 101477 0 0 1 101501 4 2 58912 2 0 1 101503 4 5 84290 9 0 1 101513 4 3 68932 1 0 1 101527 4 5 92918 10 0 1 101531 4 2 88370 6 0 1 101533 4 5 83362 20 0 1 101537 4 3 74293 7 0 1 101561 4 3 99936 2 0 1 101573 4 2 84763 3 0 1 101581 4 2 65628 6 0 1 101599 4 11 77791 2 0 1 101603 4 2 92932 4 0 1 101611 4 2 64823 6 0 1 101627 4 2 90570 8 0 1 101641 4 13 97121 16 0 1 101653 4 5 101202 6 0 1 101663 4 5 98655 4 0 1 101681 4 6 89200 4 0 1 101693 4 2 93804 2 0 1 101701 4 2 77077 3 0 1 101719 4 3 90529 2 0 1 101723 4 2 70235 10 0 1 101737 4 7 59738 12 0 1 101741 4 2 78441 1 0 1 101747 4 2 92827 1 0 1 101749 4 2 57004 10 0 1 101771 4 2 76676 12 0 1 101789 4 2 84943 6 0 1 101797 4 2 88983 6 0 1 101807 4 5 97809 4 0 1 101833 4 5 93760 12 0 1 101837 4 5 64541 6 0 1 101839 4 15 91279 2 0 1 101863 4 3 65805 6 0 1 101869 4 6 95574 2 0 1 101873 4 3 86526 4 0 1 101879 4 7 78537 5 0 1 101891 4 2 54719 6 0 1 101917 4 5 101906 14 0 1 101921 4 11 58319 4 0 1 101929 4 17 54509 22 0 1 101939 4 2 88833 4 0 1 101957 4 2 80402 7 0 1 101963 4 2 76000 7 0 1 101977 4 5 88974 16 0 1 101987 4 2 99534 7 0 1 101999 4 7 75721 3 0 1 102001 4 31 83535 32 0 1 102013 4 5 87162 6 0 1 102019 4 2 97457 8 0 1 102023 4 5 52974 3 0 1 102031 4 3 66420 3 0 1 102043 4 5 86820 5 0 1 102059 4 2 100399 2 0 1 102061 4 2 74291 6 0 1 102071 4 7 59223 2 0 1 102077 4 2 102070 8 0 1 102079 4 3 59246 3 0 1 102101 4 2 93738 1 0 1 102103 4 5 88550 34 0 1 102107 4 2 52675 2 0 1 102121 4 7 96083 16 0 1 102139 4 3 101687 3 0 1 102149 4 2 54873 4 0 1 102161 4 6 67310 0 0 1 102181 4 6 89499 11 0 1 102191 4 11 79839 6 0 1 102197 4 2 85632 3 0 1 102199 4 11 101416 0 0 1 102203 4 2 97058 0 0 1 102217 4 5 72290 10 0 1 102229 4 2 62288 12 0 1 102233 4 3 61249 7 0 1 102241 4 11 98918 8 0 1 102251 4 2 59922 8 0 1 102253 4 2 101538 9 0 1 102259 4 3 100725 0 0 1 102293 4 2 57489 1 0 1 102299 4 2 63103 3 0 1 102301 4 7 77648 9 0 1 102317 4 2 81415 3 0 1 102329 4 3 83518 2 0 1 102337 4 5 52333 6 0 1 102359 4 11 92323 3 0 1 102367 4 3 66798 3 0 1 102397 4 5 69176 10 0 1 102407 4 5 85977 5 0 1 102409 4 7 55943 14 0 1 102433 4 5 61943 18 0 1 102437 4 2 57934 2 0 1 102451 4 3 85850 2 0 1 102461 4 2 57706 12 0 1 102481 4 13 57206 14 0 1 102497 4 3 64317 7 0 1 102499 4 3 56652 0 0 1 102503 4 5 54038 9 0 1 102523 4 2 65832 8 0 1 102533 4 2 69310 6 0 1 102539 4 2 102532 8 0 1 102547 4 2 92126 8 0 1 102551 4 13 58879 5 0 1 102559 4 3 81057 6 0 1 102563 4 2 93025 10 0 1 102587 4 2 87605 8 0 1 102593 4 3 55795 4 0 1 102607 4 5 70761 10 0 1 102611 4 2 54237 4 0 1 102643 4 7 59656 12 0 1 102647 4 5 102643 3 0 1 102653 4 2 53146 4 0 1 102667 4 3 100718 11 0 1 102673 4 5 102662 14 0 1 102677 4 3 87685 4 0 1 102679 4 3 65776 13 0 1 102701 4 2 63466 12 0 1 102761 4 6 79754 7 0 1 102763 4 2 102756 8 0 1 102769 4 11 57972 23 0 1 102793 4 5 73589 6 0 1 102797 4 2 66448 9 0 1 102811 4 2 75581 8 0 1 102829 4 2 72698 14 0 1 102841 4 13 66555 14 0 1 102859 4 3 86290 1 0 1 102871 4 12 91554 3 0 1 102877 4 2 89490 6 0 1 102881 4 3 86668 3 0 1 102911 4 7 84244 10 0 1 102913 4 5 55630 10 0 1 102929 4 6 65058 0 0 1 102931 4 3 87941 2 0 1 102953 4 3 52055 0 0 1 102967 4 3 102956 12 0 1 102983 4 5 100007 3 0 1 103001 4 7 92108 12 0 1 103007 4 5 63251 10 0 1 103043 4 2 102487 2 0 1 103049 4 3 97745 2 0 1 103067 4 2 86256 2 0 1 103069 4 2 79836 12 0 1 103079 4 7 60715 2 0 1 103087 4 3 85764 11 0 1 103091 4 6 72821 5 0 1 103093 4 2 77752 6 0 1 103099 4 10 83855 0 0 1 103123 4 3 100945 3 0 1 103141 4 6 103133 12 0 1 103171 4 14 95700 7 0 1 103177 4 10 55642 0 0 1 103183 4 3 84641 3 0 1 103217 4 3 69497 9 0 1 103231 4 3 93689 3 0 1 103237 4 5 55872 1 0 1 103289 4 3 103277 0 0 1 103291 4 2 96681 2 0 1 103307 4 2 55036 4 0 1 103319 4 13 66378 6 0 1 103333 4 2 72051 3 0 1 103349 4 3 89966 3 0 1 103357 4 6 74250 8 0 1 103387 4 5 75077 5 0 1 103391 4 7 99077 11 0 1 103393 4 5 65275 6 0 1 103399 4 3 103395 4 0 1 103409 4 3 79050 2 0 1 103421 4 10 65431 8 0 1 103423 4 5 84181 16 0 1 103451 4 2 65555 3 0 1 103457 4 3 95339 12 0 1 103471 4 3 99962 6 0 1 103483 4 2 61867 8 0 1 103511 4 7 102146 2 0 1 103529 4 3 103517 0 0 1 103549 4 2 61041 3 0 1 103553 4 3 58725 7 0 1 103561 4 21 101657 8 0 1 103567 4 7 72790 10 0 1 103573 4 5 60321 1 0 1 103577 4 3 92578 0 0 1 103583 4 5 86987 2 0 1 103591 4 3 83774 3 0 1 103613 4 2 88297 1 0 1 103619 4 2 53087 2 0 1 103643 4 2 88180 8 0 1 103651 4 2 82461 8 0 1 103657 4 5 101984 11 0 1 103669 4 6 76248 2 0 1 103681 4 11 79708 23 0 1 103687 4 3 55186 6 0 1 103699 4 2 95277 8 0 1 103703 4 5 78562 8 0 1 103723 4 3 83164 5 0 1 103769 4 3 103757 0 0 1 103787 4 2 97037 2 0 1 103801 4 14 86695 12 0 1 103811 4 2 73655 7 0 1 103813 4 6 79788 16 0 1 103837 4 5 92499 3 0 1 103841 4 3 103829 0 0 1 103843 4 2 93165 11 0 1 103867 4 2 79812 8 0 1 103889 4 3 79879 2 0 1 103903 4 3 52905 2 0 1 103913 4 3 87325 1 0 1 103919 4 7 103910 4 0 1 103951 4 6 77651 3 0 1 103963 4 2 83403 7 0 1 103967 4 5 90166 4 0 1 103969 4 7 75541 0 0 1 103979 4 2 69800 7 0 1 103981 4 6 61321 7 0 1 103991 4 19 73271 2 0 1 103993 4 5 103982 14 0 1 103997 4 2 75815 6 0 1 104003 4 2 57229 8 0 1 104009 4 3 103997 0 0 1 104021 4 2 64314 16 0 1 104033 4 3 70317 0 0 1 104047 4 5 82234 3 0 1 104053 4 6 100959 0 0 1 104059 4 2 72611 8 0 1 104087 4 5 87326 1 0 1 104089 4 7 65453 0 0 1 104107 4 5 100195 2 0 1 104113 4 5 68904 11 0 1 104119 4 6 101251 2 0 1 104123 4 2 78232 2 0 1 104147 4 2 67667 3 0 1 104149 4 6 98807 7 0 1 104161 4 19 86605 14 0 1 104173 4 2 86281 6 0 1 104179 4 2 69168 2 0 1 104183 4 5 53198 14 0 1 104207 4 5 104203 3 0 1 104231 4 7 64988 6 0 1 104233 4 7 68462 10 0 1 104239 4 6 69062 10 0 1 104243 4 2 70322 2 0 1 104281 4 26 99646 14 0 1 104287 4 5 63999 5 0 1 104297 4 3 56603 7 0 1 104309 4 2 75154 6 0 1 104311 4 6 69756 5 0 1 104323 4 5 53402 5 0 1 104327 4 5 104323 3 0 1 104347 4 11 100898 2 0 1 104369 4 3 96656 2 0 1 104381 4 2 69007 0 0 1 104383 4 5 104379 3 0 1 104393 4 3 59113 11 0 1 104399 4 7 98018 2 0 1 104417 4 6 98691 7 0 1 104459 4 2 101660 7 0 1 104471 4 11 71148 5 0 1 104473 4 5 80426 17 0 1 104479 4 7 68011 0 0 1 104491 4 3 85947 6 0 1 104513 4 3 62342 4 0 1 104527 4 3 60643 3 0 1 104537 4 3 76572 9 0 1 104543 4 5 77726 14 0 1 104549 4 2 60922 1 0 1 104551 4 3 70500 2 0 1 104561 4 6 61988 0 0 1 104579 4 2 85884 2 0 1 104593 4 5 92312 12 0 1 104597 4 2 78156 20 0 1 104623 4 7 75045 5 0 1 104639 4 13 83282 3 0 1 104651 4 6 55441 0 0 1 104659 4 2 102978 8 0 1 104677 4 2 91683 6 0 1 104681 4 6 91337 0 0 1 104683 4 2 74335 11 0 1 104693 4 3 90701 15 0 1 104701 4 2 93197 10 0 1 104707 4 2 85720 8 0 1 104711 4 43 92145 3 0 1 104717 4 2 98245 6 0 1 104723 4 2 99515 2 0 1 104729 4 12 86801 0 0 1 104743 4 3 84761 3 0 1 104759 4 7 101184 2 0 1 104761 4 7 96846 0 0 1 104773 4 2 101520 12 0 1 104779 4 3 54828 5 0 1 104789 4 2 85032 1 0 1 104801 4 13 104789 5 0 1 104803 4 3 57748 5 0 1 104827 4 3 81090 5 0 1 104831 4 22 96444 4 0 1 104849 4 3 104391 7 0 1 104851 4 13 61997 2 0 1 104869 4 2 81114 12 0 1 104879 4 11 73074 5 0 1 104891 4 2 104884 8 0 1 104911 4 6 62542 4 0 1 104917 4 2 65257 12 0 1 104933 4 2 90338 6 0 1 104947 4 5 87971 7 0 1 104953 4 5 81890 18 0 1 104959 4 3 72421 2 0 1 104971 4 2 101949 2 0 1 104987 4 2 55614 7 0 1 104999 4 11 79633 7 0 1 105019 4 2 94135 1 0 1 105023 4 5 84131 5 0 1 105031 4 3 74231 3 0 1 105037 4 5 90097 10 0 1 105071 4 7 69564 7 0 1 105097 4 7 55342 13 0 1 105107 4 2 98222 8 0 1 105137 4 3 103361 7 0 1 105143 4 5 95356 8 0 1 105167 4 5 105155 11 0 1 105173 4 2 77550 3 0 1 105199 4 6 103097 3 0 1 105211 4 2 55049 8 0 1 105227 4 5 57345 5 0 1 105229 4 2 105222 8 0 1 105239 4 14 93426 2 0 1 105251 4 2 82405 2 0 1 105253 4 6 54633 6 0 1 105263 4 5 105259 3 0 1 105269 4 2 60321 9 0 1 105277 4 6 86590 10 0 1 105319 4 3 58606 3 0 1 105323 4 2 95205 8 0 1 105331 4 2 96671 13 0 1 105337 4 10 79802 6 0 1 105341 4 2 56459 4 0 1 105359 4 7 78705 8 0 1 105361 4 17 91628 28 0 1 105367 4 3 101826 3 0 1 105373 4 2 84771 9 0 1 105379 4 2 70643 7 0 1 105389 4 2 102396 6 0 1 105397 4 2 80564 7 0 1 105401 4 3 58077 4 0 1 105407 4 5 84794 9 0 1 105437 4 2 64232 3 0 1 105449 4 6 54933 4 0 1 105467 4 2 104342 4 0 1 105491 4 2 82262 7 0 1 105499 4 2 78421 3 0 1 105503 4 10 57033 8 0 1 105509 4 2 86419 3 0 1 105517 4 2 60399 9 0 1 105527 4 5 74025 8 0 1 105529 4 11 75095 22 0 1 105533 4 2 74680 8 0 1 105541 4 2 54907 6 0 1 105557 4 3 81753 5 0 1 105563 4 2 73255 14 0 1 105601 4 17 61332 20 0 1 105607 4 3 80280 2 0 1 105613 4 2 88206 10 0 1 105619 4 3 70070 7 0 1 105649 4 7 104477 0 0 1 105653 4 2 101280 12 0 1 105667 4 3 84802 2 0 1 105673 4 5 94445 6 0 1 105683 4 2 54090 13 0 1 105691 4 2 103302 2 0 1 105701 4 3 70314 3 0 1 105727 4 6 56762 3 0 1 105733 4 6 77423 0 0 1 105751 4 7 78035 0 0 1 105761 4 3 89313 7 0 1 105767 4 5 68554 3 0 1 105769 4 7 105750 22 0 1 105817 4 5 80975 23 0 1 105829 4 2 105822 8 0 1 105863 4 5 83676 2 0 1 105871 4 17 68994 3 0 1 105883 4 2 58528 8 0 1 105899 4 2 53380 2 0 1 105907 4 5 102525 0 0 1 105913 4 10 64189 6 0 1 105929 4 3 105917 0 0 1 105943 4 3 96487 5 0 1 105953 4 3 67076 0 0 1 105967 4 3 74907 6 0 1 105971 4 2 105964 8 0 1 105977 4 5 64467 4 0 1 105983 4 5 98453 6 0 1 105997 4 5 84705 6 0 1 106013 4 2 54278 3 0 1 106019 4 2 85099 8 0 1 106031 4 19 94445 3 0 1 106033 4 5 101451 11 0 1 106087 4 3 106083 4 0 1 106103 4 5 106099 3 0 1 106109 4 2 84568 1 0 1 106121 4 3 55610 2 0 1 106123 4 2 94890 7 0 1 106129 4 23 64933 22 0 1 106163 4 2 86777 7 0 1 106181 4 2 92499 4 0 1 106187 4 2 91731 14 0 1 106189 4 6 62156 7 0 1 106207 4 6 104422 4 0 1 106213 4 2 70417 6 0 1 106217 4 3 65895 0 0 1 106219 4 7 106215 4 0 1 106243 4 3 96651 3 0 1 106261 4 2 97618 7 0 1 106273 4 5 62225 16 0 1 106277 4 2 53503 3 0 1 106279 4 3 62704 2 0 1 106291 4 2 82469 6 0 1 106297 4 5 96101 15 0 1 106303 4 3 59249 6 0 1 106307 4 2 73928 2 0 1 106319 4 11 91359 6 0 1 106321 4 13 95182 15 0 1 106331 4 7 78048 2 0 1 106349 4 2 85621 1 0 1 106357 4 2 69834 6 0 1 106363 4 2 66299 10 0 1 106367 4 5 57873 6 0 1 106373 4 5 89495 7 0 1 106391 4 23 90435 4 0 1 106397 4 2 104671 9 0 1 106411 4 2 105281 8 0 1 106417 4 7 82086 17 0 1 106427 4 2 95480 2 0 1 106433 4 3 102699 4 0 1 106441 4 7 75881 17 0 1 106451 4 2 95914 7 0 1 106453 4 6 78899 8 0 1 106487 4 5 106483 3 0 1 106501 4 2 106494 8 0 1 106531 4 3 73172 6 0 1 106537 4 5 80739 18 0 1 106541 4 3 86225 3 0 1 106543 4 5 72749 2 0 1 106591 4 3 90293 6 0 1 106619 4 2 68024 7 0 1 106621 4 10 100239 19 0 1 106627 4 2 71429 14 0 1 106637 4 2 99105 1 0 1 106649 4 3 106637 0 0 1 106657 4 5 60799 6 0 1 106661 4 2 54836 6 0 1 106663 4 5 106659 3 0 1 106669 4 19 104118 13 0 1 106681 4 23 79142 21 0 1 106693 4 2 100556 1 0 1 106699 4 3 82384 7 0 1 106703 4 7 68234 3 0 1 106721 4 3 65440 4 0 1 106727 4 10 81877 3 0 1 106739 4 2 91828 1 0 1 106747 4 2 69594 10 0 1 106751 4 13 86007 6 0 1 106753 4 5 90199 12 0 1 106759 4 6 105192 8 0 1 106781 4 2 104271 4 0 1 106783 4 5 99744 12 0 1 106787 4 2 76629 0 0 1 106801 4 11 75438 14 0 1 106823 4 5 106819 3 0 1 106853 4 2 53792 1 0 1 106859 4 2 58647 7 0 1 106861 4 7 92657 4 0 1 106867 4 3 104933 2 0 1 106871 4 7 71803 2 0 1 106877 4 2 84310 1 0 1 106903 4 5 106899 3 0 1 106907 4 2 81631 11 0 1 106921 4 14 79667 10 0 1 106937 4 3 71137 6 0 1 106949 4 2 89521 1 0 1 106957 4 5 100199 20 0 1 106961 4 3 61054 7 0 1 106963 4 3 57105 5 0 1 106979 4 2 85298 6 0 1 106993 4 5 68696 18 0 1 107021 4 7 62999 9 0 1 107033 4 3 87292 9 0 1 107053 4 5 88582 19 0 1 107057 4 3 57579 0 0 1 107069 4 2 100051 1 0 1 107071 4 3 87186 3 0 1 107077 4 2 107070 8 0 1 107089 4 7 96108 0 0 1 107099 4 2 87849 9 0 1 107101 4 6 107093 12 0 1 107119 4 3 97885 6 0 1 107123 4 2 77610 4 0 1 107137 4 10 59087 15 0 1 107171 4 10 101625 2 0 1 107183 4 5 65923 4 0 1 107197 4 2 87303 15 0 1 107201 4 7 78916 7 0 1 107209 4 13 73503 14 0 1 107227 4 20 62810 5 0 1 107243 4 2 66189 13 0 1 107251 4 3 79808 2 0 1 107269 4 6 84140 7 0 1 107273 4 3 86004 1 0 1 107279 4 7 69237 3 0 1 107309 4 2 80777 6 0 1 107323 4 13 77205 2 0 1 107339 4 6 54304 4 0 1 107347 4 2 68776 8 0 1 107351 4 19 87143 5 0 1 107357 4 2 89342 3 0 1 107377 4 10 97492 8 0 1 107441 4 3 107429 0 0 1 107449 4 7 87184 0 0 1 107453 4 2 100577 9 0 1 107467 4 2 106664 2 0 1 107473 4 5 93041 15 0 1 107507 4 2 101260 8 0 1 107509 4 6 107505 6 0 1 107563 4 11 91516 10 0 1 107581 4 2 57281 7 0 1 107599 4 3 76989 3 0 1 107603 4 2 94082 11 0 1 107609 4 3 73896 4 0 1 107621 4 2 65807 15 0 1 107641 4 11 91733 12 0 1 107647 4 5 92136 5 0 1 107671 4 6 90840 10 0 1 107687 4 5 62234 7 0 1 107693 4 2 60379 2 0 1 107699 4 2 88066 8 0 1 107713 4 10 100860 20 0 1 107717 4 2 95667 6 0 1 107719 4 3 96804 2 0 1 107741 4 3 107737 4 0 1 107747 4 2 107740 8 0 1 107761 4 14 107027 0 0 1 107773 4 2 101928 6 0 1 107777 4 3 95854 7 0 1 107791 4 3 72374 3 0 1 107827 4 5 60617 3 0 1 107837 4 2 63755 6 0 1 107839 4 15 77835 5 0 1 107843 4 2 99620 0 0 1 107857 4 5 89097 12 0 1 107867 4 2 60541 18 0 1 107873 4 3 67841 17 0 1 107881 4 23 105401 14 0 1 107897 4 3 54316 2 0 1 107903 4 5 70956 9 0 1 107923 4 2 106785 8 0 1 107927 4 5 107923 3 0 1 107941 4 6 64633 10 0 1 107951 4 7 103981 3 0 1 107971 4 3 98229 6 0 1 107981 4 2 96717 4 0 1 107999 4 13 59088 6 0 1 108007 4 11 86064 2 0 1 108011 4 7 55179 1 0 1 108013 4 6 75473 8 0 1 108023 4 5 77798 7 0 1 108037 4 2 80139 22 0 1 108041 4 6 103451 10 0 1 108061 4 2 70777 10 0 1 108079 4 3 108075 4 0 1 108089 4 6 75930 2 0 1 108107 4 2 105736 12 0 1 108109 4 2 62811 6 0 1 108127 4 6 87299 7 0 1 108131 4 6 64592 0 0 1 108139 4 2 77447 6 0 1 108161 4 3 108149 0 0 1 108179 4 2 99577 8 0 1 108187 4 5 71686 8 0 1 108191 4 13 105936 3 0 1 108193 4 13 69944 6 0 1 108203 4 2 64580 8 0 1 108211 4 3 58404 5 0 1 108217 4 5 71451 12 0 1 108223 4 3 72368 3 0 1 108233 4 3 58932 1 0 1 108247 4 3 102791 2 0 1 108263 4 5 92442 8 0 1 108271 4 3 65980 6 0 1 108287 4 5 87705 9 0 1 108289 4 7 75051 17 0 1 108293 4 2 107723 4 0 1 108301 4 6 103015 7 0 1 108343 4 3 99766 6 0 1 108347 4 2 100204 0 0 1 108359 4 11 106815 7 0 1 108377 4 3 104358 7 0 1 108379 4 2 65781 2 0 1 108401 4 3 73509 4 0 1 108413 4 2 61123 2 0 1 108421 4 17 78239 1 0 1 108439 4 3 83691 6 0 1 108457 4 5 66705 16 0 1 108461 4 2 59975 4 0 1 108463 4 5 108459 3 0 1 108497 4 3 81126 12 0 1 108499 4 14 92342 2 0 1 108503 4 5 63561 2 0 1 108517 4 5 89622 6 0 1 108529 4 23 80774 14 0 1 108533 4 2 90567 3 0 1 108541 4 2 64993 10 0 1 108553 4 5 88115 25 0 1 108557 4 2 102067 6 0 1 108571 4 3 92412 3 0 1 108587 4 2 81296 0 0 1 108631 4 6 92907 3 0 1 108637 4 15 59747 15 0 1 108643 4 5 108635 6 0 1 108649 4 11 87737 22 0 1 108677 4 2 82009 12 0 1 108707 4 2 80616 0 0 1 108709 4 6 81347 8 0 1 108727 4 3 108723 4 0 1 108739 4 2 63931 8 0 1 108751 4 3 79316 3 0 1 108761 4 3 108749 0 0 1 108769 4 7 73877 16 0 1 108791 4 7 58472 2 0 1 108793 4 5 70431 8 0 1 108799 4 6 94170 5 0 1 108803 4 2 57904 8 0 1 108821 4 2 68836 0 0 1 108827 4 2 97718 10 0 1 108863 4 5 57378 3 0 1 108869 4 2 106422 3 0 1 108877 4 2 103058 3 0 1 108881 4 3 70048 2 0 1 108883 4 2 92194 2 0 1 108887 4 5 68489 5 0 1 108893 4 3 95872 7 0 1 108907 4 12 62872 0 0 1 108917 4 2 81187 28 0 1 108923 4 2 57198 7 0 1 108929 4 3 70698 2 0 1 108943 4 3 59113 5 0 1 108947 4 2 77901 2 0 1 108949 4 2 80916 10 0 1 108959 4 11 71732 7 0 1 108961 4 7 90013 14 0 1 108967 4 3 80825 3 0 1 108971 4 2 55462 4 0 1 108991 4 6 70144 2 0 1 109001 4 3 108989 0 0 1 109013 4 2 102916 7 0 1 109037 4 2 105116 1 0 1 109049 4 3 109037 0 0 1 109063 4 6 67465 3 0 1 109073 4 3 83169 1 0 1 109097 4 3 93654 6 0 1 109103 4 5 85353 7 0 1 109111 4 3 55735 6 0 1 109121 4 3 109109 0 0 1 109133 4 2 59368 9 0 1 109139 4 2 61426 8 0 1 109141 4 2 79949 12 0 1 109147 4 3 100589 2 0 1 109159 4 6 98795 4 0 1 109169 4 3 100843 8 0 1 109171 4 2 83228 3 0 1 109199 4 19 95952 5 0 1 109201 4 17 55710 38 0 1 109211 4 6 61645 4 0 1 109229 4 2 83105 1 0 1 109253 4 3 68506 23 0 1 109267 4 2 97367 8 0 1 109279 4 11 58405 3 0 1 109297 4 5 99462 17 0 1 109303 4 3 95106 8 0 1 109313 4 3 102362 6 0 1 109321 4 19 67002 20 0 1 109331 4 2 81855 4 0 1 109357 4 11 61625 3 0 1 109363 4 3 108266 0 0 1 109367 4 5 83980 3 0 1 109379 4 2 83806 5 0 1 109387 4 2 62657 6 0 1 109391 4 7 109382 4 0 1 109397 4 2 74657 17 0 1 109423 4 3 105318 14 0 1 109433 4 3 90967 9 0 1 109441 4 14 57513 8 0 1 109451 4 2 72099 2 0 1 109453 4 2 75295 6 0 1 109469 4 2 58496 3 0 1 109471 4 3 95240 2 0 1 109481 4 3 97234 2 0 1 109507 4 2 64343 2 0 1 109517 4 2 76379 0 0 1 109519 4 3 99769 3 0 1 109537 4 5 109526 14 0 1 109541 4 2 56063 9 0 1 109547 4 2 67604 7 0 1 109567 4 5 108285 2 0 1 109579 4 2 73494 8 0 1 109583 4 5 90581 2 0 1 109589 4 2 105548 0 0 1 109597 4 5 61160 7 0 1 109609 4 14 76940 16 0 1 109619 4 2 76843 7 0 1 109621 4 10 74602 7 0 1 109639 4 3 109635 4 0 1 109661 4 3 109657 4 0 1 109663 4 11 103620 5 0 1 109673 4 3 72803 0 0 1 109717 4 5 56797 10 0 1 109721 4 3 90989 7 0 1 109741 4 2 98434 6 0 1 109751 4 11 108128 6 0 1 109789 4 10 55492 12 0 1 109793 4 3 79253 0 0 1 109807 4 5 109803 3 0 1 109819 4 3 89809 3 0 1 109829 4 2 105285 3 0 1 109831 4 3 103096 3 0 1 109841 4 3 81116 4 0 1 109843 4 2 77866 7 0 1 109847 4 5 65590 14 0 1 109849 4 7 91741 24 0 1 109859 4 2 97735 3 0 1 109873 4 15 56143 0 0 1 109883 4 2 105350 8 0 1 109891 4 2 83307 6 0 1 109897 4 10 79199 12 0 1 109903 4 3 81212 2 0 1 109913 4 3 103200 2 0 1 109919 4 17 109911 3 0 1 109937 4 3 96530 5 0 1 109943 4 5 109939 3 0 1 109961 4 3 109949 0 0 1 109987 4 3 100525 3 0 1 flint2-2.8.4/qadic/ctx_clear.c000066400000000000000000000011441414523752600161250ustar00rootroot00000000000000/* 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 2.1 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); } flint2-2.8.4/qadic/ctx_init.c000066400000000000000000000066361414523752600160150ustar00rootroot00000000000000/* Copyright (C) 2011 Sebastian Pancratz Copyright (C) 2013 Mike Hansen Copyright (C) 2020 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_vec.h" #include "fmpz_mod_poly.h" #include "padic.h" #include "qadic.h" extern int flint_conway_polynomials []; 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) { unsigned int position; flint_rand_t state; fmpz_mod_poly_t poly; slong i, j; fmpz_mod_ctx_t ctxp; if (fmpz_cmp_ui(p, 109987) <= 0) { for (position = 0; flint_conway_polynomials[position] != 0; position += 3 + flint_conway_polynomials[position + 1]) { /* Different prime? */ if (fmpz_cmp_ui(p, flint_conway_polynomials[position])) continue; /* Same degree? */ if (d == flint_conway_polynomials[position + 1]) { /* Find number of non-zero coefficients */ ctx->len = 1; for (i = 0; i < d; i++) { if (flint_conway_polynomials[position + 2 + 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++) { int coeff = flint_conway_polynomials[position + 2 + i]; if (coeff) { fmpz_set_ui(ctx->a + j, coeff); 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); 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); } flint2-2.8.4/qadic/ctx_init_conway.c000066400000000000000000000050551414523752600173670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "fmpz_vec.h" #include "padic.h" #include "qadic.h" int flint_conway_polynomials [] = { #include "CPimport.h" 0 }; 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) { unsigned int position; if (fmpz_cmp_ui(p, 109987) > 0) { flint_printf("Exception (qadic_ctx_init_conway). Conway polynomials \n"); flint_printf("are only available for primes up to 109987.\n"); flint_abort(); } for (position = 0; flint_conway_polynomials[position] != 0; position += 3+flint_conway_polynomials[position+1]) { /* Different prime? */ if (fmpz_cmp_ui(p, flint_conway_polynomials[position])) continue; /* Same degree? */ if (d == flint_conway_polynomials[position+1]) { slong i, j; /* Find number of non-zero coefficients */ ctx->len = 1; for (i = 0; i < d; i++) { if (flint_conway_polynomials[position+2+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++) { int coeff = flint_conway_polynomials[position+2+i]; if (coeff) { fmpz_set_ui(ctx->a + j, coeff); 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); return; } } flint_printf("Exception (qadic_ctx_init_conway). The polynomial for \n"); flint_printf("(p,d) = (%wd,%wd) is not present in the database.\n", *p, d); flint_abort(); } flint2-2.8.4/qadic/exp.c000066400000000000000000000044601414523752600147610ustar00rootroot00000000000000/* 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 2.1 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; } } flint2-2.8.4/qadic/exp_balanced.c000066400000000000000000000124601414523752600165710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } } flint2-2.8.4/qadic/exp_rectangular.c000066400000000000000000000133041414523752600173450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "qadic.h" 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_sqr(rop, 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; } } flint2-2.8.4/qadic/fprint_pretty.c000066400000000000000000000104771414523752600171030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "qadic.h" #include "padic.h" 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_printf("ERROR (qadic_fprint_pretty). u < 0 in SERIES mode.\n"); flint_abort(); } 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_printf("Exception (qadic_fprint_pretty). Unknown print mode.\n"); flint_abort(); } 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); } flint2-2.8.4/qadic/frobenius.c000066400000000000000000000220621414523752600161570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "ulong_extras.h" #include "qadic.h" /* 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); } } flint2-2.8.4/qadic/inlines.c000066400000000000000000000010521414523752600156200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define QADIC_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "qadic.h" flint2-2.8.4/qadic/inv.c000066400000000000000000000106111414523752600147540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "qadic.h" 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_printf("Exception (qadic_inv). Zero is not invertible.\n"); flint_abort(); } /* 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); } } flint2-2.8.4/qadic/log.c000066400000000000000000000047441414523752600147530ustar00rootroot00000000000000/* 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 2.1 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; } } flint2-2.8.4/qadic/log_balanced.c000066400000000000000000000163621414523752600165630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_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; } } flint2-2.8.4/qadic/log_rectangular.c000066400000000000000000000145511414523752600173370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_poly.h" #include "qadic.h" /* 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; } } flint2-2.8.4/qadic/mul.c000066400000000000000000000042641414523752600147640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } } flint2-2.8.4/qadic/norm.c000066400000000000000000000051431414523752600151370ustar00rootroot00000000000000/* 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 2.1 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; } } flint2-2.8.4/qadic/norm_analytic.c000066400000000000000000000051221414523752600170200ustar00rootroot00000000000000/* 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 2.1 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_printf("ERROR (qadic_norm_analytic). w = %wd.\n", w); flint_abort(); } _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); } } flint2-2.8.4/qadic/norm_resultant.c000066400000000000000000000103231414523752600172340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "qadic.h" /* Computes the characteristic polynomial of the $n \times n$ matrix $M$ modulo \code{pN} using a division-free algorithm in $O(n^4)$ ring operations. Only returns the determinant. Assumes that $n$ is at least $2$. */ static void _fmpz_mod_mat_det(fmpz_t rop, const fmpz *M, slong n, const fmpz_t pN) { fmpz *F; fmpz *a; fmpz *A; fmpz_t s; slong t, i, j, p, k; F = _fmpz_vec_init(n); a = _fmpz_vec_init((n-1) * n); A = _fmpz_vec_init(n); fmpz_init(s); fmpz_neg(F + 0, M + 0*n + 0); for (t = 1; t < n; t++) { for (i = 0; i <= t; i++) fmpz_set(a + 0*n + i, M + i*n + t); fmpz_set(A + 0, M + t*n + t); for (p = 1; p < t; p++) { for (i = 0; i <= t; i++) { fmpz_zero(s); for (j = 0; j <= t; j++) fmpz_addmul(s, M + i*n + j, a + (p-1)*n + j); fmpz_mod(a + p*n + i, s, pN); } fmpz_set(A + p, a + p*n + t); } fmpz_zero(s); for (j = 0; j <= t; j++) fmpz_addmul(s, M + t*n + j, a + (t-1)*n + j); fmpz_mod(A + t, s, pN); for (p = 0; p <= t; p++) { fmpz_sub(F + p, F + p, A + p); for (k = 0; k < p; k++) fmpz_submul(F + p, A + k, F + (p-k-1)); fmpz_mod(F + p, F + p, pN); } } /* Now [F{n-1}, F{n-2}, ..., F{0}, 1] is the characteristic polynomial of the matrix M. */ if (n % WORD(2) == 0) { fmpz_set(rop, F + (n-1)); } else { fmpz_neg(rop, F + (n-1)); fmpz_mod(rop, rop, pN); } _fmpz_vec_clear(F, n); _fmpz_vec_clear(a, (n-1)*n); _fmpz_vec_clear(A, n); fmpz_clear(s); } 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 */ { { const slong n = d + len - 1; slong i, k; fmpz *M; M = flint_calloc(n * n, sizeof(fmpz)); for (k = 0; k < len-1; k++) { for (i = 0; i < lena; i++) { M[k * n + k + (d - j[i])] = a[i]; } } for (k = 0; k < d; k++) { for (i = 0; i < len; i++) { M[(len-1 + k) * n + k + (len-1 - i)] = op[i]; } } _fmpz_mod_mat_det(rop, M, n, pN); flint_free(M); } /* 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; } } flint2-2.8.4/qadic/pow.c000066400000000000000000000106561414523752600147760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "fmpz_mod_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_printf("Exception (qadic_pow). e < 0.\n"); flint_abort(); } 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); } } flint2-2.8.4/qadic/profile/000077500000000000000000000000001414523752600154555ustar00rootroot00000000000000flint2-2.8.4/qadic/profile/p-exp_balanced.c000066400000000000000000000052151414523752600204660ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); 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; 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"); } flint2-2.8.4/qadic/profile/p-exp_rectangular.c000066400000000000000000000052441414523752600212460ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); 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; 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"); } flint2-2.8.4/qadic/profile/p-frobenius.c000066400000000000000000000052061414523752600200550ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); 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; 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"); } flint2-2.8.4/qadic/profile/p-inv.c000066400000000000000000000051611414523752600166550ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); 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; 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"); } flint2-2.8.4/qadic/profile/p-log_balanced.c000066400000000000000000000054561414523752600204620ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); 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; 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"); } flint2-2.8.4/qadic/profile/p-log_rectangular.c000066400000000000000000000055061414523752600212340ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); 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; 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"); } flint2-2.8.4/qadic/profile/p-mul.c000066400000000000000000000057521414523752600166640ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); 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; 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"); } flint2-2.8.4/qadic/profile/p-norm_analytic.c000066400000000000000000000054501414523752600207210ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); 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; 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"); } flint2-2.8.4/qadic/profile/p-norm_resultant.c000066400000000000000000000054601414523752600211370ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); 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; 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"); } flint2-2.8.4/qadic/profile/p-sqrt.c000066400000000000000000000055341414523752600170560ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); 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; 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"); 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"); } flint2-2.8.4/qadic/profile/p-teichmuller.c000066400000000000000000000047041414523752600204000ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); 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; 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"); } flint2-2.8.4/qadic/profile/p-trace.c000066400000000000000000000052611414523752600171600ustar00rootroot00000000000000/* 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 2.1 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 #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++) { FLINT_TEST_INIT(state); 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; 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"); } flint2-2.8.4/qadic/set_fmpz_poly.c000066400000000000000000000014741414523752600170610ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/qadic/sqrt.c000066400000000000000000000564501414523752600151640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "nmod_mat.h" #include "fmpz_mod_poly.h" #include "qadic.h" /* 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. */ FLINT_DLL 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, rk, *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. */ rk = nmod_mat_lu(P, A, 0); assert(rk == d-1); /* 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_mod_poly_scalar_mul_fmpz(rop, w, d, f, 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); 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; /* FIXME: In this case, we don't actually check whether the element is a square! */ if (rop->val >= N) { qadic_zero(rop); return 1; } if (rop == op) { t = _fmpz_vec_init(2 * d - 1); } else { padic_poly_fit_length(rop, 2 * d - 1); t = rop->coeffs; } 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; } _padic_poly_set_length(rop, d); _padic_poly_normalise(rop); if (padic_poly_length(rop) == 0) padic_poly_val(rop) = 0; return ans; } flint2-2.8.4/qadic/teichmuller.c000066400000000000000000000103471414523752600165030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "fmpz_mod_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_printf("Exception (qadic_teichmuller). val(op) is negative.\n"); flint_abort(); } 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); } } flint2-2.8.4/qadic/test/000077500000000000000000000000001414523752600147745ustar00rootroot00000000000000flint2-2.8.4/qadic/test/t-add.c000066400000000000000000000160171414523752600161360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(lhs); qadic_clear(rhs); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-exp.c000066400000000000000000000077431414523752600162100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "qadic.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("exp... "); fflush(stdout); /* 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); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-exp_balanced.c000066400000000000000000000100311414523752600200010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "qadic.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("exp_balanced... "); fflush(stdout); /* 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); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-exp_rectangular.c000066400000000000000000000100531414523752600205630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "qadic.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("exp_rectangular... "); fflush(stdout); /* 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); 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"); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-frobenius.c000066400000000000000000000174031414523752600174020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("frobenius... "); fflush(stdout); /* 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); 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); 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); 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); 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); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-inv.c000066400000000000000000000056011414523752600161770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("inv... "); fflush(stdout); /* 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"); 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"); abort(); } qadic_clear(a); qadic_clear(b); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-log.c000066400000000000000000000127711414523752600161720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "qadic.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("log... "); fflush(stdout); /** 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"); 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); 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"); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-log_balanced.c000066400000000000000000000131001414523752600177660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "qadic.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("log_balanced... "); fflush(stdout); /** 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"); 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); 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"); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-log_rectangular.c000066400000000000000000000130201414523752600205450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "qadic.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("log_rectangular... "); fflush(stdout); /** 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"); 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"); 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"); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-mul.c000066400000000000000000000156641414523752600162120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(lhs); qadic_clear(rhs); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-neg.c000066400000000000000000000062601414523752600161560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("neg... "); fflush(stdout); /* 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"); 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"); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c1); qadic_clear(c2); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-norm.c000066400000000000000000000047731414523752600163670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("norm... "); fflush(stdout); /* 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); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); padic_clear(x); padic_clear(y); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-norm_analytic.c000066400000000000000000000051411414523752600202410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("norm_analytic... "); fflush(stdout); /* 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); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); padic_clear(x); padic_clear(y); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-norm_resultant.c000066400000000000000000000050171414523752600204600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("norm_resultant... "); fflush(stdout); /* 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); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); padic_clear(x); padic_clear(y); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-pow.c000066400000000000000000000064541414523752600162170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow... "); fflush(stdout); /* 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"); 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"); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(e); fmpz_clear(f); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-sqrt.c000066400000000000000000000526611414523752600164040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" FLINT_DLL extern int _artin_schreier_preimage(fmpz *rop, const fmpz *op, slong len, const fmpz *a, const slong *j, slong lena); int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrt... "); fflush(stdout); /* 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); 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); 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; qadic_t a, b, c; 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_randtest_val(b, state, 0, ctx); qadic_mul(a, b, b, ctx); ans = qadic_sqrt(c, 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); 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); abort(); }*/ qadic_clear(a); qadic_clear(b); qadic_clear(c); 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; qadic_t a, b; 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_randtest_val(a, state, 0, ctx); ans = qadic_sqrt(b, a, ctx); 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); abort(); } qadic_clear(c); qadic_clear(d); } qadic_clear(a); qadic_clear(b); qadic_ctx_clear(ctx); } /* Test random squares */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong deg, N; qadic_ctx_t ctx; int ans; qadic_t a, b, c; deg = n_randint(state, 10) + 1; /* N >= 3 */ N = n_randint(state, 50) + 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_randtest_val(b, state, 0, ctx); qadic_randtest_int(b, state, ctx); qadic_mul(a, b, b, ctx); ans = qadic_sqrt(c, a, ctx); 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); 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); abort(); } } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_ctx_clear(ctx); } /* Test random elements */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_t p = {WORD(2)}; slong d, N; qadic_ctx_t ctx; int ans; qadic_t a, b; 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_randtest(a, state, ctx); ans = qadic_sqrt(b, a, ctx); 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); abort(); } qadic_clear(c); qadic_clear(d); } qadic_clear(a); qadic_clear(b); 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); 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; 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); 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_randtest_val(b, state, 0, ctx); qadic_mul(a, b, b, ctx); ans = qadic_sqrt(c, 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); 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); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); 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; qadic_t a, b; 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_randtest_val(a, state, 0, ctx); ans = qadic_sqrt(b, a, ctx); 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); abort(); } qadic_clear(c); qadic_clear(d); } qadic_clear(a); qadic_clear(b); 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, q; qadic_ctx_t ctx; int ans; 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); deg = n_randint(state, 10) + 1; N = z_randint(state, 50) + 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_randtest_val(b, state, 0, ctx); /* XXX */ qadic_mul(a, b, b, ctx); ans = qadic_sqrt(c, 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); 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); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); 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, q; qadic_ctx_t ctx; int ans; qadic_t a, b; 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_randtest(a, state, ctx); ans = qadic_sqrt(b, a, ctx); 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); abort(); } qadic_clear(c); qadic_clear(d); } qadic_clear(a); qadic_clear(b); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-sub.c000066400000000000000000000156731414523752600162060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub... "); fflush(stdout); /* 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"); 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"); 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"); 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"); 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"); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); qadic_clear(lhs); qadic_clear(rhs); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-teichmuller.c000066400000000000000000000063611414523752600177240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("teichmuller... "); fflush(stdout); /* 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"); 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); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); fmpz_clear(p); fmpz_clear(q); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/test/t-trace.c000066400000000000000000000047671414523752600165150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "qadic.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("trace... "); fflush(stdout); /* 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); abort(); } qadic_clear(a); qadic_clear(b); qadic_clear(c); padic_clear(x); padic_clear(y); fmpz_clear(p); qadic_ctx_clear(ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/qadic/trace.c000066400000000000000000000036571414523752600152720ustar00rootroot00000000000000/* 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 2.1 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); } } flint2-2.8.4/qadicxx.h000066400000000000000000000316761414523752600145630ustar00rootroot00000000000000/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef QADICXX_H #define QADICXX_H #include // std::max #include "qadic.h" #include "flintxx/expression.h" #include "flintxx/flint_classes.h" #include "flintxx/matrix.h" // trace ... #include "padicxx.h" namespace flint { FLINT_DEFINE_BINOP(frobenius) FLINT_DEFINE_UNOP(norm) FLINT_DEFINE_UNOP(norm_analytic) FLINT_DEFINE_UNOP(norm_resultant) class qadicxx_ctx { private: mutable qadic_ctx_t ctx; public: // NB: you must not modify user-visible state of ctx through a constant // instance of qadicxx_ctx qadic_ctx_t& _ctx() const {return ctx;} padicxx_ctx_srcref pctx() const {return padicxx_ctx_srcref::make(&ctx->pctx);} // TODO more constructors? Should we wrap padic_print_mode? qadicxx_ctx(fmpzxx_srcref p, slong d, slong min, slong max, padic_print_mode mode, const char* var = "x") { qadic_ctx_init_conway(ctx, p._fmpz(), d, min, max, var, mode); } ~qadicxx_ctx() {qadic_ctx_clear(ctx);} }; inline void print(const qadicxx_ctx& c) { qadic_ctx_print(c._ctx()); } namespace traits { template struct has_qadicxx_ctx : mp::false_ { }; template struct is_qadic_expr : has_qadicxx_ctx::type> { }; } // traits namespace detail { struct has_qadicxx_ctx_predicate { template struct type : traits::has_qadicxx_ctx { }; }; } // detail namespace tools { template const qadicxx_ctx& find_qadicxx_ctx(const Expr& e) { return tools::find_subexpr(e).get_qctx(); } } // tools namespace detail { template struct qadic_traits { static slong prec(const Qadic& q) {return tools::padic_output_prec(q);} }; } // detail template class qadicxx_expression : public expression, Operation, Data> { public: typedef expression, Operation, Data> base_t; FLINTXX_DEFINE_BASICS(qadicxx_expression) FLINTXX_DEFINE_CTORS(qadicxx_expression) FLINTXX_DEFINE_C_REF(qadicxx_expression, qadic_struct, _qadic) typedef detail::qadic_traits traits_t; // These only make sense with immediates void reduce() {qadic_reduce(_qadic(), _ctx());} void set_zero() {qadic_zero(_qadic());} void set_one() {qadic_one(_qadic());} void set_gen() {qadic_gen(_qadic(), _ctx());} const qadicxx_ctx& get_qctx() const {return this->_data().ctx;} padicxx_ctx_srcref get_ctx() const {return get_qctx().pctx();} qadic_ctx_t& _ctx() const {return get_qctx()._ctx();} // these only make sense with qadicxx static qadicxx_expression zero(const qadicxx_ctx& ctx) {return qadicxx_expression(ctx);} static qadicxx_expression zero(const qadicxx_ctx& ctx, slong N) {return qadicxx_expression(ctx, N);} static qadicxx_expression one(const qadicxx_ctx& ctx) { qadicxx_expression res(ctx); res.set_one(); return res; } static qadicxx_expression one(const qadicxx_ctx& ctx, slong N) { qadicxx_expression res(ctx, N); res.set_one(); return res; } static qadicxx_expression gen(const qadicxx_ctx& ctx) { qadicxx_expression res(ctx); res.set_gen(); return res; } static qadicxx_expression gen(const qadicxx_ctx& ctx, slong N) { qadicxx_expression res(ctx, N); res.set_gen(); return res; } template static qadicxx_expression from_ground(const qadicxx_ctx& ctx, const Padic& p, typename mp::enable_if >::type* = 0) { qadicxx_expression res(ctx); res = p; return res; } template static qadicxx_expression from_ground(const qadicxx_ctx& ctx, slong N, const Padic& p, typename mp::enable_if >::type* = 0) { qadicxx_expression res(ctx, N); res = p; return res; } static qadicxx_expression randtest(frandxx& state, const qadicxx_ctx& ctx, slong prec = PADIC_DEFAULT_PREC) { qadicxx_expression res(ctx, prec); qadic_randtest(res._qadic(), state._data(), ctx._ctx()); return res; } static qadicxx_expression randtest_not_zero(frandxx& state, const qadicxx_ctx& ctx, slong prec = PADIC_DEFAULT_PREC) { qadicxx_expression res(ctx, prec); qadic_randtest_not_zero(res._qadic(), state._data(), ctx._ctx()); return res; } static qadicxx_expression randtest_val(frandxx& state, slong val, const qadicxx_ctx& ctx, slong prec = PADIC_DEFAULT_PREC) { qadicxx_expression res(ctx, prec); qadic_randtest_val(res._qadic(), state._data(), val, ctx._ctx()); return res; } static qadicxx_expression randtest_int(frandxx& state, const qadicxx_ctx& ctx, slong prec = PADIC_DEFAULT_PREC) { qadicxx_expression res(ctx, prec); qadic_randtest_int(res._qadic(), state._data(), ctx._ctx()); return res; } const qadicxx_ctx& estimate_ctx() const { return tools::find_qadicxx_ctx(*this); } // Create a temporary. The context will be estimated, and the precision // will be the maximum of all subexpressions. evaluated_t create_temporary() const { return evaluated_t(estimate_ctx(), prec()); } // TODO randomisation typename flint_classes::to_srcref::type toN(slong N) const { return flint_classes::to_srcref::type::make( this->_data().inner, get_qctx(), N); } slong prec () const {return traits_t::prec(*this);} // these cause evaluation slong val() const {return qadic_val(this->evaluate()._qadic());} bool is_zero() const {return qadic_is_zero(this->evaluate()._qadic());} bool is_one() const {return qadic_is_one(this->evaluate()._qadic());} // forwarding of lazy functions FLINTXX_DEFINE_MEMBER_BINOP(frobenius) FLINTXX_DEFINE_MEMBER_BINOP(pow) FLINTXX_DEFINE_MEMBER_UNOP(exp) FLINTXX_DEFINE_MEMBER_UNOP(exp_balanced) FLINTXX_DEFINE_MEMBER_UNOP(exp_rectangular) FLINTXX_DEFINE_MEMBER_UNOP(inv) FLINTXX_DEFINE_MEMBER_UNOP(log) FLINTXX_DEFINE_MEMBER_UNOP(log_balanced) FLINTXX_DEFINE_MEMBER_UNOP(teichmuller) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(padicxx, trace) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(padicxx, norm) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(padicxx, norm_analytic) FLINTXX_DEFINE_MEMBER_UNOP_RTYPE(padicxx, norm_resultant) }; namespace detail { struct qadic_data; } typedef qadicxx_expression qadicxx; typedef qadicxx_expression > qadicxx_ref; typedef qadicxx_expression > qadicxx_srcref; namespace traits { template<> struct has_padicxx_ctx : mp::true_ { }; template<> struct has_padicxx_ctx : mp::true_ { }; template<> struct has_padicxx_ctx : mp::true_ { }; template<> struct has_qadicxx_ctx : mp::true_ { }; template<> struct has_qadicxx_ctx : mp::true_ { }; template<> struct has_qadicxx_ctx : mp::true_ { }; template struct is_qadicxx : flint_classes::is_Base { }; } // traits namespace detail { template<> struct qadic_traits { template static slong prec(const Q& q) {return q._data().N;} }; template<> struct qadic_traits { template static slong prec(const Q& q) {return qadic_prec(q._qadic());} }; template<> struct qadic_traits : qadic_traits { }; } PADICXX_DEFINE_REF_STRUCTS_(qadicxx, qadic_struct, qadic_prec, const qadicxx_ctx&) namespace detail { struct qadic_data { typedef qadic_t& data_ref_t; typedef const qadic_t& data_srcref_t; const qadicxx_ctx& ctx; qadic_t inner; qadic_data(const qadicxx_ctx& c) : ctx(c) { qadic_init(inner); } qadic_data(const qadicxx_ctx& c, slong N) : ctx(c) { qadic_init2(inner, N); } qadic_data(const qadic_data& o) : ctx(o.ctx) { qadic_init2(inner, qadic_prec(o.inner)); qadic_set(inner, o.inner, ctx._ctx()); } ~qadic_data() {qadic_clear(inner);} qadic_data(qadicxx_srcref c) : ctx(c.get_qctx()) { qadic_init2(inner, c.prec()); qadic_set(inner, c._qadic(), ctx._ctx()); } }; } // detail #define QADICXX_COND_S FLINTXX_COND_S(qadicxx) #define QADICXX_COND_T FLINTXX_COND_T(qadicxx) namespace rules { FLINT_DEFINE_DOIT_COND2(assignment, QADICXX_COND_T, QADICXX_COND_S, qadic_set(to._qadic(), from._qadic(), to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, QADICXX_COND_T, traits::is_unsigned_integer, qadic_set_ui(to._qadic(), from, to._ctx())) FLINT_DEFINE_DOIT_COND2(assignment, QADICXX_COND_T, PADICXX_COND_S, padic_poly_set_padic(to._qadic(), from._padic(), from._ctx())) FLINT_DEFINE_PRINT_PRETTY_COND(QADICXX_COND_S, qadic_fprint_pretty(to, from._qadic(), from._ctx())) template struct conversion >::type> { static padicxx get(const T& from) { padicxx res(from.estimate_ctx().pctx(), from.prec()); execution_check(qadic_get_padic(res._padic(), from._qadic(), from._ctx()), "get_padic", "qadic"); return res; } }; FLINTXX_DEFINE_SWAP(qadicxx, qadic_swap(e1._qadic(), e2._qadic())) FLINTXX_DEFINE_EQUALS(qadicxx, qadic_equal(e1._qadic(), e2._qadic())) FLINT_DEFINE_CBINARY_EXPR_COND2(plus, qadicxx, QADICXX_COND_S, QADICXX_COND_S, qadic_add(to._qadic(), e1._qadic(), e2._qadic(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(minus, qadicxx, QADICXX_COND_S, QADICXX_COND_S, qadic_sub(to._qadic(), e1._qadic(), e2._qadic(), to._ctx())) FLINT_DEFINE_CBINARY_EXPR_COND2(times, qadicxx, QADICXX_COND_S, QADICXX_COND_S, qadic_mul(to._qadic(), e1._qadic(), e2._qadic(), to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(negate, qadicxx, QADICXX_COND_S, qadic_neg(to._qadic(), from._qadic(), to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(inv_op, qadicxx, QADICXX_COND_S, qadic_inv(to._qadic(), from._qadic(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(pow_op, qadicxx, QADICXX_COND_S, traits::is_fmpzxx, qadic_pow(to._qadic(), e1._qadic(), e2._fmpz(), to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(exp_op, qadicxx, QADICXX_COND_S, execution_check( qadic_exp(to._qadic(), from._qadic(), to._ctx()), "exp", "qadic")) FLINT_DEFINE_UNARY_EXPR_COND(exp_balanced_op, qadicxx, QADICXX_COND_S, execution_check(qadic_exp_balanced( to._qadic(), from._qadic(), to._ctx()), "exp_balanced", "qadic")) FLINT_DEFINE_UNARY_EXPR_COND(exp_rectangular_op, qadicxx, QADICXX_COND_S, execution_check(qadic_exp_rectangular( to._qadic(), from._qadic(), to._ctx()), "exp_rectangular", "qadic")) FLINT_DEFINE_UNARY_EXPR_COND(log_op, qadicxx, QADICXX_COND_S, execution_check( qadic_log(to._qadic(), from._qadic(), to._ctx()), "log", "qadic")) FLINT_DEFINE_UNARY_EXPR_COND(log_rectangular_op, qadicxx, QADICXX_COND_S, execution_check(qadic_log_rectangular( to._qadic(), from._qadic(), to._ctx()), "log_rectangular", "qadic")) FLINT_DEFINE_UNARY_EXPR_COND(log_balanced_op, qadicxx, QADICXX_COND_S, execution_check(qadic_log_balanced( to._qadic(), from._qadic(), to._ctx()), "log_balanced", "qadic")) FLINT_DEFINE_UNARY_EXPR_COND(teichmuller_op, qadicxx, QADICXX_COND_S, qadic_teichmuller(to._qadic(), from._qadic(), to._ctx())) FLINT_DEFINE_BINARY_EXPR_COND2(frobenius_op, qadicxx, QADICXX_COND_S, traits::fits_into_slong, qadic_frobenius(to._qadic(), e1._qadic(), e2, to._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(trace_op, padicxx, QADICXX_COND_S, qadic_trace(to._padic(), from._qadic(), from._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(norm_op, padicxx, QADICXX_COND_S, qadic_norm(to._padic(), from._qadic(), from._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(norm_analytic_op, padicxx, QADICXX_COND_S, qadic_norm_analytic(to._padic(), from._qadic(), from._ctx())) FLINT_DEFINE_UNARY_EXPR_COND(norm_resultant_op, padicxx, QADICXX_COND_S, qadic_norm_resultant(to._padic(), from._qadic(), from._ctx())) } // rules } // flint #endif flint2-2.8.4/qsieve.h000066400000000000000000000376171414523752600144170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #ifndef QSIEVE_H #define QSIEVE_H #include #include #include #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" #include "fmpz_vec.h" #include "fmpz_factor.h" #include "thread_support.h" #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 prime_t { mp_limb_t pinv; /* precomputed inverse */ int p; /* prime */ char size; } prime_t; typedef struct fac_t /* struct for factors of relations */ { slong ind; slong exp; } fac_t; typedef struct la_col_t /* 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 hash_t /* 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 relation_t /* 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 qs_poly_s { 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 qs_s { 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 ***************************************************************************/ 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))) FLINT_DLL void qsieve_init(qs_t qs_inf, const fmpz_t n); FLINT_DLL mp_limb_t qsieve_knuth_schroeppel(qs_t qs_inf); FLINT_DLL void qsieve_clear(qs_t qs_inf); FLINT_DLL void qsieve_factor(fmpz_factor_t factors, const fmpz_t n); FLINT_DLL prime_t * compute_factor_base(mp_limb_t * small_factor, qs_t qs_inf, slong num_primes); FLINT_DLL mp_limb_t qsieve_primes_init(qs_t qs_inf); FLINT_DLL mp_limb_t qsieve_primes_increment(qs_t qs_inf, mp_limb_t delta); FLINT_DLL mp_limb_t qsieve_poly_init(qs_t qs_inf); FLINT_DLL int qsieve_init_A(qs_t qs_inf); FLINT_DLL void qsieve_reinit_A(qs_t qs_inf); FLINT_DLL int qsieve_next_A(qs_t qs_inf); FLINT_DLL void qsieve_init_poly_first(qs_t qs_inf); FLINT_DLL void qsieve_init_poly_next(qs_t qs_inf, slong i); FLINT_DLL void qsieve_compute_C(fmpz_t C, qs_t qs_inf, qs_poly_t poly); FLINT_DLL void qsieve_poly_copy(qs_poly_t poly, qs_t qs_inf); FLINT_DLL void qsieve_poly_clear(qs_t qs_inf); FLINT_DLL void qsieve_do_sieving(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly); FLINT_DLL void qsieve_do_sieving2(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly); FLINT_DLL slong qsieve_evaluate_candidate(qs_t qs_inf, ulong i, unsigned char * sieve, qs_poly_t poly); FLINT_DLL slong qsieve_evaluate_sieve(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly); FLINT_DLL slong qsieve_collect_relations(qs_t qs_inf, unsigned char * sieve); FLINT_DLL void qsieve_linalg_init(qs_t qs_inf); FLINT_DLL void qsieve_linalg_realloc(qs_t qs_inf); FLINT_DLL void qsieve_linalg_clear(qs_t qs_inf); FLINT_DLL int qsieve_relations_cmp(const void * a, const void * b); FLINT_DLL slong qsieve_merge_relations(qs_t qs_inf); FLINT_DLL void qsieve_write_to_file(qs_t qs_inf, mp_limb_t prime, fmpz_t Y, qs_poly_t poly); FLINT_DLL hash_t * qsieve_get_table_entry(qs_t qs_inf, mp_limb_t prime); FLINT_DLL void qsieve_add_to_hashtable(qs_t qs_inf, mp_limb_t prime); FLINT_DLL relation_t qsieve_parse_relation(qs_t qs_inf, char * str); FLINT_DLL relation_t qsieve_merge_relation(qs_t qs_inf, relation_t a, relation_t b); FLINT_DLL int qsieve_compare_relation(const void * a, const void * b); FLINT_DLL int qsieve_remove_duplicates(relation_t * rel_list, slong num_relations); FLINT_DLL void qsieve_insert_relation(qs_t qs_inf, relation_t * rel_list, slong num_relations); FLINT_DLL 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); } FLINT_DLL uint64_t get_null_entry(uint64_t * nullrows, slong i, slong l); FLINT_DLL void reduce_matrix(qs_t qs_inf, slong *nrows, slong *ncols, la_col_t *cols); FLINT_DLL uint64_t * block_lanczos(flint_rand_t state, slong nrows, slong dense_rows, slong ncols, la_col_t *B); FLINT_DLL 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 flint2-2.8.4/qsieve/000077500000000000000000000000001414523752600142305ustar00rootroot00000000000000flint2-2.8.4/qsieve/block_lanczos.c000066400000000000000000000577201414523752600172320ustar00rootroot00000000000000/* 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 2.1 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 "qsieve.h" #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 passes; slong *counts; slong reduced_rows; slong reduced_cols; /* 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; passes = 0; 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 */ passes++; } 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 inefficent 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, iter; 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); iter = 0; /* 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) { iter++; /* 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_printf("lanczos error: dependencies don't work %wd\n",i); flint_abort(); } flint_free(v[0]); flint_free(v[1]); flint_free(v[2]); return x; } flint2-2.8.4/qsieve/clear.c000066400000000000000000000013001414523752600154540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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); } flint2-2.8.4/qsieve/collect_relations.c000066400000000000000000000375601414523752600201140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "qsieve.h" #include /* 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 printf("res = "); fmpz_print(res); 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); 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) 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; } flint2-2.8.4/qsieve/compute_poly_data.c000066400000000000000000000522621414523752600201130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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 printf("First A_ind = ("); for (i = 0; i < s - 1; i++) printf("%ld, ", A_ind[i]); printf("%ld", A_ind[s - 1]); 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 printf("A_ind = ("); for (i = 0; i < s - 1; i++) printf("%ld, ", A_ind[i]); printf("%ld", A_ind[s - 1]); 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_printf("B^2 - kn not divisible by A\n"); flint_abort(); } #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]; } } flint2-2.8.4/qsieve/factor.c000066400000000000000000000322541414523752600156600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "qsieve.h" #include "fmpz_factor.h" #include "thread_support.h" #include #define _STDC_FORMAT_MACROS #include #include #include #include #if (!defined (__WIN32) || defined(__CYGWIN__)) && !defined(_MSC_VER) #include #endif #if defined (__WIN32) && !defined(__CYGWIN__) #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, relation = 0, num_primes; uint64_t * nullrows = NULL; uint64_t mask; flint_rand_t state; fmpz_t temp, temp2, X, Y; slong num_facs; fmpz * facs; int nchars; 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__) srand((int) GetCurrentProcessId()); #else srand((int) getpid()); #endif nchars = sprintf(qs_inf->fname, "%d", (int) rand()); strcat(qs_inf->fname + nchars, "siqs.dat"); qs_inf->siqs = fopen(qs_inf->fname, "w"); 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 { relation += 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; fclose(qs_inf->siqs); 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 = fopen(qs_inf->fname, "w"); 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 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 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); relation = 0; } /************************************************************************** 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); remove(qs_inf->fname); 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); } flint2-2.8.4/qsieve/init.c000066400000000000000000000025761414523752600153510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "qsieve.h" void qsieve_init(qs_t qs_inf, const fmpz_t n) { slong i; qs_inf->fname = (char *) flint_malloc(20); /* 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; } flint2-2.8.4/qsieve/knuth_schroeppel.c000066400000000000000000000074371414523752600177640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "qsieve.h" /* 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 */ } flint2-2.8.4/qsieve/large_prime_variant.c000066400000000000000000000357721414523752600204240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "qsieve.h" #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 */ void qsieve_write_to_file(qs_t qs_inf, mp_limb_t prime, fmpz_t Y, qs_poly_t poly) { slong i; char * str = NULL; slong num_factors = poly->num_factors; slong * small = poly->small; fac_t * factor = poly->factor; flint_fprintf(qs_inf->siqs, "%X ", prime); /* write large prime */ for (i = 0; i < qs_inf->small_primes; i++) /* write small primes */ flint_fprintf(qs_inf->siqs, "%X ", small[i]); flint_fprintf(qs_inf->siqs, "%X ", num_factors); /* write number of factors */ for (i = 0; i < num_factors; i++) /* write factor along with exponent */ flint_fprintf(qs_inf->siqs, "%wx %X ", factor[i].ind, factor[i].exp); str = fmpz_get_str(str, 16, Y); /* converting value of 'Y' to hex */ flint_fprintf(qs_inf->siqs, "%s\n", str); /* write value of 'Y' */ flint_free(str); } /****************************************************************************** * * 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 neccessary 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, char * str) { slong i; char * next; relation_t rel; rel.lp = UWORD(1); rel.small = flint_malloc(qs_inf->small_primes * sizeof(slong)); rel.factor = flint_malloc(qs_inf->max_factors * sizeof(fac_t)); for (i = 0; i < qs_inf->small_primes; i++) { while (isspace(*str)) str++; rel.small[i] = strtoul(str, &next, 16); str = next; } while (isspace(*str)) str++; rel.num_factors = strtoul(str, &next, 16); rel.small_primes = qs_inf->small_primes; str = next; for (i = 0; i < rel.num_factors; i++) { while (isspace(*str)) str++; rel.factor[i].ind = strtoul(str, &next, 16); str = next; while (isspace(*str)) str++; rel.factor[i].exp = strtoul(str, &next, 16); str = next; } while (isspace(*str)) str++; fmpz_init(rel.Y); fmpz_set_str(rel.Y, str, 16); 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_printf("more than max_factor !!\n"); abort(); } } 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_printf("more than max_factor !!\n"); abort(); } } 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_printf("more than max_factor !!\n"); abort(); } } 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_printf("Inverse doesn't exist !!\n"); abort(); } 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) { char buf[1024]; char * str; slong i, num_relations = 0, num_relations2, full = 0; 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; qs_inf->siqs = fopen(qs_inf->fname, "r"); #if QS_DEBUG & 64 printf("Getting relations\n"); #endif while (fgets(buf, sizeof(buf), qs_inf->siqs) != NULL) { prime = strtoul(buf, &str, 16); 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, str); rel_list[num_relations].lp = prime; num_relations++; } } fclose(qs_inf->siqs); #if QS_DEBUG & 64 printf("Removing duplicates\n"); #endif num_relations = qsieve_remove_duplicates(rel_list, num_relations); rel_list_length = num_relations; #if QS_DEBUG & 64 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]; full++; } 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 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; qs_inf->siqs = fopen(qs_inf->fname, "a"); } 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; } flint2-2.8.4/qsieve/linalg_clear.c000066400000000000000000000023511414523752600170110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "qsieve.h" 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; } flint2-2.8.4/qsieve/linalg_init.c000066400000000000000000000070041414523752600166660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "qsieve.h" /* Initialise linear algebra. */ 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)); } flint2-2.8.4/qsieve/poly_clear.c000066400000000000000000000034771414523752600165400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "qsieve.h" 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; } flint2-2.8.4/qsieve/poly_init.c000066400000000000000000000043511414523752600164050ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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; } flint2-2.8.4/qsieve/primes_init.c000066400000000000000000000117561414523752600167300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #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_printf("Too few factor base primes\n"); flint_abort(); } 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_printf("Too few factor base primes\n"); flint_abort(); } /* 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; } flint2-2.8.4/qsieve/square_root.c000066400000000000000000000036521414523752600167450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "qsieve.h" 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); } flint2-2.8.4/qsieve/test/000077500000000000000000000000001414523752600152075ustar00rootroot00000000000000flint2-2.8.4/qsieve/test/t-factor.c000066400000000000000000000075101414523752600170750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "qsieve.h" #include "thread_support.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); } int main(void) { slong i; fmpz_t n, x, y, z; fmpz_factor_t factors; slong max_threads = 5; slong tmul = 3; FLINT_TEST_INIT(state); #ifdef _WIN32 tmul = 1; #endif fmpz_init(x); fmpz_init(y); fmpz_init(z); fmpz_init(n); flint_printf("factor...."); fflush(stdout); /* 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); 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); 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); 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); abort(); } fmpz_factor_clear(factors); } fmpz_clear(n); fmpz_clear(x); fmpz_clear(y); fmpz_clear(z); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/qsieve/test/t-primes_init.c000066400000000000000000000165071414523752600201470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" #include "qsieve.h" int main(void) { int i; slong j, k; mp_limb_t small_factor, pmod; qs_t qs_inf; fmpz_t n, x, y; FLINT_TEST_INIT(state); flint_printf("primes_init...."); fflush(stdout); 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"); 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); 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); 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"); 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); 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); 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"); 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); 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); 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"); 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); 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); abort(); } } cleanup1: qsieve_clear(qs_inf); cleanup2: fmpz_clear(n); fmpz_clear(x); fmpz_clear(y); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/scanf.c000066400000000000000000000062661414523752600142040ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include #include "flint.h" 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; } flint2-2.8.4/sprintf.c000066400000000000000000000076421414523752600145760ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/sscanf.c000066400000000000000000000071471414523752600143660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/templates.h000066400000000000000000000023621414523752600151060ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 _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 _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 flint2-2.8.4/test/000077500000000000000000000000001414523752600137135ustar00rootroot00000000000000flint2-2.8.4/test/t-add_ssaaaa.c000066400000000000000000000025371414523752600163700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("add_ssaaaa...."); fflush(stdout); for (i = 0; i < 1000000; 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); 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) { flint_printf("FAIL:\n"); flint_printf("ah1 = %wu, al1 = %wu, ah2 = %wu, al1 = %wu\n", ah1, al1, ah2, al1); flint_printf("sh2 = %wu, sh1 = %wu, sl2 = %wu, sl1 = %wu\n", sh2, sh1, sl2, sl1); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-add_sssaaaaaa.c000066400000000000000000000031711414523752600170500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("add_sssaaaaaa...."); fflush(stdout); for (i = 0; i < 1000000; 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) { flint_printf("FAIL:\n"); flint_printf("a[2] = %wu, a[1] = %wu, a[0] = %wu\n", a[2], a[1], a[0]); flint_printf("b[2] = %wu, b[1] = %wu, b[0] = %wu\n", b[2], b[1], b[0]); flint_printf("s[2] = %wu, s[1] = %wu, s[0] = %wu\n", s[2], s[1], s[0]); flint_printf("t[2] = %wu, t[1] = %wu, t[0] = %wu\n", t[2], t[1], t[0]); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-add_ssssaaaaaaaa.c000066400000000000000000000053141414523752600175360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("add_ssssaaaaaaaa...."); fflush(stdout); for (i = 0; i < 1000000; i++) { mp_limb_t s[4], t[4], a[4], b[4]; 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); } 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) { flint_printf("FAIL:\n"); flint_printf("a[3] = %wu, a[2] = %wu, a[1] = %wu, a[0] = %wu\n", a[3], a[2], a[1], a[0]); flint_printf("b[3] = %wu, b[2] = %wu, b[1] = %wu, b[0] = %wu\n", b[3], b[2], b[1], b[0]); flint_printf("s[3] = %wu, s[2] = %wu, s[1] = %wu, s[0] = %wu\n", s[3], s[2], s[1], s[0]); flint_printf("t[3] = %wu, t[2] = %wu, t[1] = %wu, t[0] = %wu\n", t[3], t[2], t[1], t[0]); flint_abort(); } 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); } mpn_add_n(t, s, b, 4); 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]); result = ((s[3] == t[3]) && (s[2] == t[2]) && (s[1] == t[1]) && (s[0] == t[0])); if (!result) { flint_printf("FAIL:\naliasing\n"); flint_printf("a[3] = %wu, a[2] = %wu, a[1] = %wu, a[0] = %wu\n", a[3], a[2], a[1], a[0]); flint_printf("b[3] = %wu, b[2] = %wu, b[1] = %wu, b[0] = %wu\n", b[3], b[2], b[1], b[0]); flint_printf("s[3] = %wu, s[2] = %wu, s[1] = %wu, s[0] = %wu\n", s[3], s[2], s[1], s[0]); flint_printf("t[3] = %wu, t[2] = %wu, t[1] = %wu, t[0] = %wu\n", t[3], t[2], t[1], t[0]); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-byte_swap.c000066400000000000000000000034061414523752600163200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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; } int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("byte_swap...."); fflush(stdout); /* byte_swap(byte_swap(n)) == n */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong n, r1, r2; n = n_randtest(state); r1 = n; r2 = n; byte_swap(r2); byte_swap(r2); result = (r1 == r2); if (!result) { flint_printf("FAIL:\n"); flint_printf("byte_swap(byte_swap(n)) != n\n"); flint_printf("n = %wx, r1 = %wx, r2 = %wx\n", n, r1, r2); flint_abort(); } } /* byte_swap(n) == byte_swap_naive(n) */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong n, r1, r2; n = n_randtest(state); r1 = n; byte_swap(r1); r2 = byte_swap_naive(n); result = (r1 == r2); if (!result) { flint_printf("FAIL:\n"); flint_printf("byte_swap(n) != byte_swap_naive(n)\n"); flint_printf("n = %wx, r1 = %wx, r2 = %wx\n", n, r1, r2); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-count_leading_zeros.c000066400000000000000000000021661414523752600203620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("count_leading_zeros...."); fflush(stdout); for (i = 0; i < 1000000; i++) { mp_limb_t n; unsigned int count = 0; n = n_randtest(state); if (n != 0) count_leading_zeros(count, n); result = ((n == UWORD(0)) || (((slong)(n << count) < WORD(0)) && (r_shift(n, FLINT_BITS-count) == UWORD(0)))); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wu, count = %u\n", n, count); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-count_trailing_zeros.c000066400000000000000000000021611414523752600205630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("count_trailing_zeros...."); fflush(stdout); for (i = 0; i < 1000000; i++) { mp_limb_t n; unsigned int count = 0; n = n_randtest(state); if (n != 0) count_trailing_zeros(count, n); result = ((n == UWORD(0)) || (((n >> count) & UWORD(1)) && (l_shift(n, FLINT_BITS-count) == UWORD(0)))); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wu, count = %u\n", n, count); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-invert_limb.c000066400000000000000000000024661414523752600166420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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) int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("invert_limb...."); fflush(stdout); 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)); invert_limb(ninv1, n); invert_limb_naive(ninv2, n); result = (ninv1 == ninv2); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wx, ninv1 = %wx, ninv2 = %wx\n", n, ninv1, ninv2); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-sdiv_qrnnd.c000066400000000000000000000045021414523752600164700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("sdiv_qrnnd...."); fflush(stdout); for (i = 0; i < 1000000*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 ((FLINT_ABS(nh) >= FLINT_ABS(d)/2) || (nh == WORD_MIN)); 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) { flint_printf("FAIL: check identity\n"); flint_printf("nh = %wd, nl = %wd\n", nh, nl); flint_printf("d = %wd\n", d); flint_printf("q = %wd\n", q); flint_printf("r = %wd\n", r); flint_printf("ph = %wu, pl = %wu\n", ph, pl); flint_abort(); } /* 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))) { flint_printf("FAIL: check remainder\n"); flint_printf("nsgn: %d\n", nsgn); flint_printf("nh = %wd, nl = %wd\n", nh, nl); flint_printf("d = %wd\n", d); flint_printf("q = %wd\n", q); flint_printf("r = %wd\n", r); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-smul_ppmm.c000066400000000000000000000035321414523752600163340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("smul_ppmm...."); fflush(stdout); for (i = 0; i < 1000000; 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) { flint_printf("FAIL:\n"); flint_printf("m1 = %wu, m2 = %wu\n", n1, n2); flint_printf("ph2 = %wu, ph1 = %wu, pl2 = %wu, pl1 = %wu\n", ph2, ph1, pl2, pl1); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-sub_dddmmmsss.c000066400000000000000000000031701414523752600171650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("sub_dddmmmsss...."); fflush(stdout); for (i = 0; i < 1000000; 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) { flint_printf("FAIL:\n"); flint_printf("a[2] = %wu, a[1] = %wu, a[0] = %wu\n", a[2], a[1], a[0]); flint_printf("b[2] = %wu, b[1] = %wu, b[0] = %wu\n", b[2], b[1], b[0]); flint_printf("s[2] = %wu, s[1] = %wu, s[0] = %wu\n", s[2], s[1], s[0]); flint_printf("t[2] = %wu, t[1] = %wu, t[0] = %wu\n", t[2], t[1], t[0]); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-sub_ddmmss.c000066400000000000000000000025071414523752600164640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sub_ddmmss...."); fflush(stdout); for (i = 0; i < 1000000; 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); 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) { flint_printf("FAIL:\n"); flint_printf("mh = %wu, ml = %wu, sh = %wu, sl = %wu\n", mh, ml, sh, sl); flint_printf("dh2 = %wu, dh1 = %wu, dl2 = %wu, dl1 = %wu\n", dh2, dh1, dl2, dl1); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-udiv_qrnnd.c000066400000000000000000000024101414523752600164660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("udiv_qrnnd...."); fflush(stdout); for (i = 0; i < 1000000; 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) { flint_printf("FAIL:\n"); flint_printf("nh = %wu, nl = %wu, d = %wu\n", nh, nl, d); flint_printf("ph = %wu, pl = %wu\n", ph, pl); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-udiv_qrnnd_preinv.c000066400000000000000000000026111414523752600200540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("udiv_qrnnd_preinv...."); fflush(stdout); for (i = 0; i < 1000000; i++) { mp_limb_t d, dinv, nh, nl, q1, r1, q2, r2, norm; do { d = n_randtest_not_zero(state); nh = n_randtest(state); count_leading_zeros(norm, d); d <<= norm; } while (nh >= d); nl = n_randtest(state); invert_limb(dinv, d); udiv_qrnnd_preinv(q1, r1, nh, nl, d, dinv); udiv_qrnnd(q2, r2, nh, nl, d); result = ((q1 == q2) && (r1 == r2)); if (!result) { flint_printf("FAIL:\n"); flint_printf("nh = %wu, nl = %wu, d = %wu, dinv = %wu\n", nh, nl, d, dinv); flint_printf("q1 = %wu, q2 = %wu, r1 = %wu, r2 = %wu\n", q1, q2, r1, r2); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test/t-umul_ppmm.c000066400000000000000000000027741414523752600163450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("umul_ppmm...."); fflush(stdout); for (i = 0; i < 1000000; 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) { flint_printf("FAIL:\n"); flint_printf("m1 = %wu, m2 = %wu\n", m1, m2); flint_printf("ph2 = %wu, ph1 = %wu, pl2 = %wu, pl1 = %wu\n", ph2, ph1, pl2, pl1); flint_abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/test_helpers.c000066400000000000000000000007041414523752600156020ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" int flint_test_multiplier() { return 10; } flint2-2.8.4/thread_pool.h000066400000000000000000000056121414523752600154110ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef THREAD_POOL_H #define THREAD_POOL_H /* for some reason this define needs to be outside of the next if */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #if FLINT_USES_CPUSET #include #endif #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 cpu_set_t 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]; typedef int thread_pool_handle; FLINT_DLL extern thread_pool_t global_thread_pool; FLINT_DLL extern int global_thread_pool_initialized; FLINT_DLL void * thread_pool_idle_loop(void * varg); FLINT_DLL void thread_pool_init(thread_pool_t T, slong l); FLINT_DLL int thread_pool_set_affinity(thread_pool_t T, int * cpus, slong length); FLINT_DLL int thread_pool_restore_affinity(thread_pool_t T); FLINT_DLL slong thread_pool_get_size(thread_pool_t T); FLINT_DLL int thread_pool_set_size(thread_pool_t T, slong new_size); FLINT_DLL slong thread_pool_request(thread_pool_t T, thread_pool_handle * out, slong requested); FLINT_DLL void thread_pool_wake(thread_pool_t T, thread_pool_handle i, int max_workers, void (*f)(void*), void * a); FLINT_DLL void thread_pool_wait(thread_pool_t T, thread_pool_handle i); FLINT_DLL void thread_pool_give_back(thread_pool_t T, thread_pool_handle i); FLINT_DLL void thread_pool_clear(thread_pool_t T); /* misc internal helpers *****************************************************/ FLINT_DLL void _thread_pool_distribute_work_2(slong start, slong stop, slong * Astart, slong * Astop, slong Alen, slong * Bstart, slong * Bstop, slong Blen); FLINT_DLL ulong _thread_pool_find_work_2(ulong a, ulong alpha, ulong b, ulong beta, ulong yn, ulong yd); #ifdef __cplusplus } #endif #endif flint2-2.8.4/thread_pool/000077500000000000000000000000001414523752600152345ustar00rootroot00000000000000flint2-2.8.4/thread_pool/clear.c000066400000000000000000000024441414523752600164720ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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_PTHREAD pthread_mutex_unlock(&T->mutex); pthread_mutex_destroy(&T->mutex); #endif T->length = -1; T->tdata = NULL; } flint2-2.8.4/thread_pool/distribute_work.c000066400000000000000000000025771414523752600206330ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 explaination. */ 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; } } flint2-2.8.4/thread_pool/find_work.c000066400000000000000000000016451414523752600173700ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/thread_pool/get_size.c000066400000000000000000000012011414523752600172030ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/thread_pool/give_back.c000066400000000000000000000016631414523752600173200ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 } flint2-2.8.4/thread_pool/init.c000066400000000000000000000051461414523752600163510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" 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 if (0 != pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &T->original_affinity)) { CPU_ZERO(&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 } } flint2-2.8.4/thread_pool/request.c000066400000000000000000000021711414523752600170710ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/thread_pool/restore_affinity.c000066400000000000000000000021721414523752600207560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" 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), &T->original_affinity); if (errorno != 0) return errorno; } /* restore affinity for main thread */ errorno = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &T->original_affinity); if (errorno != 0) return errorno; #endif return 0; } flint2-2.8.4/thread_pool/set_affinity.c000066400000000000000000000025121414523752600200640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "thread_pool.h" /* 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; } flint2-2.8.4/thread_pool/set_size.c000066400000000000000000000046751414523752600172410ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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; } flint2-2.8.4/thread_pool/test/000077500000000000000000000000001414523752600162135ustar00rootroot00000000000000flint2-2.8.4/thread_pool/test/t-thread_pool.c000066400000000000000000000126321414523752600211240ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #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); } int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("thread_pool...."); fflush(stdout); 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)) { flint_printf("n: %wu\n", n); printf("x: "); fmpz_print(x); printf("\n"); printf("y: "); fmpz_print(y); printf("\n"); printf("test1 failed\n"); flint_abort(); } test2(x, n); if (!fmpz_equal(x, y)) { flint_printf("n: %wu\n", n); printf("x: "); fmpz_print(x); printf("\n"); printf("y: "); fmpz_print(y); printf("\n"); printf("test2 failed\n"); flint_abort(); } } fmpz_clear(y); fmpz_clear(x); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/thread_pool/wait.c000066400000000000000000000015231414523752600163450ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 } flint2-2.8.4/thread_pool/wake.c000066400000000000000000000021371414523752600163320ustar00rootroot00000000000000/* Copyright (C) 2018 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 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 } flint2-2.8.4/thread_support.c000066400000000000000000000062061414523752600161470ustar00rootroot00000000000000/* Copyright (C) 2013 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 2.1 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() { 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() { if (!global_thread_pool_initialized) return 1; return thread_pool_restore_affinity(global_thread_pool); } 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); } flint2-2.8.4/thread_support.h000066400000000000000000000016011414523752600161460ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef THREAD_SUPPORT_H #define THREAD_SUPPORT_H #include "flint.h" #include "thread_pool.h" #ifdef __cplusplus extern "C" { #endif #define FLINT_DEFAULT_THREAD_LIMIT 99999 FLINT_DLL slong flint_request_threads(thread_pool_handle ** handles, slong thread_limit); FLINT_DLL void flint_give_back_threads(thread_pool_handle * handles, slong num_handles); #ifdef __cplusplus } #endif #endif flint2-2.8.4/todo.txt000066400000000000000000000305041414523752600144440ustar00rootroot00000000000000TODO ==== general ------- * Write a flint2 memory manager, both reentrant and non-reentrant stack based versions fmpz ---- * [maybe] Improve the functions fmpz_get_str and fmpz_set_str * [maybe] figure out how to write robust test code for fmpz_read (which reads from stdin), perhaps using a pipe * Inline or create inline versions of core fmpz functions. * [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_gcd and z_invert in fmpz_gcd and fmpz_invert, respectively fmpz_vec -------- * add a cache of mpfr's which can be used as temporaries for functions like _mpfr_vec_scalar_product * test code for ulong_extras/revbin.c * add test code for numerous mpfr_vec functions and mpfr_poly_mul_classical * make use of mpfr type througout LLL, mpfr_vec and mpfr_mat modules fmpz_factor ----------- * Add primality testing, perfect power testing, fast factorisation (QS, ...) * 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). * Add asymptotically fast resultants? * 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 superceded now and can be removed. It is not used anywhere. flint2-2.8.4/ulong_extras.h000066400000000000000000000346471414523752600156350ustar00rootroot00000000000000/* Copyright (C) 2006, 2007, 2008, 2009, 2016 William Hart Copyright (C) 2008, Peter Shrimpton Copyright (C) 2009, Tom Boothby 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 2.1 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 FLINT_DLL #else #define ULONG_EXTRAS_INLINE static __inline__ #endif #include #include "flint.h" #ifdef __cplusplus extern "C" { #endif typedef struct pair_s { ulong x, y; } n_pair_t; #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; #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_FACTOR_TRIAL_PRIMES 3000 /* nth_prime(FLINT_FACTOR_TRIAL_PRIMES) */ #define FLINT_FACTOR_TRIAL_PRIMES_PRIME UWORD(27449) #define FLINT_FACTOR_TRIAL_CUTOFF (UWORD(27449) * UWORD(27449)) #define FLINT_PRIMES_TAB_DEFAULT_CUTOFF 1000000 #define FLINT_FACTOR_SQUFOF_ITERS 50000 #define FLINT_FACTOR_ONE_LINE_MAX (UWORD(1)<<39) #define FLINT_FACTOR_ONE_LINE_ITERS 40000 #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 #define UWORD_HALF (UWORD_MAX / 2 + 1) 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]; FLINT_DLL void n_primes_init(n_primes_t iter); FLINT_DLL void n_primes_clear(n_primes_t iter); FLINT_DLL void n_primes_extend_small(n_primes_t iter, ulong bound); FLINT_DLL void n_primes_sieve_range(n_primes_t iter, ulong a, ulong b); FLINT_DLL void n_primes_jump_after(n_primes_t iter, ulong n); ULONG_EXTRAS_INLINE 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_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; FLINT_DLL void n_compute_primes(ulong num_primes); FLINT_DLL void n_cleanup_primes(void); FLINT_DLL const ulong * n_primes_arr_readonly(ulong n); FLINT_DLL const double * n_prime_inverses_arr_readonly(ulong n); /* 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; } /*****************************************************************************/ FLINT_DLL ulong n_randlimb(flint_rand_t state); FLINT_DLL ulong n_randint(flint_rand_t state, ulong limit); FLINT_DLL ulong n_urandint(flint_rand_t state, ulong limit); FLINT_DLL ulong n_randbits(flint_rand_t state, unsigned int bits); FLINT_DLL ulong n_randtest_bits(flint_rand_t state, int bits); FLINT_DLL ulong n_randtest(flint_rand_t state); FLINT_DLL ulong n_randtest_not_zero(flint_rand_t state); FLINT_DLL ulong n_randprime(flint_rand_t state, ulong bits, int proved); FLINT_DLL ulong n_randtest_prime(flint_rand_t state, int proved); FLINT_DLL ulong n_pow(ulong n, ulong exp); FLINT_DLL ulong n_flog(ulong n, ulong b); FLINT_DLL ulong n_clog(ulong n, ulong b); FLINT_DLL ulong n_clog_2exp(ulong n, ulong b); ULONG_EXTRAS_INLINE double n_precompute_inverse(ulong n) { return (double) 1 / (double) n; } ULONG_EXTRAS_INLINE ulong n_preinvert_limb(ulong n) { ulong norm, ninv; count_leading_zeros(norm, n); invert_limb(ninv, n << norm); return ninv; } FLINT_DLL ulong n_mod_precomp(ulong a, ulong n, double ninv); FLINT_DLL ulong n_mod2_precomp(ulong a, ulong n, double ninv); FLINT_DLL ulong n_divrem2_precomp(ulong * q, ulong a, ulong n, double npre); FLINT_DLL ulong n_divrem2_preinv(ulong * q, ulong a, ulong n, ulong ninv); FLINT_DLL ulong n_div2_preinv(ulong a, ulong n, ulong ninv); FLINT_DLL ulong n_mod2_preinv(ulong a, ulong n, ulong ninv); FLINT_DLL ulong n_ll_mod_preinv(ulong a_hi, ulong a_lo, ulong n, ulong ninv); FLINT_DLL ulong n_lll_mod_preinv(ulong a_hi, ulong a_mi, ulong a_lo, ulong n, ulong ninv); FLINT_DLL ulong n_mulmod_precomp(ulong a, ulong b, ulong n, double ninv); 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); } FLINT_DLL ulong n_mulmod_preinv(ulong a, ulong b, ulong n, ulong ninv, ulong norm); FLINT_DLL ulong n_powmod_ui_precomp(ulong a, ulong exp, ulong n, double npre); FLINT_DLL 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); } /* This function is in fmpz.h FLINT_DLL ulong n_powmod2_fmpz_preinv(ulong a, const fmpz_t exp, ulong n, ulong ninv); */ FLINT_DLL ulong n_powmod2_preinv(ulong a, slong exp, ulong n, ulong ninv); FLINT_DLL ulong n_powmod2_ui_preinv(ulong a, ulong exp, ulong n, ulong ninv); FLINT_DLL ulong n_powmod_ui_preinv(ulong a, ulong exp, ulong n, ulong ninv, ulong norm); 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); } FLINT_DLL ulong n_sqrtmod(ulong a, ulong p); FLINT_DLL slong n_sqrtmod_2pow(ulong ** sqrt, ulong a, slong exp); FLINT_DLL slong n_sqrtmod_primepow(ulong ** sqrt, ulong a, ulong p, slong exp); FLINT_DLL slong n_sqrtmodn(ulong ** sqrt, ulong a, n_factor_t * fac); FLINT_DLL ulong n_gcd(ulong x, ulong y); #define n_gcd_full n_gcd FLINT_DLL ulong n_xgcd(ulong * a, ulong * b, ulong x, ulong y); FLINT_DLL ulong n_gcdinv(ulong * a, ulong x, ulong y); 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, g/y); return r; } FLINT_DLL ulong n_CRT(ulong r1, ulong m1, ulong r2, ulong m2); FLINT_DLL ulong n_revbin(ulong in, ulong bits); FLINT_DLL int n_jacobi(slong x, ulong y); FLINT_DLL int n_jacobi_unsigned(ulong x, ulong y); FLINT_DLL int _n_jacobi_unsigned(ulong x, ulong y, unsigned int r); FLINT_DLL ulong n_sqrt(ulong a); FLINT_DLL ulong n_sqrtrem(ulong * r, ulong a); FLINT_DLL int n_is_square(ulong x); FLINT_DLL double n_cbrt_estimate(double a); FLINT_DLL ulong n_cbrt(ulong a); FLINT_DLL ulong n_cbrt_binary_search(ulong x); FLINT_DLL ulong n_cbrt_newton_iteration(ulong n); FLINT_DLL ulong n_cbrt_chebyshev_approx(ulong n); FLINT_DLL ulong n_cbrtrem(ulong* remainder, ulong n); FLINT_DLL int n_is_perfect_power235(ulong n); FLINT_DLL int n_is_perfect_power(ulong * root, ulong n); FLINT_DLL int n_divides(mp_limb_t * q, mp_limb_t n, mp_limb_t p); FLINT_DLL int n_is_oddprime_small(ulong n); FLINT_DLL int n_is_oddprime_binary(ulong n); FLINT_DLL int n_is_probabprime_fermat(ulong n, ulong i); FLINT_DLL int n_is_probabprime_fibonacci(ulong n); FLINT_DLL int n_is_probabprime_lucas(ulong n); FLINT_DLL int n_is_probabprime_BPSW(ulong n); FLINT_DLL int n_is_strong_probabprime_precomp(ulong n, double npre, ulong a, ulong d); FLINT_DLL int n_is_strong_probabprime2_preinv(ulong n, ulong ninv, ulong a, ulong d); FLINT_DLL int n_is_probabprime(ulong n); FLINT_DLL int n_is_prime_pseudosquare(ulong n); FLINT_DLL int n_is_prime_pocklington(ulong n, ulong iterations); FLINT_DLL int n_is_prime(ulong n); FLINT_DLL ulong n_nth_prime(ulong n); FLINT_DLL void n_nth_prime_bounds(ulong *lo, ulong *hi, ulong n); FLINT_DLL ulong n_prime_pi(ulong n); FLINT_DLL void n_prime_pi_bounds(ulong *lo, ulong *hi, ulong n); FLINT_DLL int n_remove(ulong * n, ulong p); FLINT_DLL int n_remove2_precomp(ulong * n, ulong p, double ppre); ULONG_EXTRAS_INLINE void n_factor_init(n_factor_t * factors) { factors->num = UWORD(0); } FLINT_DLL void n_factor_insert(n_factor_t * factors, ulong p, ulong exp); FLINT_DLL ulong n_factor_trial_range(n_factor_t * factors, ulong n, ulong start, ulong num_primes); FLINT_DLL ulong n_factor_trial_partial(n_factor_t * factors, ulong n, ulong * prod, ulong num_primes, ulong limit); FLINT_DLL ulong n_factor_trial(n_factor_t * factors, ulong n, ulong num_primes); FLINT_DLL ulong n_factor_partial(n_factor_t * factors, ulong n, ulong limit, int proved); FLINT_DLL ulong n_factor_power235(ulong *exp, ulong n); FLINT_DLL ulong n_factor_one_line(ulong n, ulong iters); FLINT_DLL ulong n_factor_lehman(ulong n); FLINT_DLL ulong n_factor_SQUFOF(ulong n, ulong iters); FLINT_DLL void n_factor(n_factor_t * factors, ulong n, int proved); FLINT_DLL ulong n_factor_pp1(ulong n, ulong B1, ulong c); FLINT_DLL ulong n_factor_pp1_wrapper(ulong n); FLINT_DLL void n_factor_pp1_table_insert(slong bits, slong B1, slong count); FLINT_DLL int n_factor_pollard_brent_single(ulong *factor, ulong n, ulong ninv, ulong ai, ulong xi, ulong normbits, ulong max_iters); FLINT_DLL int n_factor_pollard_brent(ulong *factor, flint_rand_t state, ulong n_in, ulong max_tries, ulong max_iters); FLINT_DLL int n_is_squarefree(ulong n); FLINT_DLL int n_moebius_mu(ulong n); FLINT_DLL void n_moebius_mu_vec(int * mu, ulong len); FLINT_DLL ulong n_euler_phi(ulong n); FLINT_DLL int n_sizeinbase(ulong n, int base); FLINT_DLL ulong n_nextprime(ulong n, int proved); FLINT_DLL ulong n_factorial_mod2_preinv(ulong n, ulong p, ulong pinv); FLINT_DLL ulong n_factorial_fast_mod2_preinv(ulong n, ulong p, ulong pinv); FLINT_DLL ulong n_primitive_root_prime_prefactor(ulong p, n_factor_t * factors); FLINT_DLL ulong n_primitive_root_prime(ulong p); FLINT_DLL ulong n_discrete_log_bsgs(ulong b, ulong a, ulong n); FLINT_DLL ulong n_root_estimate(double a, int n); FLINT_DLL ulong n_rootrem(ulong* remainder, ulong n, ulong root); FLINT_DLL ulong n_root(ulong n, ulong root); /***** ECM functions *********************************************************/ typedef struct n_ecm_s { 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]; FLINT_DLL void n_factor_ecm_double(ulong *x, ulong *z, ulong x0, ulong z0, ulong n, n_ecm_t n_ecm_inf); FLINT_DLL 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); FLINT_DLL 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); FLINT_DLL int n_factor_ecm_select_curve(ulong *f, ulong sig, ulong n, n_ecm_t n_ecm_inf); FLINT_DLL int n_factor_ecm_stage_I(ulong *f, const ulong *prime_array, ulong num, ulong B1, ulong n, n_ecm_t n_ecm_inf); FLINT_DLL int n_factor_ecm_stage_II(ulong *f, ulong B1, ulong B2, ulong P, ulong n, n_ecm_t n_ecm_inf); FLINT_DLL int n_factor_ecm(ulong *f, ulong curves, ulong B1, ulong B2, flint_rand_t state, ulong n); FLINT_DLL 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; r = w * t; r -= q * p; if (r >= p) { r -= p; } return r; } #ifdef __cplusplus } #endif #endif flint2-2.8.4/ulong_extras/000077500000000000000000000000001414523752600154465ustar00rootroot00000000000000flint2-2.8.4/ulong_extras/CRT.c000066400000000000000000000020521414523752600162410ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #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; } flint2-2.8.4/ulong_extras/cbrt.c000066400000000000000000000040451414523752600165470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include "flint.h" #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; bits = FLINT_BIT_COUNT(n); if (bits > 46) /* for larger numbers chebyshev approximation method is faster */ return n_cbrt_chebyshev_approx(n); /* 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 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) { 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; } flint2-2.8.4/ulong_extras/cbrt_binary_search.c000066400000000000000000000025641414523752600214440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include "flint.h" #include "ulong_extras.h" 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; } flint2-2.8.4/ulong_extras/cbrt_chebyshev_approximation.c000066400000000000000000000134621414523752600235640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include "flint.h" #include "ulong_extras.h" /* 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" - http://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; } flint2-2.8.4/ulong_extras/cbrt_estimate.c000066400000000000000000000025061414523752600204420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include "flint.h" #include "ulong_extras.h" #include "longlong.h" 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; } flint2-2.8.4/ulong_extras/cbrt_newton_iteration.c000066400000000000000000000036411414523752600222200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include "flint.h" #include "ulong_extras.h" 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; } flint2-2.8.4/ulong_extras/cbrtrem.c000066400000000000000000000015141414523752600172510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include "flint.h" #include "ulong_extras.h" 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; } flint2-2.8.4/ulong_extras/cleanup_primes.c000066400000000000000000000013741414523752600206250ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" void n_cleanup_primes() { 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; } flint2-2.8.4/ulong_extras/clog.c000066400000000000000000000014131414523752600165350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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); } } flint2-2.8.4/ulong_extras/clog_2exp.c000066400000000000000000000034261414523752600175010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" /* 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; } flint2-2.8.4/ulong_extras/compute_primes.c000066400000000000000000000061531414523752600206520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #include #undef ulong #include #define ulong mp_limb_t #include "flint.h" #include "ulong_extras.h" #if FLINT_REENTRANT && !FLINT_USES_TLS #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 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 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 pthread_mutex_unlock(&primes_lock); #endif } flint2-2.8.4/ulong_extras/discrete_log_bsgs.c000066400000000000000000000043071414523752600212770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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 */ 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); } 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_printf("Exception (n_discrete_log_bsgs). discrete log not found.\n"); flint_abort(); return 0; /* not reached, but silence the compiler */ } 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; } flint2-2.8.4/ulong_extras/div2_preinv.c000066400000000000000000000021561414523752600200450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); count_leading_zeros(norm, 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; } } flint2-2.8.4/ulong_extras/divides.c000066400000000000000000000014021414523752600172360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } } flint2-2.8.4/ulong_extras/divrem2_precomp.c000066400000000000000000000026761414523752600207220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } } flint2-2.8.4/ulong_extras/divrem2_preinv.c000066400000000000000000000023161414523752600205470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); count_leading_zeros(norm, 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; } } flint2-2.8.4/ulong_extras/euler_phi.c000066400000000000000000000013431414523752600175670ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/ulong_extras/factor.c000066400000000000000000000050101414523752600170640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #define ulong mp_limb_t #include #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; 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_printf("Exception (n_factor). Failed to factor %wd.\n", n); flint_abort(); } } 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--; } } } flint2-2.8.4/ulong_extras/factor_SQUFOF.c000066400000000000000000000067661414523752600201720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; count_leading_zeros(norm, 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; } flint2-2.8.4/ulong_extras/factor_ecm.c000066400000000000000000000110711414523752600177140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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; count_leading_zeros(n_ecm_inf->normbits, 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; } flint2-2.8.4/ulong_extras/factor_ecm_add.c000066400000000000000000000042511414523752600205260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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 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); } flint2-2.8.4/ulong_extras/factor_ecm_double.c000066400000000000000000000025471414523752600212560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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 */ /* 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); } flint2-2.8.4/ulong_extras/factor_ecm_mul_montgomery_ladder.c000066400000000000000000000034011414523752600243620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" /* 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; } flint2-2.8.4/ulong_extras/factor_ecm_select_curve.c000066400000000000000000000057351414523752600224710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" 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; 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 = w - (UWORD(5) << n_ecm_inf->normbits); /* 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) return 0; else if (*f > n_ecm_inf->one) return 1; 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; TMP_END; return 0; } flint2-2.8.4/ulong_extras/factor_ecm_stage_I.c000066400000000000000000000023131414523752600213460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" 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; } flint2-2.8.4/ulong_extras/factor_ecm_stage_II.c000066400000000000000000000060411414523752600214610ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "nmod_vec.h" #include "ulong_extras.h" 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 Differnce 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; } flint2-2.8.4/ulong_extras/factor_insert.c000066400000000000000000000014111414523752600204510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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++; } } flint2-2.8.4/ulong_extras/factor_lehman.c000066400000000000000000000033531414523752600204200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #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; } flint2-2.8.4/ulong_extras/factor_one_line.c000066400000000000000000000022741414523752600207450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/ulong_extras/factor_partial.c000066400000000000000000000052501414523752600206060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* prevent clash with standard library */ #include #include #undef ulong #include #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_printf("Error (n_factor_partial). Failed to factor %wd.\n", n); flint_abort(); } } 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; } flint2-2.8.4/ulong_extras/factor_pollard_brent.c000066400000000000000000000072411414523752600220030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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 comparisions */ 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 */ count_leading_zeros(normbits, 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; } flint2-2.8.4/ulong_extras/factor_power235.c000066400000000000000000000041121414523752600205340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with standard libraries */ #include #undef ulong #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); } flint2-2.8.4/ulong_extras/factor_pp1.c000066400000000000000000000136601414523752600176560ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* prevent clash with stdlib */ #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" /* bits of n, B1, count */ static slong n_factor_pp1_table[][3] = { {31, 2784, 5}, {32, 1208, 2}, {33, 2924, 3}, {34, 286, 5}, {35, 58, 5}, {36, 61, 4}, {37, 815, 2}, {38, 944, 2}, {39, 61, 3}, {40, 0, 0}, {41, 0, 0}, {42, 0, 0}, {43, 0, 0}, {44, 0, 0}, {45, 0, 0}, {46, 0, 0}, {47, 0, 0}, {47, 0, 0}, {49, 0, 0}, {50, 606, 1}, {51, 2403, 1}, {52, 2524, 1}, {53, 2924, 1}, {54, 3735, 2}, {55, 669, 2}, {56, 6092, 3}, {57, 2179, 3}, {58, 3922, 3}, {59, 6717, 4}, {60, 4119, 4}, {61, 2288, 4}, {62, 9004, 3}, {63, 9004, 3}, {64, 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) 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); } #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); count_leading_zeros(norm, 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][1]; count = n_factor_pp1_table[bits - 31][2]; 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; } /* exists only for tuning/profiling */ void n_factor_pp1_table_insert(slong bits, slong B1, slong count) { n_factor_pp1_table[bits][1] = B1; n_factor_pp1_table[bits][2] = count; } flint2-2.8.4/ulong_extras/factor_trial.c000066400000000000000000000011201414523752600202550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/ulong_extras/factor_trial_partial.c000066400000000000000000000021651414523752600220030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" 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; } flint2-2.8.4/ulong_extras/factor_trial_range.c000066400000000000000000000017611414523752600214440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" 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; } flint2-2.8.4/ulong_extras/factorial_fast_mod2_preinv.c000066400000000000000000000026571414523752600231110ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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; } flint2-2.8.4/ulong_extras/factorial_mod2_preinv.c000066400000000000000000000033421414523752600220640ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/ulong_extras/flog.c000066400000000000000000000013261414523752600165430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } } flint2-2.8.4/ulong_extras/gcd.c000066400000000000000000000044341414523752600163540ustar00rootroot00000000000000/* Copyright (C) 2009, 2015 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #if (defined (__amd64__) || defined (__i386__) || defined (__i486__)) ulong n_gcd(ulong x, ulong y) { register ulong s0, s1, f; if (x == 0) return y; if (y == 0) return x; count_trailing_zeros(s0, x); count_trailing_zeros(s1, y); f = FLINT_MIN(s0, s1); x >>= s0; y >>= s1; while (x != y) { if (x < y) { y -= x; count_trailing_zeros(s1, y); y >>= s1; } else { x -= y; count_trailing_zeros(s0, x); x >>= s0; } } return x << f; } #else ulong n_gcd(ulong x, ulong y) { ulong d, v, quot, rem; if (x >= y) v = y; else { v = x; x = y; } /* x and y both have top bit set */ if ((slong) (x & v) < WORD(0)) { d = x - v; x = v; v = d; } /* second value has second msb set */ while ((slong) (v << 1) < WORD(0)) { d = x - v; x = v; if (d < v) v = d; /* quot = 1 */ else if (d < (v << 1)) v = d - x; /* quot = 2 */ else v = d - (x << 1); /* quot = 3 */ } while (v) { /* overflow not possible due to top 2 bits of v not being set */ if (x < (v << 2)) /* avoid divisions when quotient < 4 */ { d = x - v; x = v; if (d < v) v = d; /* quot = 1 */ else if (d < (v << 1)) v = d - x; /* quot = 2 */ else v = d - (x << 1); /* quot = 3 */ } else { quot = x / v; rem = x - v * quot; x = v; v = rem; } } return x; } #endif flint2-2.8.4/ulong_extras/gcdinv.c000066400000000000000000000050011414523752600170600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/ulong_extras/inlines.c000066400000000000000000000010701414523752600172510ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ULONG_EXTRAS_INLINES_C #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" flint2-2.8.4/ulong_extras/is_oddprime_binary.c000066400000000000000000000023211414523752600214520ustar00rootroot00000000000000/* Copyright (C) 2009 Thomas 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" 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]); } flint2-2.8.4/ulong_extras/is_oddprime_small.c000066400000000000000000000055561414523752600213130ustar00rootroot00000000000000/* Copyright (C) 2009 Tom 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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; } flint2-2.8.4/ulong_extras/is_perfect_power.c000066400000000000000000000125231414523752600211540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #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_trailing_zeros(count, 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; } flint2-2.8.4/ulong_extras/is_perfect_power235.c000066400000000000000000000037631414523752600214140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #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; } flint2-2.8.4/ulong_extras/is_prime.c000066400000000000000000000030671414523752600174270ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart Copyright (C) 2014, 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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); } flint2-2.8.4/ulong_extras/is_prime_pocklington.c000066400000000000000000000063321414523752600220340ustar00rootroot00000000000000/* Copyright (C) 2008 Peter Shrimpton Copyright (C) 2009 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #define ulong mp_limb_t #include "flint.h" #include "ulong_extras.h" 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; 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; } if (c == 0) return 0; } if (j == iterations) return -1; } return (n_gcd(n, c) == UWORD(1)); } flint2-2.8.4/ulong_extras/is_prime_pseudosquare.c000066400000000000000000000066451414523752600222340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #include "ulong_extras.h" 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; 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; if (mod == n - 1) m1 = 1; } mod8 = n % 8; if ((mod8 == 3) || (mod8 == 7)) return 1; if (mod8 == 5) { mp_limb_t mod = n_powmod2(UWORD(2), exp, n); if (mod == n - 1) return 1; flint_printf("Whoah, %wu is a probable prime, but not prime, please report!!\n", n); flint_abort(); } 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; if (mod != 1) { flint_printf("Whoah, %wu is a probable prime, but not prime, please report!!\n", n); flint_abort(); } } flint_printf("Whoah, %wu is a probable prime, but not prime, please report!!\n", n); flint_abort(); } return 0; /* not reached, but silence the compiler */ } flint2-2.8.4/ulong_extras/is_probabprime.c000066400000000000000000000054541414523752600206170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" /* 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; count_trailing_zeros(norm, 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; } flint2-2.8.4/ulong_extras/is_probabprime_BPSW.c000066400000000000000000000026441414523752600214500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" 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); } } flint2-2.8.4/ulong_extras/is_probabprime_fermat.c000066400000000000000000000013271414523752600221500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" 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); } flint2-2.8.4/ulong_extras/is_probabprime_fibonacci.c000066400000000000000000000056221414523752600226110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" 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)); } } flint2-2.8.4/ulong_extras/is_probabprime_lucas.c000066400000000000000000000072731414523752600220070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" 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); } flint2-2.8.4/ulong_extras/is_square.c000066400000000000000000000025271414523752600176130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #define ulong mp_limb_t #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); } flint2-2.8.4/ulong_extras/is_squarefree.c000066400000000000000000000007651414523752600204570ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/ulong_extras/is_strong_probabprime2_preinv.c000066400000000000000000000020641414523752600236520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #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; /* Map large base to range 2 ... n - 1 */ if (a >= n) a = n_mod2_preinv(a, n, ninv); 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); } flint2-2.8.4/ulong_extras/is_strong_probabprime_precomp.c000066400000000000000000000020571414523752600237340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/ulong_extras/jacobi.c000066400000000000000000000025151414523752600170440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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 */ count_trailing_zeros(e, 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); } flint2-2.8.4/ulong_extras/ll_mod_preinv.c000066400000000000000000000031251414523752600204440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); count_leading_zeros(norm, 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); } } flint2-2.8.4/ulong_extras/lll_mod_preinv.c000066400000000000000000000031301414523752600206140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; count_leading_zeros(norm, 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); } } flint2-2.8.4/ulong_extras/mod2_precomp.c000066400000000000000000000023051414523752600202000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/ulong_extras/mod2_preinv.c000066400000000000000000000021241414523752600200350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); count_leading_zeros(norm, 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); } } flint2-2.8.4/ulong_extras/mod_precomp.c000066400000000000000000000013431414523752600201170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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))); } flint2-2.8.4/ulong_extras/moebius_mu.c000066400000000000000000000055011414523752600177570ustar00rootroot00000000000000/* 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 2.1 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; } flint2-2.8.4/ulong_extras/mulmod_precomp.c000066400000000000000000000014371414523752600206410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/ulong_extras/mulmod_precomp_shoup.c000066400000000000000000000012441414523752600220530ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/ulong_extras/mulmod_preinv.c000066400000000000000000000020641414523752600204740ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/ulong_extras/nextprime.c000066400000000000000000000056331414523752600176340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #define ulong mp_limb_t #include #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_printf("Exception (n_nextprime). No larger single-limb prime exists.\n"); flint_abort(); } index = n % 30; do { n += nextmod30[index]; index = nextindex[index]; } while (!n_is_prime(n)); return n; } flint2-2.8.4/ulong_extras/nth_prime.c000066400000000000000000000014121414523752600175750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #define ulong mp_limb_t #include "flint.h" #include "ulong_extras.h" mp_limb_t n_nth_prime(ulong n) { if (n == 0) { flint_printf("Exception (n_nth_prime). n_nth_prime(0) is undefined.\n"); flint_abort(); } return n_primes_arr_readonly(n)[n-1]; } flint2-2.8.4/ulong_extras/nth_prime_bounds.c000066400000000000000000000017361414523752600211600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" 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))); } flint2-2.8.4/ulong_extras/pow.c000066400000000000000000000012001414523752600164100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" mp_limb_t n_pow(mp_limb_t n, ulong exp) { ulong i; mp_limb_t res; res = UWORD(1); for (i = 0; i < exp; i++) res *= n; return res; } flint2-2.8.4/ulong_extras/powmod2_preinv.c000066400000000000000000000016711414523752600205710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } count_leading_zeros(norm, n); return n_powmod_ui_preinv(a << norm, exp, n << norm, ninv, norm) >> norm; } flint2-2.8.4/ulong_extras/powmod2_ui_preinv.c000066400000000000000000000021561414523752600212650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); count_leading_zeros(norm, 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; } flint2-2.8.4/ulong_extras/powmod_precomp.c000066400000000000000000000020361414523752600206450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/ulong_extras/powmod_ui_preinv.c000066400000000000000000000023121414523752600211750ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/ulong_extras/prime_inverses_arr_readonly.c000066400000000000000000000013401414523752600234030ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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]; } flint2-2.8.4/ulong_extras/prime_pi.c000066400000000000000000000027211414523752600174200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/ulong_extras/prime_pi_bounds.c000066400000000000000000000017261414523752600207760ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" 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; } } flint2-2.8.4/ulong_extras/primes_arr_readonly.c000066400000000000000000000013231414523752600216510ustar00rootroot00000000000000/* Copyright (C) 2013 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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]; } flint2-2.8.4/ulong_extras/primes_clear.c000066400000000000000000000011621414523752600202570ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } flint2-2.8.4/ulong_extras/primes_extend_small.c000066400000000000000000000022111414523752600216440ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; } } flint2-2.8.4/ulong_extras/primes_init.c000066400000000000000000000013221414523752600201320ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/ulong_extras/primes_jump_after.c000066400000000000000000000014611414523752600213270ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/ulong_extras/primes_sieve_range.c000066400000000000000000000035161414523752600214650ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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_printf("invalid sieve range %wu,%wu!\n", a, b); flint_abort(); } 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; } flint2-2.8.4/ulong_extras/primitive_root_prime.c000066400000000000000000000027111414523752600220620ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #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_printf("Exception (n_primitive_root_prime_prefactor). root not found.\n"); flint_abort(); return 0; /* cannot happen, but silence the compiler */ } 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; } flint2-2.8.4/ulong_extras/profile/000077500000000000000000000000001414523752600171065ustar00rootroot00000000000000flint2-2.8.4/ulong_extras/profile/p-factor.c000066400000000000000000000043031414523752600207650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; flint_bitcnt_t bits = params->bits; ulong i, j, res, primes = (WORD(1)<<(bits/3))/10 + 1; n_factor_t factors; 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; FLINT_TEST_INIT(state); int i; 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; } flint2-2.8.4/ulong_extras/profile/p-factor_pp1.c000066400000000000000000000033561414523752600215540ustar00rootroot00000000000000#include "flint.h" #include "ulong_extras.h" #include "profiler.h" #define cpumin 2 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; } flint2-2.8.4/ulong_extras/profile/p-gcd.c000066400000000000000000000032651414523752600202520ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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; FLINT_TEST_INIT(state); int i; 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; } flint2-2.8.4/ulong_extras/profile/p-is_probabprime_BPSW.c000066400000000000000000000027141414523752600233430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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 n, d, r, norm; double dpre; 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; } flint2-2.8.4/ulong_extras/profile/p-lll_mod_preinv.c000066400000000000000000000037001414523752600225140ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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 n, d, dinv, r = 0, norm; double dpre; info_t * info = (info_t *) arg; flint_bitcnt_t bits = info->bits; ulong type = info->type; ulong i; FLINT_TEST_INIT(state); mp_ptr arr = (mp_ptr) flint_malloc(1024*sizeof(mp_limb_t)); mp_ptr 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, n); } switch (type) { case 1: prof_start(); for (mp_size_t 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)) abort(); flint_randclear(state); flint_free(arr); flint_free(arr2); } int main(void) { double min1, min2, min3, min4, min5, 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; } flint2-2.8.4/ulong_extras/profile/p-mod2_precomp.c000066400000000000000000000026341414523752600221020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" void sample(void * arg, ulong count) { mp_limb_t n, 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) 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; } flint2-2.8.4/ulong_extras/profile/p-mod2_preinv.c000066400000000000000000000070111414523752600217320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #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 n, d, dinv, r = 0, norm; 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)) abort(); flint_randclear(state); flint_free(arr); } int main(void) { double min1, min2, min3, 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; } flint2-2.8.4/ulong_extras/profile/p-mod_precomp.c000066400000000000000000000027121414523752600220150ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" void sample(void * arg, ulong count) { mp_limb_t n, d, r, norm, 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++) { r = 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; } flint2-2.8.4/ulong_extras/profile/p-mulmod2_preinv.c000066400000000000000000000026541414523752600224600ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" void sample(void * arg, ulong count) { mp_limb_t a, b, d, r, norm, 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++) { r = 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; } flint2-2.8.4/ulong_extras/profile/p-mulmod_precomp.c000066400000000000000000000026631414523752600225400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "profiler.h" #include "flint.h" #include "ulong_extras.h" void sample(void * arg, ulong count) { ulong i; mp_limb_t a, b, d, r; 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++) { r = 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; } flint2-2.8.4/ulong_extras/profile/timings.txt000066400000000000000000000162731414523752600213320ustar00rootroot00000000000000K10-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 flint2-2.8.4/ulong_extras/randbits.c000066400000000000000000000011631414523752600174210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.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)); } flint2-2.8.4/ulong_extras/randint.c000066400000000000000000000022661414523752600172570ustar00rootroot00000000000000/* Copyright (C) 2009 William Hart 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" 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; } } flint2-2.8.4/ulong_extras/randlimb.c000066400000000000000000000020411414523752600173770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #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 flint2-2.8.4/ulong_extras/randprime.c000066400000000000000000000026701414523752600176000ustar00rootroot00000000000000/* Copyright (C) 2007, 2008 William Hart Copyright (C) 2008 Peter Shrimpton Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #define ulong mp_limb_t #include "flint.h" #include "ulong_extras.h" mp_limb_t n_randprime(flint_rand_t state, ulong bits, int proved) { mp_limb_t rand; if (bits < 2) { flint_printf("Exception in n_randprime: attempt to generate prime < 2!\n"); flint_abort(); } if (bits == FLINT_BITS) { do { rand = n_randbits(state, bits); } while (rand >= 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); } flint2-2.8.4/ulong_extras/randtest.c000066400000000000000000000036111414523752600174370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "fmpz.h" #include "ulong_extras.h" 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)<. */ #include #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) { count_trailing_zeros(exp, *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; } flint2-2.8.4/ulong_extras/remove2_precomp.c000066400000000000000000000016151414523752600207210ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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) { count_trailing_zeros(exp, *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; } flint2-2.8.4/ulong_extras/revbin.c000066400000000000000000000061641414523752600171060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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); } } flint2-2.8.4/ulong_extras/root.c000066400000000000000000000127041414523752600166010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #define ulong mp_limb_t #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; } flint2-2.8.4/ulong_extras/root_estimate.c000066400000000000000000000121221414523752600204660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #define ulong mp_limb_t #include "flint.h" #include "ulong_extras.h" #include "longlong.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 */ /* Intead 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; } flint2-2.8.4/ulong_extras/rootrem.c000066400000000000000000000132651414523752600173100ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #define ulong mp_limb_t #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 (!n || !root) return 0; if (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; } flint2-2.8.4/ulong_extras/sizeinbase.c000066400000000000000000000012421414523752600177450ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #define ulong mp_limb_t #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; } flint2-2.8.4/ulong_extras/sqrt.c000066400000000000000000000013231414523752600166020ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #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; } flint2-2.8.4/ulong_extras/sqrtmod.c000066400000000000000000000052011414523752600173010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } 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; } flint2-2.8.4/ulong_extras/sqrtmod_primepow.c000066400000000000000000000172661414523752600212410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #define ulong mp_limb_t #include #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)<. */ #define ulong ulongxx /* interferes with system includes */ #include #include #undef ulong #include #include "flint.h" #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; 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; } flint2-2.8.4/ulong_extras/sqrtrem.c000066400000000000000000000012631414523752600173110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/ulong_extras/test/000077500000000000000000000000001414523752600164255ustar00rootroot00000000000000flint2-2.8.4/ulong_extras/test/t-CRT.c000066400000000000000000000045421414523752600174670ustar00rootroot00000000000000/* Copyright (C) 2020 Daniel Schultz This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { slong i, j; FLINT_TEST_INIT(state); flint_printf("CRT...."); fflush(stdout); 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_add_ui(m1, m1, 1); fmpz_abs(m2, m2); fmpz_add_ui(m2, m2, 1); 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))) { flint_printf("FAIL\n:"); flint_printf("a1: "); fmpz_print(a1); flint_printf("\n"); flint_printf("m1: "); fmpz_print(m1); flint_printf("\n"); flint_printf("a2: "); fmpz_print(a2); flint_printf("\n"); flint_printf("m2: "); fmpz_print(m2); flint_printf("\n"); } } } fmpz_clear(m1); fmpz_clear(m2); fmpz_clear(m1m2); fmpz_clear(a1); fmpz_clear(a2); fmpz_clear(r); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-addmod.c000066400000000000000000000023501414523752600202620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("addmod...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, b = %wu, d = %wu\n", a, b, d); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-cbrt.c000066400000000000000000000071151414523752600177700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cbrt...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } mpz_clear(mpz_n); mpz_clear(mpz_val); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-cbrt_binary_search.c000066400000000000000000000072171414523752600226640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cbrt_binary_search...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } mpz_clear(mpz_n); mpz_clear(mpz_val); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-cbrt_chebyshev_approx.c000066400000000000000000000072351414523752600234240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cbrt_chebyshev_approx...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } mpz_clear(mpz_n); mpz_clear(mpz_val); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-cbrt_newton_iteration.c000066400000000000000000000072351414523752600234430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cbrt_newton_iteration...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, val = %wd, ans = %wu\n", n, val, ans); abort(); } mpz_clear(mpz_n); mpz_clear(mpz_val); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-cbrtrem.c000066400000000000000000000027621414523752600204770ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("cbrtrem...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("Passed Parameters : n = %wu", c); flint_printf("Answer generated : base = %wu remainder = %wu", a, b); flint_printf("Expected answer : base = %wu remainder = %wu", i, j); abort(); } mpz_clear(e); mpz_clear(f); mpz_clear(g); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-clog.c000066400000000000000000000024451414523752600177630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("clog...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", b); flint_printf("x = %wu\n", x); flint_printf("k = %wu\n", k); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/ulong_extras/test/t-clog_2exp.c000066400000000000000000000034731414523752600207230ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { 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}}; FLINT_TEST_INIT(state); flint_printf("clog_2exp...."); fflush(stdout); 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]) { flint_printf("FAIL:\n"); flint_printf("clog_2exp(%wu, %wu) = %wu\n", t[i][0], t[i][1], t[i][2]); flint_printf("but computed %wu\n", r); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/ulong_extras/test/t-compute_primes.c000066400000000000000000000035111414523752600220650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main() { slong i, lim = 1000000; n_primes_t pg; mp_limb_t * ref_primes; double * ref_inverses; FLINT_TEST_INIT(state); flint_printf("compute_primes...."); fflush(stdout); 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]) { flint_printf("FAIL!\n"); flint_printf("n = %wd, p1 = %wu, p2 = %wu\n", n, primes[n], ref_primes[n]); flint_printf("inv1 = %g, inv2 = %g\n", inverses[n], ref_inverses[n]); abort(); } if (n_randint(state, 20) == 0) { n_cleanup_primes(); } } flint_free(ref_primes); flint_free(ref_inverses); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-discrete_log_bsgs.c000066400000000000000000000023471414523752600225210ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i; FLINT_TEST_INIT(state); flint_printf("discrete_log_bsgs...."); fflush(stdout); flint_randinit(state); for (i = 0; i < 1000; i++) { mp_limb_t p, root, b, d, result; double pinv; p = n_randprime(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) { flint_printf("FAIL:\n"); flint_printf("%wu ** (%wu) == %wu != %wu\n", root, d, result, b); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-div2_preinv.c000066400000000000000000000022371414523752600212650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("div2_preinv...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, d = %wu, dinv = %wu\n", n, d, dinv); flint_printf("q1 = %wu, q2 = %wu\n", q1, q2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-divides.c000066400000000000000000000036031414523752600204630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divides...."); fflush(stdout); /* test random values */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, p, q; int flag; int nbits = n_randint(state, FLINT_BITS + 1); int pbits = 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))); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wu, p = %wu, q = %wu\n", n, p, q); abort(); } } /* test known divisible values */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n, p, q, s; int flag; int pbits = n_randint(state, FLINT_BITS + 1); 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, p = %wu, q = %wu\n", n, p, q); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-divrem2_precomp.c000066400000000000000000000024501414523752600221300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int result; ulong i; FLINT_TEST_INIT(state); flint_printf("divrem2_precomp...."); fflush(stdout); for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t d, n, r1, r2, q1, q2; double dpre; d = n_randtest(state); if (d == UWORD(0)) d++; 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, d = %wu, dpre = %f\n", n, d, dpre); flint_printf("q1 = %wu, q2 = %wu, r1 = %wu, r2 = %wu\n", q1, q2, r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-divrem2_preinv.c000066400000000000000000000024141414523752600217660ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("divrem2_preinv...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, d = %wu, dinv = %wu\n", n, d, dinv); flint_printf("q1 = %wu, q2 = %wu\n", q1, q2); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-euler_phi.c000066400000000000000000000017551414523752600210160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int n, k, t; FLINT_TEST_INIT(state); flint_printf("euler_phi...."); fflush(stdout); for (n = 0; n < 20 * flint_test_multiplier(); n++) { t = 0; for (k = 1; k <= n; k++) t += (n_gcd(n, k) == 1); if (t != n_euler_phi(n)) { flint_printf("FAIL:\n"); flint_printf("phi(%d) = %d, got %wu\n", n, t, n_euler_phi(n)); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factor.c000066400000000000000000000033641414523752600203160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("factor...."); fflush(stdout); /* Test random numbers */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t n1, n2; n_factor_t factors; n_factor_init(&factors); n1 = n_randtest_not_zero(state); 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) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, n2 = %wu\n", n1, n2); abort(); } } { mp_limb_t n1, n2; n_factor_t factors; n_factor_init(&factors); n1 = UWORD(4253857039); 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) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, n2 = %wu\n", n1, n2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factor_SQUFOF.c000066400000000000000000000027241414523752600214000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; ulong count = UWORD(0); FLINT_TEST_INIT(state); flint_printf("factor_SQUFOF...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, n2 = %wu\n", n1, n2); abort(); } } } if (count < 280 * flint_test_multiplier()) { flint_printf("FAIL:\n"); flint_printf("Only %wu numbers factored\n", count); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factor_ecm.c000066400000000000000000000036161414523752600211420ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j, k, result, fails; mp_limb_t prime1, prime2, prod, f, mod; FLINT_TEST_INIT(state); fails = 0; flint_printf("factor_ecm...."); fflush(stdout); 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)) { flint_printf("WRONG ANSWER from stage %d\n", result); flint_printf("Number : %wu = %wu * %wu\n", prod, prime1, prime2); flint_printf("Factor found : %wu", f); flint_printf("Aborting"); abort(); } } else fails += 1; } } } if (fails > 2*flint_test_multiplier()) { flint_printf("Too many unsuccessful factorizations, %d\n", fails); flint_printf("Aborting\n"); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factor_lehman.c000066400000000000000000000040361414523752600216370ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("factor_lehman...."); fflush(stdout); for (i = 0; i < 1000 * 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 /* cannot compute enough primes */ || (n1 >= UWORD(10000000000000000)) #endif ); n2 = n_factor_lehman(n1); result = ((n1%n2) == UWORD(0) && n1 != n2); if (!result) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, n2 = %wu\n", n1, n2); abort(); } } for (i = 0; i < 100 * flint_test_multiplier(); i++) /* Test random products of two primes */ { mp_limb_t n1, n2, n3, n, limit; #if FLINT64 limit = UWORD(100000000) - UWORD(100); #else limit = UWORD(65535); #endif n1 = n_randtest(state) % (limit + 1); n2 = n_randtest(state) % (limit + 1); n1 = n_nextprime(n1, 1); n2 = n_nextprime(n2, 1); /* test a specific bug */ #if FLINT64 if (i == 0) { n1 = 72528697; n2 = 73339073; } #endif n = n1*n2; n3 = n_factor_lehman(n); result = ((n%n3) == UWORD(0) && n != n3); if (!result) { flint_printf("FAIL:\n"); flint_printf("n = %wd, n3 = %wu\n", n, n3); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factor_one_line.c000066400000000000000000000027751414523752600221730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; ulong count = UWORD(0); FLINT_TEST_INIT(state); flint_printf("factor_one_line...."); fflush(stdout); for (i = 0; i < 500 * flint_test_multiplier(); 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) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, n2 = %wu\n", n1, n2); abort(); } } } if (count < 450 * flint_test_multiplier()) { flint_printf("FAIL:\n"); flint_printf("Only %wu numbers factored\n", count); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factor_partial.c000066400000000000000000000024761414523752600220350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("factor_partial...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, n2 = %wu\n", n1, n2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factor_pollard_brent.c000066400000000000000000000036561414523752600232310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { mp_limb_t prime1, prime2, primeprod, fac, modval; int i, j, k, l, fails; FLINT_TEST_INIT(state); fails = 0; flint_printf("factor_pollard_brent...."); fflush(stdout); 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) { flint_printf("FAIL : Wrong factor calculated\n"); flint_printf("n : %wu\n", primeprod); flint_printf("Factor calculated: %wn\n", fac); abort(); } } } } } #if FLINT64 if (fails > flint_test_multiplier()) #else if (fails > 2 * flint_test_multiplier()) #endif { printf("FAIL : Pollard Rho - Brent failed too many times (%d times)\n", fails); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factor_power235.c000066400000000000000000000051121414523752600217550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("factor_power235...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test random squares */ { mp_limb_t factor, exp, n1, n2, bits; bits = n_randint(state, FLINT_BITS/2) + 1; n1 = n_randtest_bits(state, bits); factor = n_factor_power235(&exp, n1*n1); n2 = n_pow(factor, exp); result = (n1*n1 == n2); if (!result) { flint_printf("FAIL:\n"); flint_printf("factor = %wu, exp = %wu\n", factor, exp); abort(); } } for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test random cubes */ { mp_limb_t factor, exp, n1, n2, bits; bits = n_randint(state, FLINT_BITS/3) + 1; n1 = n_randtest_bits(state, bits); factor = n_factor_power235(&exp, n1*n1*n1); n2 = n_pow(factor, exp); result = (n1*n1*n1 == n2); if (!result) { flint_printf("FAIL:\n"); flint_printf("factor = %wu, exp = %wu\n", factor, exp); abort(); } } for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test random fifth powers */ { mp_limb_t factor, exp, n1, n2, bits; bits = n_randint(state, FLINT_BITS/5) + 1; n1 = n_randtest_bits(state, bits); factor = n_factor_power235(&exp, n1*n1*n1*n1*n1); n2 = n_pow(factor, exp); result = (n1*n1*n1*n1*n1 == n2); if (!result) { flint_printf("FAIL:\n"); flint_printf("factor = %wu, exp = %wu\n", factor, exp); abort(); } } for (i = 0; i < 1000 * flint_test_multiplier(); i++) /* Test non 235-powers */ { mp_limb_t exp, n1; do { n1 = n_randtest(state); } while (n_is_perfect_power235(n1)); result = (!n_factor_power235(&exp, n1)); if (!result) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, exp = %wu\n", n1, exp); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factor_pp1.c000066400000000000000000000030041414523752600210650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j, result; ulong count = UWORD(0); FLINT_TEST_INIT(state); flint_printf("factor_pp1...."); fflush(stdout); 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))); 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) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, n2 = %wu\n", n1, n2); abort(); } } } if (count < 295 * flint_test_multiplier()) { flint_printf("FAIL:\n"); flint_printf("Only %wu numbers factored\n", count); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factor_trial.c000066400000000000000000000023351414523752600215060ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("factor_trial...."); fflush(stdout); 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(&factors, n1, UWORD(10000)); for (j = 0; j < factors.num; j++) { n2 *= n_pow(factors.p[j], factors.exp[j]); } result = (n1 == n2); if (!result) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, n2 = %wu\n", n1, n2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factor_trial_partial.c000066400000000000000000000027061414523752600232240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("factor_trial_partial...."); fflush(stdout); 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_trial_partial(&factors, n1, &prod, UWORD(10000), limit); if (n1 != n2*prod) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, n2 = %wu, prod = %wu\n", n1, n2, prod); abort(); } for (j = 0; j < factors.num; j++) { n2 *= n_pow(factors.p[j], factors.exp[j]); } result = (n1 == n2); if (!result) { flint_printf("FAIL:\n"); flint_printf("n1 = %wu, n2 = %wu\n", n1, n2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factor_trial_range.c000066400000000000000000000023631414523752600226630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j, result; FLINT_TEST_INIT(state); flint_printf("factor_trial_range...."); fflush(stdout); 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) { flint_printf("FAIL\n"); flint_printf("n1 = %wu, n2 = %wu\n", n1, n2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factorial_fast_mod2_preinv.c000066400000000000000000000027211414523752600243210ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" 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; } int main(void) { mp_limb_t n; int j; FLINT_TEST_INIT(state); flint_printf("factorial_fast_mod2_preinv...."); fflush(stdout); for (n = 0; n < 100 * flint_test_multiplier(); n++) { mp_limb_t p, pinv, x, y; for (j = 0; j < 10; 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu\np = %wu\nx = %wu\ny = %wu\n", n, p, x, y); abort(); } } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-factorial_mod2_preinv.c000066400000000000000000000027071414523752600233100ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" 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; } int main(void) { mp_limb_t n; int j; FLINT_TEST_INIT(state); flint_printf("factorial_mod2_preinv...."); fflush(stdout); for (n = 0; n < 100 * flint_test_multiplier(); n++) { mp_limb_t p, pinv, x, y; for (j = 0; j < 10; j++) { 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu\np = %wu\nx = %wu\ny = %wu\n", n, p, x, y); abort(); } } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-flog.c000066400000000000000000000023601414523752600177620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("flog...."); fflush(stdout); 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_flog(a, b); x = n_pow(b, k); result = (x <= a && a / b < x); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", b); flint_printf("x = %wu\n", x); flint_printf("k = %wu\n", k); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/ulong_extras/test/t-gcd.c000066400000000000000000000050241414523752600175700ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd...."); fflush(stdout); /* test gcd(ac, bc) == gcd(a, b) */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong a, b, c, g, 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) { flint_printf("FAIL:\n"); flint_printf("gcd(ac, bc) != gcd(a, b)\n"); flint_printf("a = %wu, b = %wu, c = %wu, g = %wu\n", a, b, c, g); abort(); } } /* test gcd(a, 0) == a */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong a, g; a = n_randtest(state); g = n_gcd(a, 0); result = (g == a); if (!result) { flint_printf("FAIL:\n"); flint_printf("gcd(a, 0) != a\n"); flint_printf("a = %wu\n", a); abort(); } } /* test gcd(0, b) == b */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong b, g; b = n_randtest(state); g = n_gcd(0, b); result = (g == b); if (!result) { flint_printf("FAIL:\n"); flint_printf("gcd(0, b) != b\n"); flint_printf("b = %wu\n", b); abort(); } } /* test gcd(0, 0) == 0 */ { result = (n_gcd(0, 0) == 0); if (!result) { flint_printf("FAIL:\n"); flint_printf("gcd(0, 0) != 0\n"); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-gcd_full.c000066400000000000000000000025031414523752600206110ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcd_full...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { mp_limb_t a, b, c, bits1, bits2, bits3; bits1 = n_randint(state, FLINT_BITS-1) + 1; bits2 = n_randint(state, bits1) + 1; bits3 = n_randint(state, FLINT_BITS - bits1) + 1; do { a = n_randtest_bits(state, bits1); b = n_randtest_bits(state, bits2); } while ((n_gcd_full(a, b) != UWORD(1))); c = n_randtest_bits(state, bits3); result = (n_gcd_full(a*c, b*c) == c); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = %wu, b = %wu, c = %wu\n", a, b, c); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-gcdinv.c000066400000000000000000000060341414523752600203070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("gcdinv...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { 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) { flint_printf("FAIL\n"); flint_printf("Cofactor doesn't agree with n_xgcd\n"); flint_printf("a = %wu, b = %wu, c = %wu\n", a, b, c); flint_printf("g = %wu, g2 = %wu, t = %wd, t2 = %wd\n", g, g2, t, t2); abort(); } /* test b*t2 == 1 mod a */ ainv = n_preinvert_limb(a); s = n_mulmod2_preinv(t2, b, a, ainv); result = (s == 1); if (!result) { flint_printf("FAIL\n"); flint_printf("Incorrect inverse\n"); flint_printf("a = %wu, b = %wu, c = %wu\n", a, b, c); flint_printf("g2 = %wu, s = %wd, t2 = %wd\n", g2, s, t2); abort(); } } /* test modulo 1 */ { ulong s, g; g = n_gcdinv(&s, 0, 1); result = (g == 1 && s == 0); if (!result) { flint_printf("FAIL\n"); flint_printf("Incorrect modulo 1\n"); flint_printf("g = %wu, s = %wu\n", g, s); abort(); } } /* check gcd not 1 when a = 0 (and b != 1) */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong b, s, g; b = n_randtest_not_zero(state); g = n_gcdinv(&s, 0, b); result = (g != 1 || b == 1); if (!result) { flint_printf("FAIL\n"); flint_printf("gcd(0, b) == 1\n"); flint_printf("b = %wu, s = %wu\n", b, s); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-invmod.c000066400000000000000000000024261414523752600203320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("invmod...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) { mp_limb_t 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, b = %wu, r = %wd\n", a, b, r); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_oddprime_binary.c000066400000000000000000000036151414523752600227010ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; slong cutoff = 100000; FLINT_TEST_INIT(state); flint_printf("is_oddprime_binary...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that primes pass the test */ { mp_limb_t d; mpz_t d_m; mpz_init(d_m); do { d = n_randint(state, cutoff) | 1; if (d == UWORD(1)) d += 16; /* algorithm requires d >= 17 */ flint_mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = flint_mpz_get_ui(d_m); } while (d > cutoff); result = n_is_oddprime_binary(d); if (!result) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared composite\n", d); abort(); } mpz_clear(d_m); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that not too many composites pass */ { mp_limb_t d; mpz_t d_m; mpz_init(d_m); do { d = (n_randint(state, cutoff) + 16) | 1; flint_mpz_set_ui(d_m, d); } while ((mpz_probab_prime_p(d_m, 12)) || (d > cutoff)); result = !n_is_oddprime_binary(d); if (!result) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared prime\n", d); abort(); } mpz_clear(d_m); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_oddprime_small.c000066400000000000000000000035631414523752600225270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_oddprime_small...."); fflush(stdout); for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that primes pass the test */ { mp_limb_t d; mpz_t d_m; mpz_init(d_m); do { d = n_randint(state, FLINT_ODDPRIME_SMALL_CUTOFF) | 1; flint_mpz_set_ui(d_m, d); mpz_nextprime(d_m, d_m); d = flint_mpz_get_ui(d_m); } while (d > FLINT_ODDPRIME_SMALL_CUTOFF); result = n_is_oddprime_small(d); if (!result) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared composite\n", d); abort(); } mpz_clear(d_m); } for (i = 0; i < 10000 * flint_test_multiplier(); i++) /* Test that not too many composites pass */ { mp_limb_t d; mpz_t d_m; mpz_init(d_m); do { d = n_randint(state, FLINT_ODDPRIME_SMALL_CUTOFF) | 1; flint_mpz_set_ui(d_m, d); } while ((mpz_probab_prime_p(d_m, 12)) || (d > FLINT_ODDPRIME_SMALL_CUTOFF)); result = !n_is_oddprime_small(d); if (!result) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared prime\n", d); abort(); } mpz_clear(d_m); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_perfect_power.c000066400000000000000000000066711414523752600224030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; ulong bits, root, hi, n; mp_limb_t d; FLINT_TEST_INIT(state); flint_printf("is_perfect_power...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("d^2 = %wu is declared not a perfect power\n", d*d); abort(); } if (n_pow(root, result) != n_pow(d, 2)) { flint_printf("FAIL:\n"); flint_printf("%wu^%wu != %wu\n", root, result, d*d); abort(); } } 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) { flint_printf("FAIL:\n"); flint_printf("d^3 = %wu is declared not a perfect power\n", d*d*d); abort(); } if (n_pow(root, result) != n_pow(d, 3)) { flint_printf("FAIL:\n"); flint_printf("%wu^%wu != %wu\n", root, result, d*d*d); abort(); } } 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) { flint_printf("FAIL:\n"); flint_printf("d^5 = %wu is declared not a perfect power\n", d*d*d*d*d); abort(); } if (n_pow(root, result) != n_pow(d, 5)) { flint_printf("FAIL:\n"); flint_printf("%wu^%wu != %wu\n", root, result, d*d*d*d*d); abort(); } } /* 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) { flint_printf("FAIL:\n"); flint_printf("%wu^%wu != %wu\n", root, result, n); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared a perfect power\n", d); abort(); } mpz_clear(d_m); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_perfect_power235.c000066400000000000000000000047061414523752600226320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; ulong bits; mp_limb_t d; FLINT_TEST_INIT(state); flint_printf("is_perfect_power235...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("d^2 = %wu is declared not a perfect power\n", d*d); abort(); } } 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) { flint_printf("FAIL:\n"); flint_printf("d^3 = %wu is declared not a perfect power\n", d*d*d); abort(); } } 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) { flint_printf("FAIL:\n"); flint_printf("d^5 = %wu is declared not a perfect power\n", d*d*d*d*d); abort(); } } 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("FAIL:\n"); flint_printf("d = %wu is declared a perfect power\n", d); abort(); } mpz_clear(d_m); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_prime.c000066400000000000000000000132221414523752600206410ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.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 int main(void) { int i, result; mp_limb_t d; mpz_t d_m; slong pow; ulong bits; FLINT_TEST_INIT(state); flint_printf("is_prime...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared composite\n", d); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared prime\n", d); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("Perfect power d = %wu is declared prime\n", d); abort(); } } #if FLINT64 for (i = 0; i < sizeof(composites) / sizeof(mp_limb_t); i++) { d = composites[i]; result = !n_is_prime(d); if (!result) { flint_printf("FAIL:\n"); flint_printf("Known composite d = %wu is declared prime\n", d); abort(); } } #endif FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_prime_pocklington.c000066400000000000000000000037731414523752600232620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; ulong count = 0; mp_limb_t d; mpz_t d_m; FLINT_TEST_INIT(state); flint_printf("is_prime_pocklington...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared composite\n", d); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared prime\n", d); abort(); } mpz_clear(d_m); } if (count > 200 * flint_test_multiplier()) { flint_printf("FAIL: Pocklington-Lehmer failed too many times (%wu times)\n", count); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_prime_pseudosquare.c000066400000000000000000000033611414523752600234440ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; mp_limb_t d; mpz_t d_m; FLINT_TEST_INIT(state); flint_printf("is_prime_pseudosquare...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared composite\n", d); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared prime\n", d); abort(); } mpz_clear(d_m); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_probabprime.c000066400000000000000000000050261414523752600220320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; mp_limb_t d; mpz_t d_m; slong pow; ulong bits; FLINT_TEST_INIT(state); flint_printf("is_probabprime...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared composite\n", d); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared prime\n", d); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("Perfect power d = %wu is declared prime\n", d); abort(); } } /* Regression test, check certain composites do not pass */ #if FLINT64 { d = UWORD(2007193456621); result = !n_is_probabprime(d); if (!result) { flint_printf("FAIL:\n"); flint_printf("Known composite d = %wu is declared prime\n", d); abort(); } } #endif FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_probabprime_BPSW.c000066400000000000000000000033331414523752600226640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; mp_limb_t d; mpz_t d_m; FLINT_TEST_INIT(state); flint_printf("is_probabprime_BPSW...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared composite\n", d); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared prime\n", d); abort(); } mpz_clear(d_m); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_probabprime_fermat.c000066400000000000000000000043111414523752600233640ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; ulong count = UWORD(0); mp_limb_t d, j; mpz_t d_m; FLINT_TEST_INIT(state); flint_printf("is_probabprime_fermat...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared composite\n", d); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("%wu composites declared prime\n", count); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_probabprime_fibonacci.c000066400000000000000000000035321414523752600240270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; ulong count = UWORD(0); mp_limb_t d; mpz_t d_m; FLINT_TEST_INIT(state); flint_printf("is_probabprime_fibonacci...."); fflush(stdout); 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_fibonacci(d); if (!result) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared composite\n", d); abort(); } 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) | 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 * flint_test_multiplier()); if (!result) { flint_printf("FAIL:\n"); flint_printf("%wu composites declared prime\n", count); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_probabprime_lucas.c000066400000000000000000000034571414523752600232270ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; ulong count = UWORD(0); mp_limb_t d; mpz_t d_m; FLINT_TEST_INIT(state); flint_printf("is_probabprime_lucas...."); fflush(stdout); 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_lucas(d); if (!result) { flint_printf("FAIL:\n"); flint_printf("d = %wu is declared composite\n", d); abort(); } 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)); if (n_is_probabprime_lucas(d) == 1) count++; mpz_clear(d_m); } result = (count < 20 * flint_test_multiplier()); if (!result) { flint_printf("FAIL:\n"); flint_printf("%wu composites declared prime\n", count); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_square.c000066400000000000000000000030241414523752600210240ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("is_square...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("s = %wu is declared square\n", s); abort(); } } 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) { flint_printf("FAIL:\n"); flint_printf("s = %wu is declared square\n", s); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_squarefree.c000066400000000000000000000035511414523752600216730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" void check(mp_limb_t n, int s1, int s2) { if (s1 != s2) { flint_printf("FAIL:\n"); flint_printf("%wu: got %d instead of %d\n", n, s1, s2); abort(); } } int main(void) { int s, k; FLINT_TEST_INIT(state); flint_printf("is_squarefree...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("expected %d squarefree numbers <= 10000 (got %d)\n", 6083, s); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_strong_probabprime2_preinv.c000066400000000000000000000050111414523752600250650ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; ulong count = UWORD(0); FLINT_TEST_INIT(state); flint_printf("is_strong_probabprime2_preinv...."); fflush(stdout); for (i = 0; i < 100 * flint_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); count_trailing_zeros(norm, d - 1); result = n_is_strong_probabprime2_preinv(d, dinv, a, (d - 1)>>norm); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = %wu, d = %wu\n", a, d); abort(); } } mpz_clear(d_m); } for (i = 0; i < 100 * flint_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); count_trailing_zeros(norm, 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 * flint_test_multiplier()) #else if (count > 432 * flint_test_multiplier()) #endif { flint_printf("FAIL:\n"); flint_printf("count = %wu\n", count); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-is_strong_probabprime_precomp.c000066400000000000000000000050451414523752600251540ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j, result; ulong count = UWORD(0); FLINT_TEST_INIT(state); flint_printf("is_strong_probabprime_precomp...."); fflush(stdout); for (i = 0; i < 100 * flint_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); count_trailing_zeros(norm, d - 1); result = n_is_strong_probabprime_precomp(d, dpre, a, (d - 1)>>norm); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = %wu, d = %wu\n", a, d); abort(); } } mpz_clear(d_m); } for (i = 0; i < 100 * flint_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); count_trailing_zeros(norm, d - 1); result = !n_is_strong_probabprime_precomp(d, dpre, a, (d - 1)>>norm); if (!result) count++; } mpz_clear(d_m); } if (count > 220 * flint_test_multiplier()) { flint_printf("FAIL:\n"); flint_printf("count = %wu\n", count); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-jacobi.c000066400000000000000000000024331414523752600202630ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("jacobi...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, d = %wu\n", a, d); abort(); } mpz_clear(a_m); mpz_clear(d_m); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-ll_mod_preinv.c000066400000000000000000000047321414523752600216710ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "fmpz.h" int main(void) { int i, result; fmpz_t n; FLINT_TEST_INIT(state); flint_printf("ll_mod_preinv...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); flint_printf(" = (m*d + r1) but % d != r1\n"); flint_printf("nh = %wu, nl = %wu, d = %wu, dinv = %wu\n", nh, nl, d, dinv); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } } 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) { flint_printf("FAIL:\n"); flint_printf ("n = but n % d does not agree with fmpz_fdiv_ui\n"); flint_printf("nh = %wu, nl = %wu, d = %wu, dinv = %wu\n", nh, nl, d, dinv); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); fmpz_clear(n); abort(); } } fmpz_clear(n); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-lll_mod_preinv.c000066400000000000000000000026721414523752600220460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("lll_mod_preinv...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); flint_printf("nh = %wu, nm = %wd, nl = %wu, d = %wu, dinv = %wu\n", nh, nm, nl, d, dinv); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-mod2_precomp.c000066400000000000000000000022771414523752600214300ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mod2_precomp...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, d = %wu, dpre = %f\n", n, d, dpre); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-mod2_preinv.c000066400000000000000000000022371414523752600212620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mod2_preinv...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, d = %wu, dinv = %wu\n", n, d, dinv); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-mod_precomp.c000066400000000000000000000026371414523752600213460ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mod_precomp...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, d = %wu, dinv = %g\n", n, d, dpre); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-moebius_mu.c000066400000000000000000000037671414523752600212130ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" void check(mp_limb_t n, int mu1, int mu2) { if (mu1 != mu2) { flint_printf("FAIL:\n"); flint_printf("mu(%wu): %d != %d\n", n, mu1, mu2); abort(); } } int main(void) { int n, k, s; int * mu; FLINT_TEST_INIT(state); flint_printf("moebius_mu...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("expected mu(k), k <= 10000 to sum to %d (got %d)\n", -23, s); abort(); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-mulmod2.c000066400000000000000000000023511414523752600204120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulmod2...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, b = %wu, d = %wu\n", a, b, d); flint_printf("q = %wu, r1 = %wu, r2 = %wu\n", q, r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-mulmod2_preinv.c000066400000000000000000000024441414523752600220000ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulmod2_preinv...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, b = %wu, d = %wu, dinv = %wu\n", a, b, d, dinv); flint_printf("q = %wu, r1 = %wu, r2 = %wu\n", q, r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-mulmod_precomp.c000066400000000000000000000026411414523752600220570ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulmod_precomp...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, b = %wu, d = %wu, dinv = %f\n", a, b, d, dpre); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-mulmod_preinv.c000066400000000000000000000027601414523752600217170ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulmod_preinv...."); fflush(stdout); 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; count_leading_zeros(norm, 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, b = %wu, d = %wu, dinv = %wu\n", a, b, d, dinv); flint_printf("q = %wu, r1 = %wu, r2 = %wu\n", q, r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-mulmod_shoup.c000066400000000000000000000026051414523752600215500ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulmod_shoup...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, b = %wu, d = %wu, w_pr = %wu\n", a, b, d, w_pr); flint_printf("q = %wu, r1 = %wu, r2 = %wu\n", q, r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-n_urandint.c000066400000000000000000000061741414523752600212030ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { ulong limit, rand_num; slong deviation; int i, j, result; int * count; int * count_in_subrange; FLINT_TEST_INIT(state); flint_printf("n_urandint...."); fflush(stdout); /* 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 * flint_test_multiplier(); i++) { rand_num = n_urandint(state, limit); count[rand_num]++; } result = 1; for (i = 0; i < limit; i++) { deviation = count[i] - (1000 * flint_test_multiplier())/limit; if (deviation >= WORD(100) * flint_test_multiplier() || deviation <= WORD(-100) * flint_test_multiplier()) { result = 0; break; } } if (!result) { flint_printf("FAIL:\n"); flint_printf("limit = %wu, deviation = %wd\n", limit, deviation); flint_free(count); abort(); } } 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 * flint_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 * flint_test_multiplier()) >> 2); if (deviation >= WORD(100) * flint_test_multiplier() || deviation <= WORD(-100) * flint_test_multiplier()) { result = 0; break; } } if (!result) { flint_printf("FAIL:\n"); flint_printf("limit = %wu, deviation = %wd\n", limit, deviation); flint_free(count_in_subrange); abort(); } } flint_free(count_in_subrange); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-nextprime.c000066400000000000000000000041251414523752600210470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { mp_limb_t n; mp_limb_t res1, res2; slong rep; mpz_t mpz_n; FLINT_TEST_INIT(state); flint_printf("nextprime...."); fflush(stdout); if (n_nextprime(0, 0) != 2) { flint_printf("FAIL: expected n_nextprime(0) = 2"); abort(); } if (n_nextprime(UWORD_MAX_PRIME - 1, 0) != UWORD_MAX_PRIME) { flint_printf("FAIL: expected n_nextprime(UWORD_MAX_PRIME-1) = UWORD_MAX_PRIME"); abort(); } 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 #include #include "flint.h" #include "ulong_extras.h" void check(ulong n, mp_limb_t ans) { 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) return; flint_printf("FAIL:\n"); flint_printf("n = %wu: %wu < %wu < %wu\n", n, lo, ans, hi); abort(); } int main(void) { int n; FLINT_TEST_INIT(state); flint_printf("nth_prime_bounds...."); fflush(stdout); for (n=6; n<7500 * FLINT_MIN(10, flint_test_multiplier()); n++) { check(n, n_nth_prime(n)); } /* Some known large primes */ check(UWORD(10), UWORD(29)); check(UWORD(100), UWORD(541)); check(UWORD(1000), UWORD(7919)); check(UWORD(10000), UWORD(104729)); check(UWORD(100000), UWORD(1299709)); check(UWORD(1000000), UWORD(15485863)); check(UWORD(10000000), UWORD(179424673)); check(UWORD(100000000), UWORD(2038074743)); #if FLINT64 check(UWORD(1000000000), UWORD(22801763489)); check(UWORD(10000000000), UWORD(252097800623)); check(UWORD(100000000000), UWORD(2760727302517)); check(UWORD(1000000000000), UWORD(29996224275833)); check(UWORD(10000000000000), UWORD(323780508946331)); check(UWORD(100000000000000), UWORD(3475385758524527)); check(UWORD(1000000000000000), UWORD(37124508045065437)); check(UWORD(10000000000000000), UWORD(394906913903735329)); check(UWORD(100000000000000000), UWORD(4185296581467695669)); #endif FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-pow.c000066400000000000000000000026121414523752600176400ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("pow...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, exp1 = %wu, exp2 = %wu, r1 = %wu, r2 = %wu\n", n, exp1, exp2, r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-powmod.c000066400000000000000000000042441414523752600203430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, exp = %wd, d = %wu\n", a, exp, d); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("0^0 != 1 mod %wd\n", d); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-powmod2.c000066400000000000000000000047161414523752600204310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod2...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, exp = %wd, d = %wu\n", a, exp, d); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("0^0 != 1 mod %wd\n", d); abort(); } } /* 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) { flint_printf("FAIL:\n"); flint_printf("0^%wd != 0 mod 1\n", exp); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-powmod2_preinv.c000066400000000000000000000052061414523752600220070ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" #include "long_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod2_preinv...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, exp = %wd, d = %wu, dinv = %wu\n", a, exp, d, dinv); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("0^0 != 1 mod %wd\n", d); abort(); } } /* 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) { flint_printf("FAIL:\n"); flint_printf("0^%wd != 0 mod 1\n", exp); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-powmod2_ui_preinv.c000066400000000000000000000046631414523752600225120ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod2_ui_preinv...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, exp = %wu, d = %wu\n", a, exp, d); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("0^0 != 1 mod %wd\n", d); abort(); } } /* 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) { flint_printf("FAIL:\n"); flint_printf("0^%wd != 0 mod 1\n", exp); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-powmod_precomp.c000066400000000000000000000044711414523752600220720ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_precomp...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, exp = %wd, d = %wu\n", a, exp, d); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("0^0 != 1 mod %wd\n", d); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-powmod_ui_precomp.c000066400000000000000000000042551414523752600225670ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_ui_precomp...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, exp = %wd, d = %wu\n", a, exp, d); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("0^0 != 1 mod %wd\n", d); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-powmod_ui_preinv.c000066400000000000000000000053211414523752600224200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("powmod_ui_preinv...."); fflush(stdout); 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); count_leading_zeros(norm, 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, exp = %wu, d = %wu\n", a, exp, d); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } 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); count_leading_zeros(norm, 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) { flint_printf("FAIL:\n"); flint_printf("0^0 != 1 mod %wd\n", d); abort(); } } /* check 0^exp = 0 mod 1 */ for (i = 0; i < 10000 * flint_test_multiplier(); i++) { ulong r, dinv, norm, exp; exp = n_randtest(state); count_leading_zeros(norm, 1); dinv = n_preinvert_limb(1); r = n_powmod_ui_preinv(0, exp, UWORD(1) << norm, dinv, norm) >> norm; result = (r == 0); if (!result) { flint_printf("FAIL:\n"); flint_printf("0^%wd != 0 mod 1\n", exp); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-prime_pi.c000066400000000000000000000023141414523752600206360ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int n; FLINT_TEST_INIT(state); flint_printf("prime_pi...."); fflush(stdout); 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)) { flint_printf("FAIL:\n"); flint_printf("expected pi(%d) + 1 = pi(%d)\n", n-1, n); abort(); } } for (n=1; n<5000 * FLINT_MIN(10, flint_test_multiplier()); n++) { if (n_prime_pi(n_nth_prime(n)) != n) { flint_printf("FAIL:\n"); flint_printf("expected pi(prime(%d)) = %d\n", n, n); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-prime_pi_bounds.c000066400000000000000000000036541414523752600222200ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" void check(mp_limb_t n, ulong ans) { 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) return; flint_printf("FAIL:\n"); flint_printf("n = %wu: %wu < %wu < %wu\n", n, lo, ans, hi); abort(); } int main(void) { int n; FLINT_TEST_INIT(state); flint_printf("prime_pi_bounds...."); fflush(stdout); for (n=17; n<10000 * FLINT_MIN(10, flint_test_multiplier()); n++) { check(n, n_prime_pi(n)); } check(UWORD(10), UWORD(4)); check(UWORD(100), UWORD(25)); check(UWORD(1000), UWORD(168)); check(UWORD(10000), UWORD(1229)); check(UWORD(100000), UWORD(9592)); check(UWORD(1000000), UWORD(78498)); check(UWORD(10000000), UWORD(664579)); check(UWORD(100000000), UWORD(5761455)); check(UWORD(1000000000), UWORD(50847534)); #if FLINT64 check(UWORD(10000000000), UWORD(455052511)); check(UWORD(100000000000), UWORD(4118054813)); check(UWORD(1000000000000), UWORD(37607912018)); check(UWORD(10000000000000), UWORD(346065536839)); check(UWORD(100000000000000), UWORD(3204941750802)); check(UWORD(1000000000000000), UWORD(29844570422669)); check(UWORD(10000000000000000), UWORD(279238341033925)); check(UWORD(100000000000000000), UWORD(2623557157654233)); #endif FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-primes.c000066400000000000000000000034351414523752600203360ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { slong n; FLINT_TEST_INIT(state); flint_printf("primes...."); fflush(stdout); _flint_rand_init_gmp(state); /* 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) { flint_printf("FAIL\n"); flint_printf("i = %wu, p = %wu, q = %wu\n", i, p, q); abort(); } } 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]) { flint_printf("FAIL\n"); flint_printf("pi(10^%wd) = %u, computed = %wu\n", n, primepi[n], s); abort(); } n_primes_clear(iter); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-primes_jump_after.c000066400000000000000000000025151414523752600225500ustar00rootroot00000000000000/* Copyright (C) 2012 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { slong j, k, l; FLINT_TEST_INIT(state); flint_printf("primes_jump_after...."); fflush(stdout); 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) { flint_printf("FAIL\n"); flint_printf("p = %wu, q = %wu\n", p, q); abort(); } } } n_primes_clear(iter); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-primitive_root_prime.c000066400000000000000000000024551414523752600233070ustar00rootroot00000000000000/* Copyright (C) 2013 Mike Hansen This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, j; FLINT_TEST_INIT(state); flint_printf("primitive_root_prime...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("%wu ** (%wu / %wu) == 1 mod %wu\n", root, p-1, factors.p[j], p); abort(); } } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-remove.c000066400000000000000000000053441414523752600203350ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("remove...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, exp1 = %d, exp2 = %d, n1 = %wu, n2 = %wu, p = %d\n", orig_n, exp1, exp2, n1, n2, flint_primes_small[j]); abort(); } } 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) { flint_printf("FAIL\n"); flint_printf("n = %wu, exp1 = %d, exp2 = %d, n1 = %wu, n2 = %wu, p = %d\n", orig_n, exp1, exp2, n1, n2, flint_primes_small[j]); abort(); } } mpz_clear(d_n1); mpz_clear(d_n2); mpz_clear(d_p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-remove2_precomp.c000066400000000000000000000056221414523752600221430ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; const mp_limb_t * primes; const double * inverses; FLINT_TEST_INIT(state); flint_printf("remove2_precomp...."); fflush(stdout); 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) { flint_printf("FAIL\n"); flint_printf("n = %wu, exp1 = %d, exp2 = %d, n1 = %wu, n2 = %wu, p = %d\n", orig_n, exp1, exp2, n1, n2, flint_primes_small[j]); abort(); } } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu, exp1 = %d, exp2 = %d, n1 = %wu, n2 = %wu, p = %d\n", orig_n, exp1, exp2, n1, n2, flint_primes_small[j]); abort(); } } mpz_clear(d_n1); mpz_clear(d_n2); mpz_clear(d_p); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-revbin.c000066400000000000000000000062261414523752600203250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.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; } int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("revbin...."); fflush(stdout); /* 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) { flint_printf("FAIL:\n"); flint_printf("b = %wu\n", b); flint_printf("n = %wx\n", n); flint_printf("r = %wx\n", r); abort(); } } /* 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) { flint_printf("FAIL:\n"); flint_printf("b = %wu\n", b); flint_printf("n = %wx\n", n); flint_printf("d = %wx\n", d); flint_printf("r1 = %wx\n", r1); flint_printf("r2 = %wx\n", r2); abort(); } } } } /* 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) { flint_printf("FAIL:\n"); flint_printf("b = %wu\n", b); flint_printf("n = %wx\n", n); flint_printf("d = %wx\n", d); flint_printf("r1 = %wx\n", r1); flint_printf("r2 = %wx\n", r2); abort(); } } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; } flint2-2.8.4/ulong_extras/test/t-root.c000066400000000000000000000106571414523752600200260ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; mp_limb_t upper_limit; FLINT_TEST_INIT(state); flint_printf("root...."); fflush(stdout); #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) { flint_printf("FAIL:\n"); flint_printf("Passed Parameters : n = %wu root = %wu", c, d); flint_printf("Answer generated : base = %wu", a); flint_printf("Expected answer : base = %wu", val); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("Passed Parameters : n = %wu root = %wu", c, d); printf("\n"); flint_printf("Answer generated : base = %wu", a); printf("\n"); flint_printf("Expected answer : base = %wu", base); abort(); } } /* 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) { flint_printf("FAIL:\n"); flint_printf("Passed Parameters : n = %wu root = %wu", c, d); printf("\n"); flint_printf("Answer generated : base = %wu", a); printf("\n"); flint_printf("Expected answer : base = %wu", base); abort(); } } /* 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) { flint_printf("FAIL:\n"); flint_printf("Passed Parameters : n = %wu root = %wu", c, d); flint_printf("Answer generated : base = %wu", a); flint_printf("Expected answer : base = %wu", val); abort(); } mpz_clear(e); mpz_clear(g); mpz_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-rootrem.c000066400000000000000000000115701414523752600205250ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; mp_limb_t upper_limit; FLINT_TEST_INIT(state); flint_printf("n_rootrem...."); fflush(stdout); #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) { flint_printf("FAIL:\n"); flint_printf("Passed Parameters : n = %wu root = %wu", c, d); flint_printf("Answer generated : base = %wu remainder = %wu", a, b); flint_printf("Expected answer : base = %wu remainder = %wu", val, j); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("Passed Parameters : n = %wu root = %wu", c, d); printf("\n"); flint_printf("Answer generated : base = %wu remainder = %wu", a, b); printf("\n"); flint_printf("Expected answer : base = %wu remainder = 0", base); abort(); } } /* 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) { flint_printf("FAIL:\n"); flint_printf("Passed Parameters : n = %wu root = %wu", c, d); printf("\n"); flint_printf("Answer generated : base = %wu remainder = %wu", a, b); printf("\n"); flint_printf("Expected answer : base = %wu remainder = 1", base); abort(); } } /* 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) { flint_printf("FAIL:\n"); flint_printf("Passed Parameters : n = %wu root = %wu", c, d); flint_printf("Answer generated : base = %wu remainder = %wu", a, b); flint_printf("Expected answer : base = %wu remainder = %wu", val, j); abort(); } mpz_clear(e); mpz_clear(f); mpz_clear(g); mpz_clear(h); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-sizeinbase.c000066400000000000000000000025631414523752600211740ustar00rootroot00000000000000/* Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { mp_limb_t n; int base, size1, size2; slong rep; mpz_t t; char * str; FLINT_TEST_INIT(state); flint_printf("sizeinbase...."); fflush(stdout); 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) { flint_printf("FAIL: n = %wu, base = %d\n", n, base); flint_printf("n_sizeinbase: %d, strlen: %d\n", size1, size2); abort(); } } flint_free(str); mpz_clear(t); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-sqrt.c000066400000000000000000000035631414523752600200320ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrt...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, s1 = %wd, s2 = %wu\n", a, s1, s2); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, s1 = %wd, s2 = %wu\n", a, s1, s2); abort(); } mpz_clear(a_m); mpz_clear(s2_m); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-sqrtmod.c000066400000000000000000000035531414523752600205310ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrtmod...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("p = %wu\n", p); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", b); abort(); } } 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) { flint_printf("FAIL:\n"); flint_printf("p = %wu\n", p); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", b); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-sqrtmod_primepow.c000066400000000000000000000122671414523752600224550ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrtmod_primepow...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("p = %wu\n", p); flint_printf("exp = %wd\n", exp); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", b); flint_printf("num = %wd\n", num); if (!btest) flint_printf("Square root not found.\n"); if (i != num) flint_printf("%wu not a square root of %wu mod %wu\n", sqrt[i], a, pow); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("p = %wu\n", p); flint_printf("exp = %wd\n", exp); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", b); flint_printf("num = %wd\n", num); if (!btest) flint_printf("Square root not found.\n"); if (i != num) flint_printf("%wu not a square root of %wu mod %wu\n", sqrt[i], a, pow); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("%wu^2 is not %wu mod %wu\n", sqrt[0], a, pow); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("p = %wu\n", p); flint_printf("exp = %wd\n", exp); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", b); abort(); } flint_free(sqrt); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-sqrtmodn.c000066400000000000000000000063771414523752600207160ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrtmodn...."); fflush(stdout); 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) + 2; n = n_randtest_bits(state, bits); if (n == 0) n = 1; 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu\n", n); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", b); flint_printf("num = %wd\n", num); if (!btest) flint_printf("Square root not found.\n"); if (i != num) flint_printf("%wu not a square root of %wu mod %wu\n", sqrt[i], a, n); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("%wu^2 is not %wu mod %wu\n", sqrt[0], a, n); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("n = %wu\n", n); flint_printf("a = %wu\n", a); flint_printf("b = %wu\n", b); abort(); } flint_free(sqrt); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-sqrtrem.c000066400000000000000000000042541414523752600205340ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("sqrtrem...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, r1 = %wd, r2 = %wu, s1 = %wd, s2 = %wu\n", a, r1, r2, s1, s2); abort(); } 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, r1 = %wd, r2 = %wu, s1 = %wd, s2 = %wu\n", a, r1, r2, s1, s2); abort(); } mpz_clear(a_m); mpz_clear(r2_m); mpz_clear(s2_m); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-submod.c000066400000000000000000000024301414523752600203220ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("submod...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("a = %wu, b = %wu, d = %wu\n", a, b, d); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/test/t-xgcd.c000066400000000000000000000061601414523752600177620ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #include #include #include "flint.h" #include "ulong_extras.h" int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("xgcd...."); fflush(stdout); 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) { flint_printf("FAIL:\n"); flint_printf("s >= b*c\n"); flint_printf ("a = %wu, b = %wu, c = %wu, g = %wu, s = %wu, t = %wu\n", a, b, c, g, s, t); abort(); } result = (t <= a * c || a * c == 0); if (!result) { flint_printf("FAIL:\n"); flint_printf("t >= a*c\n"); flint_printf ("a = %wu, b = %wu, c = %wu, g = %wu, s = %wu, t = %wu\n", a, b, c, g, s, t); abort(); } result = (g == c && ph == UWORD(0) && pl == c); if (!result) { flint_printf("FAIL:\n"); flint_printf("g != c or s*ac + t*bc != c\n"); flint_printf ("a = %wu, b = %wu, c = %wu, g = %wu, s = %wu, t = %wu\n", a, b, c, g, s, t); abort(); } } /* a = 0, b = 0 */ { ulong g, s, t; g = n_xgcd(&s, &t, 0, 0); result = (g == 0 && s == 1 && t == 0); if (!result) { flint_printf("FAIL:\n"); flint_printf("Case a = 0, b = 0\n"); flint_printf("g = %wu, s = %wu, t = %wu\n", g, s, t); abort(); } } /* 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) { flint_printf("FAIL:\n"); flint_printf("Case a = 0\n"); flint_printf("a = %wu, g = %wu, s = %wu, t = %wu\n", a, g, s, t); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; } flint2-2.8.4/ulong_extras/xgcd.c000066400000000000000000000063721414523752600165470ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include #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; } flint2-2.8.4/version.c000066400000000000000000000006641414523752600145730ustar00rootroot00000000000000/* 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 2.1 of the License, or (at your option) any later version. See . */ #include "flint.h" char flint_version[]=FLINT_VERSION;